socket建立客户端服务器程序
在python标准库中,使用socket模块中提供的socket对象,就可以i在计算机网络中建立服务器和客户端,并且能够进行通信,服务器端需要建立一个socket对象,并等待客户端的连接,客户端使用socket对象与服务器进行连接,一旦连接成功,客户端和服务器就可以进行通信了
socket模块中的socket对象是socket网络编程中的基础对象,原型如下:
socket(family,type,proto)
family: 地址簇,可选参数,默认为AF_INET(IPV4),也可以是AF_INET6或AF_UNIX;
type: socket类型,可选参数,默认为: SOCK_STREAM(TCP协议),可用SOCKET_DGRAM(UDP协议)
proto: 协议类型,可选参数,默认为0
socket客户端对象主要应用以下这些常用方法:
1.bind(host,port): 其参数是由ip地址和端口组成的元组,例如:(127.0.0.1,8888)。如果ip地址为空,则表示本机,它的作用是使socket和服务器相关联
2.listen(backlog): 参数backlog指定在拒绝连接之前,操作系统允许他的最大连接数,最小值为0,就是说已经连接了一个客户端,然后还可以连接几个,即同时连接的客户端数量; 该方法会将socket设置为服务器模式, 之后就可以调用以下的accept()方法等待客户端连接了
3.accept(): 被动模式,它会等待客户端来连接,并返回一个新的套接字对象和一个客户端的地址信息
4.close(): 关闭, 这个方法的作用是关闭该socket,停止本程序与服务器或客户端的连接
5.recv(buffersize,[flag]): 接收数据, 用来接收远程连接发来的信息,返回该信息,buffersize设置缓冲区大小
6.send(): 用于向连接的远端发送信息,data应该是bytes类型的数据, 其返回值为已传送的字节数
socket建立的基本顺序如下:
s=socket()--->s.bind()--->s.listen()--->c,a=s.accept()--->c.recv()/c.send()--->s.close()
建立套接字 绑定localhost 监听 等待连接 接收 发送 关闭socket
使用TCP协议连接会话
实例1-1:服务器socket的代码如下
import socket
HOST='' #这个设置为本机ip地址
PORT='8888' #这个是本机的端口
#建立套接字,基于IPV4和TCP协议的
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind((HOST,PORT)) #绑定本地的ip和端口
s.listen(5) #最大同时连接数量
#accept()返回一个新的套接字和一个地址信息,conn为新套接字,addr是地址信息
conn,addr=s.accept()
print(f"新的套接字为: {conn},地址为: {addr}")
while True: #循环为死循环,无限接收数据
data=conn.recv(1024) #1024是接收的最多1024字节的数据,数据赋值给data
if not data: #如果数据为空,没有数据,就执行结束
break
print(f"从{addr}接收到的数据为:")
conn.send("data") #将数据再发回到客户端
conn.close()#关闭运行
#此程序会一直运行,接收数据,直到接收的data为空,跳出循环,关闭socket
实例1-2:客户端socket的代码如下:
相比较用socket来建立服务器而言,建立客户端程序要简单的多,当然也要创建一个socket实例,而后调用这个socket实例的connect()方法来连接服务器即可,可以理解connect()是一个主动的方法,原型如下:
connect(address)
参数address通常为一个元组(由一个主机名/ip地址,端口构成),当然连接本地计算机的话,主机名可以直接使用localhost,它用于将socket连接到远程以address为地址的计算机,
s=socket()--->s.connect()--->c.recv()/c.send()--->s.close()
建立套接字 连接服务器 接收数据 发送数据 关闭socket
client代码如下:
import socket
HOST='10.10.1.1' #服务器的IP地址
PORT=8888 #要链接的服务器的端口
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect((HOST,PORT)) #这里类似server的s,bind()
data='你好'
while data: #data为true进入循环
#data进行utf-8的字节编码,sendall和send不同德是,sendall会确保所有数据发送出去,或在错误时抛出异常
s.sendall(data.encode('utf-8'))
data=s.recv(1024) #接收德最大字节
print(f'来自服务器返回德数据: \n{data.decode('utf-8')}')
data=input("请输入要发送给socket服务器的内容:")
s.colse()
使用UDP连接会话
通过使用socket传输的UDP协议建立服务器与客户程序,从步骤上看,要比使用TCP协议简单一些,发送和接收数据使用socket对象的主要方法如下:
recvfrom(buffersize,[flag]) #buffersize用来设置缓冲区大小
sendto(bytes,address) #发送data数据和地址信息
参数bytes是要发送的数据,address是要发送信息的目标地址,也是由ip地址和端口构成的元组,主要用来通过UDP协议将数据发送到指定的服务器端
使用socket建立基于UDP协议的服务器流程:
s=socket()--->s.bind()--->s.sendto()/s.recvfrom()--->s.close()
建立套接字 绑定ip地址 发送 接收 关闭套接字
使用socket建立的基于UDP协议的客户端流程:
s=socket()--->s.sendto()/s.recvfrom()--->s.close()
建立套接字 发送 接收 关闭套接字
可以看出,UDP和TCP的区别就是,基于UDP协议的服务器与客户端进行数据传时,不是先建立连接,而是直接进行数据传送
实例1-1:服务器使用UDP搭建socket
import socket
HOST=''
PORT='8888'
s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
s.bind((HOST,PORT))
while True:
data,address=recvfrom(1024)
if data==b'bye':
break
print("客户端发来的数据:\n",data.decode('utf-8'))
s.sendto(date,address)
s.close()
实例1-2:客户端使用UDP搭建socket
import socket
HOST='10.10.1.1' #socket服务器的ip地址
PORT=8888 #socket服务器的端口号
s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
data="你好!"
while data:
s.sendto(data.encode('utf-8'),(HOST,PORT))
if data==b'bye':
break
data,address=s.recvfrom(1024)
print("服务器返回的数据:",data.decode('utf-8'))
data=input("请输入发送到socket服务器的数据:\n")
s.close()
代码说明:客户端创建socket后,直接向服务器端发送数据,而没有进行连接,当用户输入bye的时,程序退出循环,关闭socket
使用socketserver模块搭建服务器
虽然使用socket模块可以创建服务器,但是程序员要对包括网络连接等进行管理和编程,为了更加方便的创建网络服务器,python标准库提供了一个创建网络服务器的框架---socketserver
socketserver框架将处理的亲求划分为两个部分,分别对应服务器类和请求处理类,服务器类处理通信等问题,请求处理类处理数据交换或传送,这样,更加容易进行网络编程和程序的扩展,同时,该模块还支持快速的多线程或者多进程的服务器编程
socketsserver模块中使用的服务器类主要有TCPserver、UDPserver、ThreadingTCPserver、ThreadingUDPserver、ForkingTCPserver、FockingUDPserver等,其中有TCP字符的就是使用TCP协议的服务器类,有UDP协议的服务器类,有Threading字符的是多线程服务器类,有Forking字符的是多进程服务器类,要创建不同类型的服务器程序,只需继承其中之一或直接实例化,然后调用服务器类方法, serve_forever((),这些服务器的构造方法参数有:
server_address #由ip地址和端口构成的元组
requestHandlerClass #处理器类,供服务器类调用处理数据
socketserver模块中使用处理器类主要有StreamRequestHandler和DatagramRequestHandler,只要继承其中之一,就可以i自定义一个处理器类,通过覆盖以下三种方法,实现自定义
setup() 为请求准备请求处理器(请求处理的初始化工作)
handler() 完成具体的请求处理工作
finish() 清理请求处理器相关数据
使用socket模块来搭建TCP协议的服务器
import socketserver #导入模块
class myserver(socketserver.BaseRequestHandler):
def handle(self):
print("conn是:",self.request) #调用父类中的request
print("addr is",self.client_address)
while True:
try: #捕获消息
data=self.request.recv(1024) #相当于s.recv(1024)
if not data: #如果data为空,那么就结束循环
break
print("客户端发来的信息是:",data.decode())
self.sendall(data.encode())
except Exception as e:
print(e)
break
if __name__=='__main__':
s=socketserver.ThreadingTCPServer(('10.10.1.1',8080),myserver)
s.serve_forever()
实例定义了一个继承自StreamRequestHandler的处理器类,并覆盖了handler()方法,以实现数据处理,然后直接实例化了TCPserver的类,调用serve_forever()方法启动服务器