华子目录
- 引言
- 什么是`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端