网络编程: 基于TCP协议的socket, 实现一对一, 一对多通信
TCP协议 面向连接 可靠的 面向字节流形式的
tcp是基于链接的,必须先启动服务端,然后再启动客户端去链接服务端
TCP协议编码流程:
服务器端: 客户端
实例化对象 实例化对象
绑定IP地址和端口号
监听
接收客户端的连接 连接服务器
收发 收发
关闭 关闭
问题:有的同学在重启服务端时可能会遇到
解决方法:
#加入一条socket配置,重用ip和端口 import socket from socket import SOL_SOCKET,SO_REUSEADDR sk = socket.socket() sk.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #就是它,在bind前加 sk.bind(('127.0.0.1',8898)) #把地址绑定到套接字 sk.listen() #监听链接 conn,addr = sk.accept() #接受客户端链接 ret = conn.recv(1024) #接收客户端信息 print(ret) #打印客户端信息 conn.send(b'hi') #向客户端发送信息 conn.close() #关闭客户端套接字 sk.close() #关闭服务器套接字(可选)
tcp三次握手: 一定是client先发起请求
a 客户端发起请求连接服务器
b 服务器返回:接收到请求,并要求连接客户端
c 客户端回复:可以连接
四次挥手: 谁先发起断开连接的请求都可以
a 客户端发起断开连接的请求:
意思是: 我想和你断开连接,我没有数据要继续发送了,但是如果你有数据需要发送,我可以继续接收
b 服务器回复 : 我接收到你的请求了
c 服务器发送 : 我已经准备好断开连接了
d 客户端回复 : 收到你的信息,断开连接
tcp实现的一个聊天室, 可以实现一对多,但是必须断掉别人的连接, 然后才能和下一个人聊,本质还是一对一
只是创建一个死循环,让服务器一直处于待机状态
while 1: conn,addr = sk.accept()
1 import socket 2 3 4 sk = socket.socket() 5 sk.bind(('127.0.0.1',8888)) 6 sk.listen() 7 8 while 1: 9 10 conn,addr = sk.accept() 11 12 msg_r = conn.recv(1024) 13 if msg_r.decode('utf-8') != 'q': 14 print(msg_r.decode('utf-8')) 15 16 else: 17 break 18 19 msg_s = input('>>>') 20 if msg_s != 'q': 21 conn.send(msg_s.encode('utf-8')) 22 else: 23 conn.send(msg_s.encode('utf-8')) 24 break
1 import socket 2 3 name = input('请输入你的名字:\n') 4 5 sk = socket.socket() 6 sk.connect(('127.0.0.1', 8888)) 7 8 9 while 1: 10 11 msg_s = input('>>>') 12 if msg_s != 'q': 13 sk.send((name + msg_s).encode('utf-8')) 14 else: 15 sk.send(msg_s.encode('utf-8')) 16 break 17 18 msg_r = sk.recv(1024) 19 if msg_r != 'q': 20 print(msg_r.decode('utf-8')) 21 else: 22 break 23 24 sk.close()
1 import socket 2 3 name = input('请输入你的名字:\n') 4 5 sk = socket.socket() 6 sk.connect(('127.0.0.1', 8888)) 7 8 while 1: 9 10 msg_s = input('>>>') 11 if msg_s != 'q': 12 sk.send((name + msg_s).encode('utf-8')) 13 else: 14 sk.send(msg_s.encode('utf-8')) 15 break 16 17 msg_r = sk.recv(1024) 18 if msg_r != 'q': 19 print(msg_r.decode('utf-8')) 20 else: 21 break 22 23 sk.close()