Socket
socket(套接字)是一种计算机通信协议。具体的数据传输可以通过TCP&IP、UDP、 蓝牙等实现。TCP、UDP的特点如下:
TCP(Transmission Control Protocol):可靠、通信双方建立连接、数据传输按照顺序。UDP(User Datagram Protocol):用户数据报协议,不可靠、不保证顺序。但快速,服务器压力小,因此很多要求实时性高的应用如视频、游戏,通常选择UDP。
(TCP套接字的流程,图源 https://realpython.com/python-sockets/#tcp-sockets)
TCP套接字的流程如图所示,双方建立双向连接然后发送接收数据,具体过程如下:
-
1. 服务器创建监听socket,等待客户端的连接(
listen()
)。 -
2. 当客户端请求连接时,服务器调用
.accept()
接受连接。 -
3. 连接建立后,双方就可以传输数据了(
.send()
and.recv()
)。客户端发送数据后,服务器会接收到相应的数据。同样,服务器发送数据后,客户端会接收到数据。 -
4. 最后,双方可以通过
.close()
关闭套接字。
下面用Python实现这个过程。
server
服务器端创建一个socket
并监听请求。在while True
中一直尝试接受请求然后接收信息,然后发送一条信息并断开连接。
#server.py
import socket
HOST = '127.0.0.1' # ipv4 address.内网ip. 查看方法:ipconfig (Windows);ip addr show (Linux )
PORT = 55555 # 端口,不要使用被占用的端口(建议使用四位数,22,443等较小的数字可能被占用)。
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Internet, tcp
server.bind((HOST, PORT))
server.listen(5) # 监听...
while True:
communication_socket, address = server.accept()
print(f"Connected to {address}")
message = communication_socket.recv(1024).decode('utf-8')
print(f"Message from client is {message}")
communication_socket.send(f"Got your message!".encode("utf-8"))
communication_socket.close()
print(f"Connection with {address} ended!")
client
客户端和上面很类似,创建socket并连接,然后发送信息和接收信息。
#client.py
import socket
HOST = '127.0.0.1' # 如果是连接公网上的电脑(非局域网) , 则写server的公网 ip.
PORT= 55555
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((HOST, PORT))
client.send("hello, world!".encode('utf-8'))
print(client.recv(1024).decode('utf-8'))
然后打开两个命令行分别运行 python server.py
python client.py
得到下面的结果:
这个简单的例子展示了socket的基本原理。我们可以通过socket通信实现多人聊天、联机游戏……
多人聊天
服务器端使用多线程来处理多个客户端请求。
server
# server.py
import socket
import threading
host = '127.0.0.1'
port = 55555
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((host, port))
server.listen()
clients = []
usernames = []
# 将message 发送给所有 clients
def broadcast(message):
for client in clients:
client.send(message)
# 处理客户端消息(接收并广播)
def handle(client):
while True:
try:
message = client.recv(1024)
broadcast(message)
except Exception:
index = clients.index(client)
clients.remove(client)
username = usernames[index]
broadcast(f"{username} left the chat!".encode('utf-8'))
usernames.remove(username)
break
# 处理客户端请求连接
def reveive():
while True:
client, address = server.accept()
print(f"Connected with {address}")
client.send("name:".encode('utf-8'))
name = client.recv(1024).decode('utf-8')
usernames.append(name)
clients.append(client)
print(f"user name is {name}")
broadcast(f"{name} joined the chat!".encode("utf-8"))
client.send(f"connected to the server!".encode('utf-8'))
thread = threading.Thread(target=handle, args=(client,))
thread.start()
print("server is listening...")
reveive()
client
客户端使用线程来接收消息和发送消息。
# client.py
import socket
import threading
name = input("input your name:")
host = '127.0.0.1'
port = 55555
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))
def receive():
while True:
try:
message = client.recv(1024).decode('utf-8')
if message == 'name:':
client.send(name.encode('utf-8'))
else:
print(message)
except Exception:
print("exception happened... exit")
client.close()
break
def write():
while True:
message = f"{name}: {input('')}"
client.send(message.encode("utf-8"))
receive_thread = threading.Thread(target=receive)
receive_thread.start()
write_thread = threading.Thread(target=write)
write_thread.start()
然后打开3个命令行分别运行 python server.py
python client.py
python client.py
然后两个客户端就可以进行对话了。
关于ip地址
上面我们使用HOST = '127.0.0.1'
作为ip地址,只能在自己的电脑上进行连接。
局域网连接:server端的HOST改为内网ip。client端的HOST改为server内网ip。
互联网连接:如果你有一个公网ip,则可以将server端的HOST内网ip。client端的HOST改为公网ip。
注:ipconfig
(Windows)或ip addr show
(Linux)可显示 内网ip。
参考
[1] Python Sockets Simply Explained: https://www.youtube.com/watch?v=YwWfKitB8aA&list=PL7yh-TELLS1FwBSNR_tH7qVbNpYHL4IQs&index=11
[2]python-socket库: https://docs.python.org/zh-cn/3.8/library/socket.html
[3]python-sockets: https://realpython.com/python-sockets/#tcp-sockets
[4]tcp协议详解: https://zhuanlan.zhihu.com/p/64155705
原文始发于微信公众号(一只大鸽子):Python网络编程-socket
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/237625.html