本文只整理了最常见、最基础的socket编程,大神们就不用浪费时间了
socket本意是插座的意思,在编程中也有类似的含义,将所匹配的服务器-客户端所连接起来,交互信息
接下来就介绍下搭建最简单的框架,以实现网络编程的功能
套接字分类
流式套接字(TCP)
数据报套接字(UDP)
原始套接字(偏底层)
socket编程思路
服务端
1、导入模块
from socket import *
2、创建套接字
sockfd = socket() #此处有多个参数,后文有详解。此处是默认创建的TCP
3、绑定服务器IP和端口号
注意:此处传参是一个元组(HOST, PORT)
sockfd.bind((HOST, PORT))
4、设为监听套接字,并建立监听队列
sockfd.listen(5)
5、接受客户端的连接
说明:此处有两个返回值,分别是一个新的套接字connfd以及客户端的地址addr
connfd, addr = sockfd.accept()
6、接受客户端消息、发送消息给客户端
注意:信息的交互是以二进制进行传输
recv_msg = connfd.recv(BUFFERSIZE).decode()
connfd.send(msg.encode())
7、关闭套接字(服务器一般不进行此项操作)
客户端
1、导入模块
from socket import *
2、创建套接字
sockfd = socket()
3、连接服务器
注意:此处的参数也是元组
sockfd.connect((HOST, PORT))
4、发送消息、接收消息
sockfd.send(msg.encode())
recv_msg = sockfd.recv(BUFFERSIZE).decode()
5、关闭套接字
sockfd.close()
socket()说明
该部分引用自:
https://blog.csdn.net/zzyandzzzy/article/details/72236388
在创建套接字时,需要调用socket.socket()函数,而该函数有多个参数:
sockfd = socket.socket(
socket_family = socket.AF_INET,
socket_type = socket.SOCK_STREAM,
proto = 0)
其中
socket_family:地址族类型
socket_family参数 | 描述 |
---|---|
socket.AF_UNIX | 只能够用于单一的Unix系统进程间通信 |
socket.AF_INET | 服务器之间网络通信 |
socket.AF_INET6 | ipv6 |
socket_type:要创建的套接字类型
socket_type参数 | 描述 |
---|---|
socket.SOCK_STREAM | 流式socket , 当使用TCP时选择此参数 |
socket.SOCK_DGRAM | 数据报式socket ,当使用UDP时选择此参数 |
socket.SOCK_RAW | 原始套接字,普通的套接字无法处理ICMP、IGMP等网络报文,而SOCK_RAW可以;其次,SOCK_RAW也可以处理特殊的IPv4报文;此外,利用原始套接字,可以通过IP_HDRINCL套接字选项由用户构造IP头。 |
proto:指明所要接收的协议类型,通常为0或者不填
Type参数 | 描述 |
socket.IPPROTO_RAW | 相当于protocol=255,此时socket只能用来发送IP包,而不能接收任何的数据。发送的数据需要自己填充IP包头,并且自己计算校验和 |
socket.IPPROTO_IP | 相当于protocol=0,此时用于接收任何的IP数据包。其中的校验和和协议分析由程序自己完成。 |
SocketServer
此外,python还封装了一个特别简便的模块——SocketServer,接下来就简单介绍下大致的用法
详情请移步:https://www.cnblogs.com/xiajie/p/5250675.html
要实现本模块的功能,必须定义一个继承于父类的
BaseRequestHandler处理程序handle类
使用流程如下:
import socketserver
#定义一个类,继承socketserver.BaseRequestHandler
class Server(socketserver.BaseRequestHandler):
def handle(self):
print('新的客户端连接:',self.client_address)
while True:
#接收客户发送的数据
data = self.request.recv(1024)
print('接受到的消息为:',data.decode())
self.request.send(data)#将收到的信息再发送给客户端
if __name__ == '__main__':
host,port = '127.0.0.1',8080
server = socketserver.ThreadingTCPServer((host,port),Server) #多线程、TCP
server.serve_forever()#保证一个客户端退出后,服务器能正常运行
实例具有以下方法和变量:
1.sock.socket 用于传入请求的套接字对象
2.sock.server_address 监听服务器的地址.比如元组("127.0.0.1",9999)
3.sock.RequestHandlerClass 传递给服务器构造函数并由用户提供的请求处理程序类.
4.sock.serve_forever() 处理无限的请求.
5.sock.shutdown() 停止serve_forever()循环.
6.sock.fileno() 返回服务器套接字的整数文件描述符.该方法可以有效的通过轮询操作(如select()函数)使用服务器实例.
具体类说明
'DatagramRequestHandler', #数据报套接字
'StreamRequestHandler', #流式套接字
********************------------------------------------**************************
'ForkingMixIn', #多进程
'ThreadingMixIn', #多线程
********************------------------------------------**************************
'ForkingTCPServer', #'ForkingMixIn' + 'TCPServer'
'ForkingUDPServer',
'ThreadingTCPServer',
'ThreadingUDPServer',
********************------------------------------------**************************
'TCPServer', #TCP服务器
'UDPServer', #UDP服务器
********************------------------------------------**************************
'ThreadingUnixDatagramServer',
'ThreadingUnixStreamServer',
********************------------------------------------**************************
'UnixDatagramServer',
'UnixStreamServer',
常用组合
多进程、TCP服务器
'StreamRequestHandler',
'ForkingMixIn',
'TCPServer',
********************------------------------------------**************************
多线程、TCP服务器
'StreamRequestHandler',
'ThreadingMixIn',
'TCPServer',
********************------------------------------------**************************
多进程、UDP服务器
'DatagramRequestHandler',
'ForkingMixIn',
'UDPServer',
********************------------------------------------**************************
多线程程、UDP服务器
'DatagramRequestHandler',
'ThreadingMixIn',
'UDPServer',