什么是 socket?
Socket又名“套接字”,是基于TCPP协议封装出来的一套编程接口。通常就被称作套接字,反正记住这个就可以了。
Socket把底层复杂的TCP协议的各种细节给隐藏了,封装成了简单的可操作的编程API接口,提高开发人员写网络通信软件的开发效率。
如果你想写一个像qq、微信这样的C/S架构的通信软件,就可以基于 Socket,而不是自己生写原生的TCP/IP协议底层的东西。
注意 Socket本身并不是协议,它是应用层与TCP/IP协议族通信的中间软件抽象层,是一组调用接口。
sokcet的工作流程
Socket模块编程参数详解
只在服务端用的socket函数
s.bind()绑定主机端口号到套接字
s.listen()开始tcp监听
s.accept()被动接受客户的连接,(阻塞式)等待连接的到来
客户端socket函数
c.connect() 主动初始化tcp服务器连接
c.connect_ex() connect()函数的扩展版本,错时返回出错码,而不是抛出异常
公共用途的 socket函数
s.recv接收tcp数据
s.send()发送tcp数据,会返回已发送的数据量,如果仅传输了一些数据,到应用程序需要试传剩余数据,(需要用户自己完成)
s.sendall()发送完整的tcp数据(本质就是循环调用send,试发送所有数据,成功到返回none,失败则抛出异常
s.recvfrom()接收udp数据
s.sendto()发送udp数据
s.getpeername()连接到当前套接字的远端的地址
s.getsockename()当前套接字的地址
s.getsockopt()返回指定套接字的参数
s.setsockopt()设置指定接字的参数
s.close()关闭套接字
s.fileno()返回套接的文件描述符(异步编程用)
单一通信模式案例
server端代码
#!/usr/bin/env python
import socket
host_info = ("0.0.0.0", 8888)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(host_info)
s.listen()
print("----wait connection-------")
con, addr = s.accept()
con.send("hello, client. we will connection...".encode())
data = con.recv(1024)
print("FROM CLIENT:", data.decode())
con.close()
s.close()
client端代码
#!/usr/bin/env python
import socket
c = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
c.connect(("127.0.0.1", 8888))
data = c.recv(1024)
print("from server:", data.decode())
c.send("hello server".encode())
c.close()
交互的结果
一对多交互演示
刚才演示的是一个server对应一个client交互的样式,那么一个server如何对应多个client呢?
server端代码
#!/usr/bin/env python
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(("localhost", 9000))
s.listen(3)
count = 0
while True:
print("-----wait connetion-----")
con, addr = s.accept()
count += 1
print(f"the {count} conneted,addr is {addr}.")
while True:
try:
data = con.recv(1024)
con.send(data.decode().upper().encode())
print(f"from client {addr} data:{data.decode()}")
if not data:
break
except ConnectionResetError as e:
print(e)
break
代码解读:
内层while循环是针对单一客户端持续交互的代码,而外层while循环是针对多个客户端的连接而定的。
同时处理了客户端异常结束后,避免服务端抛出异常。
s.listen(3),意思是允许排队的客户端是3个。
client端代码
#!/usr/bin/env python
import socket
c = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
c.connect(("localhost", 9000))
except ConnectionRefusedError as e:
print(e)
else:
while True:
msg = input("client msg>>:").strip()
if msg == "q":
break
try:
c.send(msg.encode())
data_from_server = c.recv(1024)
print("from server msg:", data_from_server.decode())
except ConnectionResetError as e:
print(e)
break
这里处理了服务端未响应的异常ConnectionRefusedError和服务端断开的异常ConnectionResetError。
这里针对模拟客户端多开做一个配置说明。
第一步:
第二步:
如此,多次执行客户端代码就可以模拟多个客户端和服务端交互了。
快点来一起试试吧,有什么问题可以私信或者评论交流哦。