华子目录
- 引言
- 什么是`socket`
- `socket`套接字`类型`
- `TCP`和`UDP`
- `socket`服务端核心组件
- 1.创建`socket`对象
- 2.绑定`地址`和`端口`
- 3.监听连接
- 4.接受连接
- 5.接受`client端`消息`client_sock.revc(1024)`
- 6.发送`响应`给`client端`
- 6.1`client_sock.send()`
- 6.2`client_sock.sendall()`
- 7.关闭`client端`连接
- 8.关闭`server`端连接
- `socket`客户端核心组件
- 1.创建`socket`对象
- 2.连接`server端`
- 3.发送`请求`给`server端`
- 3.1`client.send()`
- 3.2`client.sendall()`
- 4.接受`server端`响应`client.revc(1024)`
- 5.关闭`client端`连接
- 示例
- 测试
引言
在互联网时代,网络编程已经成为开发人员必备的技能之一。无论是Web开发、实时通信还是分布式计算,都离不开网络编程的支持。Python提供的socket模块为我们提供了简洁而强大的接口,可以轻松实现客户端和服务器之间的通信。
Socket编程是网络编程的重要部分,主要用于在不同计算机之间进行通信。Python提供了一个非常强大的socket库,使得网络编程变得简单和灵活。本篇博文将详细介绍Python的socket编程,包括基础概念、核心组件、常用功能,并附上一个综合的示例及其运行结果。
什么是socket
Socket是网络通信的端点,它允许不同的计算机之间进行数据交换。在Python中,socket是通过socket模块来实现的。Socket的通信过程主要包括创建socket对象、绑定地址、监听连接、发送和接收数据等步骤。
socket套接字类型
在 Python 中,socket类型主要有以下几种:
流式套接字stream(SOCK_STREAM):提供面向连接的、可靠的字节流服务。常用于TCP协议。数据报套接字dgram(SOCK_DGRAM):提供无连接的、不可靠的数据报服务。常用于UDP协议。
TCP和UDP
TCP(Transmission Control Protocol):面向连接的、可靠的协议,适用于需要保证数据准确传输的场景。UDP(User Datagram Protocol):无连接的、不可靠的协议,适用于需要快速传输数据但不要求数据准确到达的场景。
socket服务端核心组件
1.创建socket对象
使用socket.socket()函数可以创建一个 socket对象。该函数的两个参数分别指定了地址族和套接字类型。
import socket
#创建名为server的一个socket对象
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.AF_INET:表示使用IPv4地址。socket.SOCK_STREAM:表示套接字类型为流式套接字,即TCP。
2.绑定地址和端口
服务端需要绑定一个 IP地址和端口号,使得客户端可以找到并连接到服务器。
- 使用
对象名.bind()进行绑定,bind()括号中是一个元组类型的
#绑定ip地址和服务的端口号
server.bind(("127.0.0.1", 10086))
3.监听连接
服务器端需要监听来自客户端的连接请求。
- 使用
对象名.listen()函数进行监听,listen()括号中是一个int类型,表示允许连接的最大连接数
#监听的最大连接数是3
server.listen(3)
4.接受连接
服务器端使用 对象名.accept() 函数接受客户端的连接请求。
- 该函数会发生
阻塞,直到有客户端连接。 - 如果有
客户端连接了,accept()返回2个值,第一个是client的socket对象,第二个是client的ip地址和端口
#通过接受到的客户端连接,来获取client的socket对象,从而获取client发送过来的消息
client_sock, client_address = server.accept()
client_sock是一个客户端socket对象client_address是客户端的地址信息,是一个元组(ip地址, 端口号)
5.接受client端消息client_sock.revc(1024)
- 使用返回的
client_sock对象与客户端进行数据交换。可以使用client_sock.recv()方法接收客户端发送的数据, recv()能接受的最大字节数为1024个字节,所以recv()括号中填写int类型的数字表示字节数,如果接受的字节数大于1024会发生粘包recv()方法在接受数据时会发生阻塞recv()会返回一个编码后的数据,所以我们在查看数据的时候,需要进行data.decode("utf-8")进行解码
data = client_sock.recv(1024)
print(data.decode("utf-8"))
6.发送响应给client端
6.1client_sock.send()
发送时,需要对数据进行编码,常使用encode("utf-8")对数据进行编码send()可能会发送数据的全部或部分。如果缓冲区已满或网络状况不佳,它可能只会发送部分数据。send()方法返回一个整数,表示实际发送的字节数
response = "收到了"
byte_number = client_sock.send(response.encode("utf-8"))
print(byte_number) #此时byte_number值为9,因为一个汉字在utf-8中占3个字节
6.2client_sock.sendall()
发送时,需要对数据进行编码,常使用encode("utf-8")对数据进行编码- 如果由于
网络拥塞或其他原因,数据不能立即发送完毕,sendall()会继续尝试发送数据,直到所有数据都发送完毕。
client_sock.sendall("接受到了".encode("utf-8"))
7.关闭client端连接
使用close()函数可以关闭socket连接。
client_sock.close()
8.关闭server端连接
使用close()函数可以关闭socket连接。
server.close()
socket客户端核心组件
1.创建socket对象
使用socket.socket()函数可以创建一个 socket对象。该函数的两个参数分别指定了地址族和套接字类型。
import socket
#创建名为client的一个socket对象
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.AF_INET:表示使用IPv4地址。socket.SOCK_STREAM:表示套接字类型为流式套接字,即TCP。
2.连接server端
client端需要使用client对象.connect()函数连接到服务端。connect()括号中是一个元组类型,第一个参数表示服务端ip,第二个参数表示服务端开发的端口
client.connect(("127.0.0.1", 10086))
3.发送请求给server端
3.1client.send()
发送时,需要对数据进行编码,常使用encode("utf-8")对数据进行编码send()可能会发送数据的全部或部分。如果缓冲区已满或网络状况不佳,它可能只会发送部分数据。send()方法返回一个整数,表示实际发送的字节数
request = "你好服务端"
byte_number = client.send(request.encode("utf-8"))
print(byte_number) #此时byte_number值为15,因为一个汉字在utf-8中占3个字节
3.2client.sendall()
发送时,需要对数据进行编码,常使用encode("utf-8")对数据进行编码- 如果由于
网络拥塞或其他原因,数据不能立即发送完毕,sendall()会继续尝试发送数据,直到所有数据都发送完毕。
client.sendall("你好服务端".encode("utf-8"))
4.接受server端响应client.revc(1024)
- 使用
client对象,可以使用client.recv(1024)方法接收server端响应的数据, recv()能接受的最大字节数为1024个字节,所以recv()括号中填写int类型的数字表示字节数,如果接受的字节数大于1024会发生粘包recv()方法在接受数据时会发生阻塞recv()会返回一个编码后的数据,所以我们在查看数据的时候,需要进行data.decode("utf-8")进行解码
data = client.recv(1024)
print(data.decode("utf-8"))
5.关闭client端连接
使用close()函数可以关闭socket连接。
client.close()
示例
server端
import socket
class TCPSERVER:
def __init__(self, ip, port):
self.ip = ip
self.port = port
self.number = 5 #设置服务端监听个数
def serverTCP(self):
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #tcp
server.bind((self.ip, self.port))
server.listen(self.number)
client_sock, client_address = server.accept()
while True:
try: #tcp中不允许client先关机,如果先关机,服务端会报错,所以这里使用try异常捕获
# 接受client消息
data = client_sock.recv(1024)
print(data.decode("utf-8"))
# 响应client
client_sock.sendall("响应:".encode("utf-8")+data)
except ConnectionAbortedError:
break
client_sock.close()
server.close()
if __name__ == '__main__':
s = TCPSERVER("127.0.0.1", 10080)
s.serverTCP()
client端
import socket
class TCPCLIENT:
def __init__(self, ip, port):
self.server_ip = ip
self.server_port = port
def clientTCP(self):
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #tcp
client.connect((self.server_ip, self.server_port))
while True:
msg = input(">>(quit退出):").strip()
if not msg: #tcp不能发送空白消息
continue
if msg == "quit":
break
# client端发送数据
client.sendall(msg.encode("utf-8"))
# client端接受响应
data = client.recv(1024)
print(data.decode("utf-8"))
client.close()
if __name__ == '__main__':
c = TCPCLIENT("127.0.0.1", 10080)
c.clientTCP()
测试
必须先启动server端,再启动client端




















