Python Socket模块实现服务端与客户端通信

Socket是TCP/IP提供的外部编程接口,是对TCP/IP的封装和应用。

Socket被称作“套接字”,用于描述IP地址和端口,是一个通信、链的句柄,可以实现不同虚拟机 或不同计算机之间的通信。网络上的两个程序通过一个双向的通信连接实现数据的交换,应用程序通过“套接字”向网络发出请求或者应答网络请求。

Socket模块的主要目的是帮助在网络上的两个程序之间建立信息通道。在Python中提供了两个基本的Socket模块:服务端Socket客户端Socket

当创建一个服务端Socket之后,这个Socket就会在本机的一个端口上等待连接,客户端Socket会访问这个端口,当两者完成连接之后,就可以进行交互了。

使用Socket编写一个简单的服务端和客户端

多线程服务端程序:

# -*- coding: UTF-8 -*-
import socket               # 导入 socket 模块
import threading

# 处理客户端的请求操作
def handle_client_request(service_client_socket, ip_port):
    # 循环接收客户端发送的数据
    while True:
        # 接收客户端发送的数据
        recv_data = service_client_socket.recv(1024)
        # 容器类型判断是否有数据可以直接使用if语句进行判断,如果容器类型里面有数据表示条件成立,否则条件失败
        # 容器类型: 列表、字典、元组、字符串、set、range、二进制数据
        if recv_data:
            message = recv_data.decode()
            print(message)
            print(ip_port)
            # 回复
            service_client_socket.send("已接收...".encode())
 
        else:
            print("客户端下线了:", ip_port)
            print()
            break
    # 终止和客户端进行通信
    service_client_socket.close()
 
if __name__ == '__main__':
    # 创建tcp服务端套接字
    tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 设置端口号复用,让程序退出端口号立即释放
    tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
    # 绑定端口号
    tcp_server_socket.bind(("", 9090))
    # 设置监听, listen后的套接字是被动套接字,只负责接收客户端的连接请求
    tcp_server_socket.listen(128)
    # 循环等待接收客户端的连接请求
    while True:
        # 等待接收客户端的连接请求
        service_client_socket, ip_port = tcp_server_socket.accept()
        print("客户端连接成功:", ip_port)
        # 当客户端和服务端建立连接成功以后,需要创建一个子线程,不同子线程负责接收不同客户端的消息
        sub_thread = threading.Thread(target=handle_client_request, args=(service_client_socket, ip_port))
        # 设置守护主线程
        sub_thread.setDaemon(True)
        # 启动子线程
        sub_thread.start()
 
    # tcp服务端套接字可以不需要关闭,因为服务端程序需要一直运行
    # tcp_server_socket.close()

客户端程序:

# -*- coding: UTF-8 -*-
import socket               # 导入 socket 模块

if __name__ == '__main__':
    sk = socket.socket()         # 创建 socket 对象

    host = socket.gethostname() # 获取本地主机名
    port = 9090                # 设置端口号

    sk.connect((host, port))
    message = "connect······"
    sk.sendall(message.encode())
    print(sk.recv(1024).decode())

    i = 0
    while True:
        try:
            message = input(">>>")
            sk.send(message.encode())
            print(sk.recv(1024).decode())
        except KeyboardInterrupt:
            break
        
    sk.close()

运行结果:
在这里插入图片描述

Socket实例化

格式:

sk = socket.socket(family,type[,protocal])

family:地址族,常用地址族有AF_INET、AF_INET6、AF_LOCAL(或称AF_UNIX、UNIX域Socket)、AF_ROUTE等。默认为AF_INET,通常使用默认即可。

type:Socket类型
SOCK_STREAM,TCP类型(默认)
SOCK_DGRAM,UDP类型
SOCK_RAM,原始类型,允许对底层协议如IP或ICMP进行直接访问,基本用不到。

protocol:可选项,使用的协议,通常赋值“0”,由系统自动选择。

Socket常用函数

  1. bind()
    服务端 Socket调用,将之前创建Socket与指定的IP地址和端口进行绑定。
sk.bind(("127.0.0.1",9090))
  1. listen()
    用于在使用TCP的服务端开启监听模式。
#服务端开启一个监听,最大连接数为5
sk.listen(128)
  1. accept()
    用于在使用TCP的服务端接收连接,一般是阻塞态。接受TCP连接并返回(conn, adress),其中conn为新的套接字对象,可以用来接收和发送数据,address为连接客户端的地址。
socket_new, port = sk.accept()
  1. connect()
    用于在使用TCP的客户端去连接服务端时使用
sk.connect(("127.0.0.1", 9090))
  1. send()
    用于在使用TCP时发送数据,可能未将指定的内容全部发送。
sk.send(string[,flag])   #返回值是发送字节数量
  1. sendall()
    用于在使用TCP时发送数据,完整发送TCP数据。
# 发送一段字符到Socket
sk.sendall("Hello!".encode())
# 成功返回None,失败抛出异常 
  1. recv()
    用于使用TCP接收数据。
sk.recv(bufsize[,flag])
# bufsize指定最多可以接收的数量
  1. sendto()
    用于使用UDP时发送数据

  2. recvfrom()
    UDP专用,接收数据,返回远端的IP地址和端口

  3. close()
    关闭Socket

猜你喜欢

转载自blog.csdn.net/qq_43619058/article/details/125114332