Python-socket模块网络编程基本使用(TCP和UDP协议)
目录
一、socket模块通信简述
本次主要是大致说明socket模块可以使用的两个通信协议TCP和UDP。注意网络通信是多端的,不可能就一个程序来完成,在不同的端程序也会有所不同。我们所说的端一般为服务器端和客户端。服务器端和客户端的程序是不同的。并且我们是要先打开服务器,再打开客户端开始通信。
TCP协议服务器端建立了连接,所以要关闭这个连接。UDP协议服务器什么都没做。也就不需要服务器关闭什么。
当然你要是想关服务器的话,那也可以给服务器给关掉。
1.1 TCP协议程序结构流程图图(以下左边是服务器端,右边是客户端)
1.2 UDP协议程序结构流程图
二、TCP和UDP的大致区别
TCP相对来说复杂一些,TCP协议服务器会创建一个新的连接socker对象来与客户端互相通信。而UDP就不会。所以在后面也可以看出,TCP一旦建立连接后,发送数据就不再需要地址直接send(data)即可,但是UDP通信是没有建立连接,所以发送数据需要服务器的地址,它使用的方法为sendto(data, address)。这就是它们的主要区别。
TCP发送数据前要先建立连接(connect);UDP发送数据前不建立连接,但发送数据是要传入一个参数为服务器的地址(address)
注意:
- 它发送的数据必须是字节序列对象,类似与我们的图片(jpg文件等)文件。图片其本质上就是一连串字节序列对象,每一个像素点为8位二进制字节序列(灰度图像,彩色图像是3通道,所以每一个像素点为24位二进制字节序列)。
- 上面以及下文所说的地址都是(ip地址, 端口号),是ip地址和端口号组成的二个元素的元组。
三、常用参数
socket.AF_INET:表示使用IPv4地址
socket.SOCK_STREAM:表示使用TCP通信协议,用于创建TCP Socket对象的参数
socket.SOCK_DGRAM:表示使用UDP通信协议,用于创建UDP Socket对象的参数
address参数:是ip地址和端口号的二元组。即:(ip地址,端口号)
四、常用方法
网络通信分为服务器端和客户端。
两个使用的函数(socket类的方法)也有一些不同。
4.1 TCP协议常用方法
TCP协议通信需要服务器监听端口,并阻塞端口,等待客户端连接。
创建TCP Socket对象
<模块名.类名>
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket类对象有很多方法。
以下为:
<类对象.方法>
服务器端一般用:
socket.bind(address):绑定地址和端口
socke.listen(backlog):监听端口,backlog是最大连接数,即该端口最多能连接的客户端数。
socket.accept():使用阻塞方法,等待客户端连接,并返回(coon,address)二元组对象。
其中coon是连接用的socket类对象, address为客户端地址(形式见上)
客户端一般用:
socket.connect(address):连接服务器socket,address是服务器的ip地址和端口号
服务器端和客户端共同使用的方法有:
socket.recv(buffsize):接收TCP Socket数据,该方法返回字节序列对象(我们打的字符串是Unicode编码对象,应先用字符串类的encode()方法,将其变为字节序列编码对象,再发送)。buffsize是一次最大接收字节数。
socket.send(bytes):发送TCP Socket数据,将字节序列对象(数据)发送到远程socket,返回成功发送的字节数。如果发送的数据量很大,需要多次调用该方法发送数据。
socket.sendall(bytes):和send()功能一样,如果发送成功返回None,发送失败则抛出异常。该方法会一次将数据全部发送完。
socket.close():关闭Socket。
4.2 UDP协议常用方法
服务器使用:
只需要使用TCP协议中的的bind()方法。不需要listen()和accept()方法。
因为UDP通信不需要像TCP一样监听端口,建立连接。
客户端使用:
socket.recvfrom(buffsize):接收UDP Socket数据,该方法返回(data,address)二元组对象,data是字节序列对象,address是发送数据的远程Socket地址,
参数buffsize表示一次接收的最大字节数。
socket.sendto(bytes, address):发送UDP Socket数据。将bytes数据发送到地址为adress的远程Socket,返回成功发送的字节数。
socket.close():关闭Socket。
五、简单程序实例
5.1 TCP协议
5.1.1 服务器端
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 绑定自己的ip地址和端口号
s.bind(('0.0.0.0', 8888)) # 0.0.0.0表示可以监听任何网段
print(socket.gethostname()) # 返回主机名字
# 监听端口
s.listen()
print('服务器启动...')
# 等待客户端连接,用阻塞方法s.accept
coon, address = s.accept()
# 客户端连接成功
print(address)
# 接受客户端数据
data = coon.recv(1024)
print('从客户端接收消息:{0}'.format(data.decode()))# 接受的消息需解码为字符串
# 客户端发送数据
coon.send('你好'.encode()) # 发送的数据需要编码为字节流
# 释放服务器端资源
coon.close()
print('服务器端已释放资源!')
s.close()
5.1.2 客户端
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#连接服务器
s.connect(('127.0.0.1', 8888))
#给服务器发送消息
s.send(b'Hello')
#从服务器接受消息
data = s.recv(1024)
print('从服务器端接收消息:{0}'.format(data.decode()))
s.close()
print('客户端以释放资源!')
5.2 UDP协议
5.2.1 服务器端
import socket
#使用IPv4地址类型,使用UDP协议
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.settimeout(10) # 设置超时时间,如果服务器一段时间为与客户端通信,则主动关闭服务器端
s.bind(('',8888))
print('服务器启动......')
data, client_address = s.recvfrom(1024)
print('从客户端接收消息:{0}'.format(data.decode()))
s.sendto('你好'.encode(), client_address)
s.close()
5.2.2 客户端
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
#服务器地址
server_address = ('127.0.0.1', 8888)
#给服务器发送数据
s.sendto(b'Hello', server_address)
#从服务器端接收数据
data,_ = s.recvfrom(1024)
print('从服务端接收消息:{0}'.format(data.decode()))