前言:网络编程主要分成udp和tcp两种,udp不需要创建连接,所以传输速度快,但不稳健,tcp需要创建连接,所以传输速度慢,但稳健,现在,大多数应用都采用tcp来进行通信。
一、UDP
1.send端
1)导包 from socket import *
2)创建udpSocket对象,udpSocket = socket(AF_INET,SOCK_DGREAM)
3)调用对象发送消息,udpSocket.sendto("hello,udp,我来了".encode("utf-8"),("你要发送的那台机器的ip地址",端口))
4)关闭udpSocket对象,udpSocket.close()
2.recive端
1)导包 from socket import *
2)创建udpSocket对象,udpSocket = socket(AF_INET,SOCK_DGREAM)
3)绑定ip和端口,udpSocket.bind(("你要接收的那台机器的ip地址",端口))
4)接收数据,udpSocket.recvfrom(1024)
5)关闭udpSocket对象,udpSocket.close()
1 from socket import * 2 3 udpSocket = socket(AF_INET,SOCK_DGRAM) 4 #使用udp发送的数据,在每一次的都需要写上接收方的ip和port,可以告诉接收方用什么方式编码 5 udpSocket.sendto("haha ".encode("gb2312"),("172.25.6.222",8080)) 6 7 udpSocket.sendto("你好啊".encode("utf-8"),("202.193.52.52",1880))
1 #coding = utf-8 2 3 from socket import * 4 udpSocket = socket(AF_INET,SOCK_DGRAM) 5 6 udpSocket.bind(('',8080)) 7 recvData = udpSocket.recvfrom(1024) 8 print(recvData[0].decode("utf-8"))
二、TCP
1.server端
1)导包 from socket import *
2)创建tcpSocket对象,tcpSocket = socket(AF_INET,SOCK_STREAM)
3)绑定ip和端口,tcpSocket.bind("server端的ip",端口)
4)监听,tcpSocket.listen(5)
5)接收client端,clientSocket,clientInfo = tcpSocket.accept()
6)将client端的请求信息进行打印,recvData = clientSocket.recv(1024),print(recvData)
2.client端
1)导包 from socket import *
2)创建tcpSocket对象,tcpSocket = socket(AF_INET,SOCK_STREAM)
3)连接server端,tcpSocket.connect("server的ip地址",端口)
4)向server端发送数据,clientSocket.send("hello,tcp,我来了".encode("utf-8"))
5)将server端返回的信息进行打印,recvData = clientSocket.recv(1024),print(recvData)
6)关闭客户端,clientSocket.close()
1 from socket import * 2 3 serverSocket = socket(AF_INET, SOCK_STREAM) 4 5 serverSocket.bind(("", 8899)) 6 7 serverSocket.listen(5) 8 9 print("-----1-----") 10 clientSocket,clientInfo = serverSocket.accept() 11 12 print("-----2-----") 13 #clientSocket 表示这个新的客户端 14 #clientInfo 表示这个新的客户端的ip以及port 15 16 recvData = clientSocket.recv(1024) 17 18 print("-----3-----") 19 print("%s:%s"%(str(clientInfo), recvData)) 20 21 clientSocket.close() 22 serverSocket.close()
1 from socket import * 2 3 clientSocket = socket(AF_INET, SOCK_STREAM) 4 clientSocket.connect(("192.168.119.153", 8989)) 5 6 #注意: 7 # 1. tcp客户端已经链接好了服务器,所以在以后的数据发送中,不需要填写对方的iph和port----->打电话 8 # 2. udp在发送数据的时候,因为没有之前的链接,所依需要 在每次的发送中 都要填写接收方的ip和port----->写信 9 clientSocket.send("haha".encode("gb2312")) 10 11 recvData = clientSocket.recv(1024) 12 13 print("recvData:%s"%recvData) 14 15 clientSocket.close()
三、单进程服务器
四、多进程服务器
1 from socket import * 2 from multiprocessing import * 3 from time import sleep 4 5 # 处理客户端的请求并为其服务 6 def dealWithClient(newSocket,destAddr): 7 while True: 8 recvData = newSocket.recv(1024) 9 if len(recvData)>0: 10 print('recv[%s]:%s'%(str(destAddr), recvData)) 11 else: 12 print('[%s]客户端已经关闭'%str(destAddr)) 13 break 14 15 newSocket.close() 16 17 18 def main(): 19 20 serSocket = socket(AF_INET, SOCK_STREAM) 21 serSocket.setsockopt(SOL_SOCKET, SO_REUSEADDR , 1) 22 localAddr = ('', 7788) 23 serSocket.bind(localAddr) 24 serSocket.listen(5) 25 26 try: 27 while True: 28 print('-----主进程,,等待新客户端的到来------') 29 newSocket,destAddr = serSocket.accept() 30 31 print('-----主进程,,接下来创建一个新的进程负责数据处理[%s]-----'%str(destAddr)) 32 client = Process(target=dealWithClient, args=(newSocket,destAddr)) 33 client.start() 34 35 #因为已经向子进程中copy了一份(引用),并且父进程中这个套接字也没有用处了 36 #所以关闭 37 newSocket.close() 38 finally: 39 #当为所有的客户端服务完之后再进行关闭,表示不再接收新的客户端的链接 40 serSocket.close() 41 42 if __name__ == '__main__': 43 main()
五、多线程服务器
1 #coding=utf-8 2 from socket import * 3 from threading import Thread 4 from time import sleep 5 6 # 处理客户端的请求并执行事情 7 def dealWithClient(newSocket,destAddr): 8 while True: 9 recvData = newSocket.recv(1024) 10 if len(recvData)>0: 11 print('recv[%s]:%s'%(str(destAddr), recvData)) 12 else: 13 print('[%s]客户端已经关闭'%str(destAddr)) 14 break 15 16 newSocket.close() 17 18 19 def main(): 20 21 serSocket = socket(AF_INET, SOCK_STREAM) 22 serSocket.setsockopt(SOL_SOCKET, SO_REUSEADDR , 1) 23 localAddr = ('', 7788) 24 serSocket.bind(localAddr) 25 serSocket.listen(5) 26 27 try: 28 while True: 29 print('-----主进程,,等待新客户端的到来------') 30 newSocket,destAddr = serSocket.accept() 31 32 print('-----主进程,,接下来创建一个新的进程负责数据处理[%s]-----'%str(destAddr)) 33 client = Thread(target=dealWithClient, args=(newSocket,destAddr)) 34 client.start() 35 36 #因为线程中共享这个套接字,如果关闭了会导致这个套接字不可用, 37 #但是此时在线程中这个套接字可能还在收数据,因此不能关闭 38 #newSocket.close() 39 finally: 40 serSocket.close() 41 42 if __name__ == '__main__': 43 main()
六、单进程服务器-非堵塞模式
1 #coding=utf-8 2 from socket import * 3 import time 4 5 # 用来存储所有的新链接的socket 6 g_socketList = [] 7 8 def main(): 9 serSocket = socket(AF_INET, SOCK_STREAM) 10 serSocket.setsockopt(SOL_SOCKET, SO_REUSEADDR , 1) 11 localAddr = ('', 7788) 12 serSocket.bind(localAddr) 13 #可以适当修改listen中的值来看看不同的现象 14 serSocket.listen(1000) 15 #将套接字设置为非堵塞 16 #设置为非堵塞后,如果accept时,恰巧没有客户端connect,那么accept会 17 #产生一个异常,所以需要try来进行处理 18 serSocket.setblocking(False) 19 20 while True: 21 22 #用来测试 23 #time.sleep(0.5) 24 25 try: 26 newClientInfo = serSocket.accept() 27 except Exception as result: 28 pass 29 else: 30 print("一个新的客户端到来:%s"%str(newClientInfo)) 31 newClientInfo[0].setblocking(False) 32 g_socketList.append(newClientInfo) 33 34 # 用来存储需要删除的客户端信息 35 needDelClientInfoList = [] 36 37 for clientSocket,clientAddr in g_socketList: 38 try: 39 recvData = clientSocket.recv(1024) 40 if len(recvData)>0: 41 print('recv[%s]:%s'%(str(clientAddr), recvData)) 42 else: 43 print('[%s]客户端已经关闭'%str(clientAddr)) 44 clientSocket.close() 45 g_needDelClientInfoList.append((clientSocket,clientAddr)) 46 except Exception as result: 47 pass 48 49 for needDelClientInfo in needDelClientInfoList: 50 g_socketList.remove(needDelClientInfo) 51 52 if __name__ == '__main__': 53 main()