Python网络编程-socket

Socket

socket(套接字)是一种计算机通信协议。具体的数据传输可以通过TCP&IP、UDP、 蓝牙等实现。TCP、UDP的特点如下:
TCP(Transmission Control Protocol):可靠、通信双方建立连接、数据传输按照顺序。UDP(User Datagram Protocol):用户数据报协议,不可靠、不保证顺序。但快速,服务器压力小,因此很多要求实时性高的应用视频、游戏,通常选择UDP。

Python网络编程-socket

(TCP套接字的流程,图源 https://realpython.com/python-sockets/#tcp-sockets)
TCP套接字的流程如图所示,双方建立双向连接然后发送接收数据,具体过程如下:

  1. 1. 服务器创建监听socket,等待客户端的连接(listen())。

  2. 2. 当客户端请求连接时,服务器调用.accept()接受连接。

  3. 3. 连接建立后,双方就可以传输数据了(.send() and .recv())。客户端发送数据后,服务器会接收到相应的数据。同样,服务器发送数据后,客户端会接收到数据。

  4. 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 得到下面的结果:

Python网络编程-socket

Python网络编程-socket

这个简单的例子展示了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 然后两个客户端就可以进行对话了。

Python网络编程-socket

关于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

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!