python网络编程1
socket编程
一、server端和client端通过套接字互相通信(基于TCP)
1.对于服务器端的整个流程:
1.先创建套接字:sk = socket.socket()
2.设定ip和port,将套接字绑定在(ip,port)上:sk.bind((ip,port))
3.进行监听,并设定处理队列中最大的处理连接数:sk.listen(5)
4.进入while死循环
1.等待客户端连接服务器端的套接字并返回与客户端连接的套接字conn和ip+port
2.然后从调用conn.recv(1024)方法,通过套接字conn中接收数据并打印,1次性最大接收1024字节
3.调用conn.sendall(****)方法,通过套接字conn向客户端发送数据
4.调用conn.close()方法,关闭套接字
#!/usr/bin/env python # -*- coding:utf-8 -*- import socket #定义主机的地址和端口号 ip_port = ('127.0.0.1',999) #创建socket对象sk sk =socket.socket() #将socket绑定到127.0.0.1主机的999端口上 sk.bind(ip_port) #将此连接套接字接口变成被连接套接字接口,即将此进程设置为服务器进程,可以接受其他请求。 # 5表示已完成服务器连接但服务器未处理的最大进程数量,即等候处理的连接 sk.listen(5) #设定死循环 while True: print "plz waiting...." #调用套接字的accept函数接受客户端的主动连接,并返回2个信息: # 1.连接至服务器的客户端的套接字conn # 2.连接至服务器端的客户端的ip+port,并以元组的形式返回出来 conn,addr = sk.accept() print addr #从客户端套接字接收数据,并且每次只能接收最大1024字节 get_data = conn.recv(1024) print get_data #通过客户端套接字向客户端发送数据 conn.send("this is server,hello client") #关闭套接字 conn.close()
2.客户端连接的整个流程
1.创建套接字对象
2.设置要连接的服务器端的ip和端口port,并调用sk.connect((ip,port))方法进行连接服务器
3.分别调用sendall()方法和recv()方法进行发送和接收数据
4.关闭套接字
import socket #设定要连接的服务器的端口和IP ip_port = ('127.0.0.1',999) #创建socket对象sk sk = socket.socket() #调用sk.connect(ip_port)连接服务器端 sk.connect(ip_port) #调用sk.sendall()方法向服务器端发送信息 sk.sendall('this is client,hello server') #调用sk.recv(1024)方法接收服务器端发来的信息 server_reply = sk.recv(1024) print server_reply #关闭套接字 sk.close()
二、server端的WEB服务的代码(基于TCP)
server.py
#定义处理请求的函数,传入客户端的套接字 def handle_request(client): get_data = client.recv(1024) client.send("jachy") client.send("HTTP/1.1 200 OK\r\n\r\n") #定义主函数,用于服务器端的套接字的创建、监听、以及阻塞 def main(): import socket sk = socket.socket() ip_port = ('localhost',999) sk.bind(ip_port) sk.listen(5) while True: conn,addr = sk.accept()
#传入监听得到的套接字conn,然后传入请求处理函数,进行对请求进行处理 handle_request(conn) conn.close() if __name__ == "__main__": main()
三、server端和client端通过套接字互相通信(基于UDP通信)
流程:
服务器端:
1.创建基于UDP通信的套接字sk
2.将套件字绑定在特定端口和IP上,调用sk.bind((ip,port)) 【不用像tcp通信一样进行监听,即调用sk.listen(5)】
3.创建while死循环,等待接收客户端发送的数据,直接调用sk.recv(1024)
4.关闭套接字
客户端:
1.创建基于UDP的套接字对象
2.向特定套接字发送数据,调用sk.sendto('数据',套接字)
3.关闭套接字
1.客户端的代码:client.py
import socket ip_port = ('127.0.0.1',999) sk = socket.socket(socket.AF_INET,socket.SOCK_DGRAM,0) while True: inp = raw_input("data:").strip() if inp == 'exit': break sk.sendto(inp,ip_port) sk.close()
2.服务器端的代码
import socket
sk = socket.socket(socket.AF_INET,socket.SOCK_DGRAM,0)
ip_port = ('127.0.0.1',999)
sk.bind(ip_port)
#sk.listen(5) #UDP不用监听套接字,否则会出错
while True:
data = sk.recv(1024)
print data
简版机器人示例
服务器端:对客户端发过来的信息进行判断,然后对不同的信息采取不同的处理方式
import socket ip_port = ('127.0.0.1',1111) sk = socket.socket() sk.bind(ip_port) sk.listen(5) while True: conn,addr = sk.accept() conn.sendall('welcome to phone,0 to man ') Flag = True while Flag: print 'plz waiting.....' data = conn.recv(1024) if data == 'exit': Flag = False elif data == '0': conn.sendall('connect from man') else: conn.sendall('plz input again:') conn.close()
客户端:(在客户端对输入的内容进行判断,当输入的是exit时,就自动关闭套接字连接)
import socket ip_port = ('127.0.0.1',1111) sk = socket.socket() sk.connect(ip_port) sk.settimeout(5) while True: data = sk.recv(1024) print "receieve :",data inp = raw_input("plz input :").strip() sk.sendall(inp) if inp == "exit": break sk.close()
四、基于SocketServer多线程处理并发
server.py
import SocketServer
#定义MyServer类,继承BaseRequestHandler类,请求处理 class MyServer(SocketServer.BaseRequestHandler): #定义处理对象函数 def handle(self): #得到客户端的套接字conn conn = self.request #向客户端套接字发送信息 conn.sendall("welcome to phone 10086,0 to man ,1 to work") #设定标志位,为当收到exit信息时,跳出循环做准备 Flag = True while Flag: data = conn.recv(1024) if data == "exit": Flag = False elif data == "0": conn.sendall("connect to people") else: conn.sendall("plz input again:") if __name__ == "__main__": ip_port = ('127.0.0.1',8009) #传入特定地址的套接字和处理方法,创建多线程处理服务器对象 server = SocketServer.ThreadingTCPServer(ip_port,MyServer) #调用对象的serve_forever方法 server.serve_forever()
client.py
import socket sk = socket.socket() ip_port = ('127.0.0.1',8009) sk.connect(ip_port) #设置阻塞模式下socket的超时时间为5s,socket的后续操作若在给定超时时间内没完成,将触发timeout异常 sk.settimeout(5) while True: get_data = sk.recv(1024) print "get data %s" %get_data inp = raw_input("plz input:").strip() sk.sendall(inp) if inp == "exit": break sk.close()
观察效果方法:
1.运行server.py,让server处于监听状态
2.运行多个client.py,使得多个客户端去连接服务器,即让服务器处理多个客户端的请求
五、基于socket、threading、select模块实现并发、多线程处理多个连接请求
select--用于异步阻塞,实现非阻塞I/O
threading---用于多线程处理请求
import socket import threading import select def process(request,client_address): print request,client_addr conn = request conn.sendall("welcome to phone 10086") flag = True while flag: data = conn.recv(1024) if data == "exit": flag = False elif data == "0": conn.sendall("connect to man service") else: conn.sendall("plz input again") sk = socket.socket(socket.AF_INET,socket.SOCK_STREAM) ip_port = ('127.0.0.1',8002) sk.bind(ip_port) sk.listen(5) while True: #select模块以列表的形式接收4个参数: #1.需要监控的可读文件(套接字)对象,list类型 #2.可写文件文件对象,list类型 #3.产生异常的文件对象,list类型 #4.超时设置
返回3个对象:
#1.读事件,list类型
#2、写事件,list类型
#3、异常对象,list类型
rs, ws,es =select.select([sk,],[],[],1) print "looping" #判断sk是否是本机上用于监听的socket if sk in rs: print 'get request' request和client_addr分别是接收到的socket对象和地址+端口 request,client_addr = sk.accept() #创建线程对象,接收处理线程处理函数,参数是端口+ip t = threading.Thread(target=process,args=(request,client_addr)) t.daemon = False #开始线程活动 t.start() sk.close()