流程如下:
tcp三次握手 client server SYN=1,ACK=0,seq=x -> <- SYN=1,ACK=1,seq=y,ack=x+1 ACK=1,seq=x+1,ack=y+1 -> tcp四次挥手 client server FIN=1,seq=u -> <- ACK=1,seq=v,ack=u+1 <- FIN=1,ACK=1,seq=w,ack=u+1 ACK=1,seq=u+1,ack=w+1 ->2、套接字
套接字:实现网络编程进行数据传输的一种技术手段 在python中使用:import socket 流式套接字(SOCK_STREAM):以字节流方式传输数据,实现tcp网络传输 数据报套接字(SOCK_DGRAM):以数据报形式传输数据,实现udp网络传输3、TCP套接字编程 3.1、服务端流程
1、创建socket套接字 2、绑定地址bind 3、监听listen 4、阻塞等待连接accept 5、数据收发send/recv 6、关闭连接close 1、创建套接字 sk = socket.socket(socket_family=AF_INET, socket_type=SOCK_STREAM, proto=0) socket_family: 网络地址类型,AF_INET表示IPV4; socket_type套接字类型(SOCK_STREAM,SOCK_DGRAM) proto通常为0,选择子协议 2、绑定地址 sk.bind(addr) 绑定本机网络地址 参数:二元元祖:(ip, port),如:('0.0.0.0', 8888) 注意:绑定本地主机地址有4种方式:127.0.0.1、'localhost'、'0.0.0.0'、实际IP(如:123.56.67.111) 方式1(127.0.0.1/localhost):以该方式绑定,本地主机客服端可通过127.0.0.1访问,但其他主机不能访问; 方式2(0.0.0.0):本地主机可以通过127.0.0.1访问,其他主机可通过123.56.67.111访问; 方式3(123.56.67.111):本地和其他主机可通过123.56.67.111访问 3、设置监听 sk.bind(n) 将套接字设置为监听套接字,确定监听队列大小,n在linux下设置后不生效 监听了之后客户端就可以连接了 4、等待处理客户端连接请求 client, addr = sk.accept() 阻塞等待处理客户端请求,accept()为阻塞函数,程序执行到这儿暂停 返回值:client客户端连接套接字;addr连接的客户端地址 5、消息收发 data = client.recv(buffersize) 接收客户端消息,阻塞函数 参数:每次最多接收消息大小 返回值:接收到的内容 n = client.send(data) 功能:发送消息 参数:要发送的内容 bytes形式 返回值:发送的字节数 6、关闭套接字 sk.close()3.2、客户端流程
1、创建socket 2、连接connect 3、收发消息send/recv 4、断开连接close3.3、TCP粘包
原因:TCP以字节流传输,没有消息边界,多次发送的消息被一次接收,就会形成粘包。 影响:如果每次发送内容是一个独立的含义,需要接收端独立解析此时粘包会有影响。 处理方法: 1、人为添加消息边界 2、控制发送速度4、UDP套接字编程 4.1、服务端流程
1、创建socket 2、绑定bind 3、消息收发recvfrom/sendto 4、断开连接close4.2、客户端流程
1、创建socket 2、收发信息sendto/recvfrom 3、断开连接close5、代码实例 5.1、TCP SERVER
import socket #创建tcp套接字 sk = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM) #绑定地址 sk.bind(('127.0.0.1', 8888)) #设置监听 sk.listen(5) #阻塞等待处理连接 while True: print("Waiting for connect...") try: client, addr = sk.accept() print("Connect from %s" % str(addr)) #打印连接的客户端地址 except Exception as e: print(e) continue #收发消息 while True: data = client.recv(1024) if not data: #客户端断开连接会立即返回一个空 print("Data trans end.") break print("received:%s" % data.decode()) n = client.send(b"Data received!") print("send %d bytes" % n) client.close() #关闭套接字 sk.close()5.2、TCP CLIENT
import socket #创建tcp套接字 sk = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM) #连接服务器 service_addr = ("127.0.0.1", 8888) sk.connect(service_addr) #收发消息 while True: data = input("Please input msg>>") if not data: break sk.send(data.encode()) data = sk.recv(1024) print("Server:%s" % data.decode()) #关闭 sk.close()
运行结果:
客户端: Please input msg:>>abc Server response:Data received! Please input msg:>> 服务端: Waiting for connect... Connect from ('127.0.0.1', 13535) received:abc send 14 bytes Data trans end. Waiting for connect...5.3、UDP SERVER
import socket #创建udp套接字 sk = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM) #绑定地址 sk.bind(('127.0.0.1', 8888)) #收发消息 while True: try: data, addr = sk.recvfrom(1024) print("Received msg:" + data.decode() + " from " +str(addr)) sk.sendto(b'UDP Data received!', addr) except Exception as e: print(e) continue #关闭 sk.close()5.3、UDP CLIENT
from socket import * # 服务器地址 ADDR = ('127.0.0.1',8888) # 创建套接字 sockfd = socket(AF_INET,SOCK_DGRAM) # 收发消息 while True: data = input("Please input msg>>") if not data: break sockfd.sendto(data.encode(),ADDR) msg,addr = sockfd.recvfrom(1024) print("From server:",msg.decode()) sockfd.close()
运行结果:
客户端: Please input msg>>abc From server: UDP Data received! Please input msg>>def From server: UDP Data received! Please input msg>> 服务端: Received msg:abc from ('127.0.0.1', 56066) Received msg:def from ('127.0.0.1', 56066)