Python实现TCP客户端和服务器(多线程)

收藏链接
服务端要做的事有这些:
Step 1:创建ServerSocket对象,绑定监听的端口
Step 2:调用accept()方法监听客户端的请求
Step 3:连接建立后,通过输入流读取客户端发送的请求信息
Step 4:通过输出流向客户端发送响应信息
Step 5:关闭相关资源

  1. 用于区分不同的应用程序
  2. 端口号的范围为0-65535,其中0-1023未系统的保留端口,我们的程序尽可能别使用这些端口!
  3. IP地址和端口号组成了我们的Socket,Socket是网络运行程序间双向通信链路的终结点, 是TCP和UDP的基础!
  4. 常用协议使用的端口:HTTP:80,FTP:21,TELNET:23

学习链接
Python中socket 类(客户端)的介绍
导入 socket 模块
import socket

创建客户端socket 对象
socket.socket(AddressFamily, Type)

参数说明:
AddressFamily 表示IP地址类型, 分为IPv4和IPv6
Type 表示传输协议类型

方法说明:
connect((host, port)) 表示和服务端套接字建立连接, host是服务器ip地址,port是应用程序的端口号
send(data) 表示发送数据,data是二进制数据
recv(buffersize) 表示接收数据, buffersize是每次接收数据的长度

在Python中创建一个tcp客户端:

import socket

if __name__ == '__main__':

    # 1 创建客户端套接字对象tcp_client_1
    # 参数介绍:AF_INET 代表IPV4类型, SOCK_STREAM代表tcp传输协议类型 ,注:AF_INET6代表IPV6
   
    tcp_client_1 = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

    # 2 通过客户端套接字的connect方法与服务器套接字建立连接  
    # 参数介绍:前面的ip地址代表服务器的ip地址,后面的61234代表服务端的端口号 。
    
    tcp_client_1.connect(("192.168.100.100",61234))

    # 将编号好的数据存到变量send_data中,注:encode(encoding='utf-8)是将数据转换成utf-8的格式发送给服务器
    send_data = "你好,服务器,我是客户端1号".encode(encoding='utf-8')
     
    # 3 通过客户端套接字的send方法将数据发送给服务器
    tcp_client_1.send(send_data)

    # 4 通过客户端套接字的recv方法来接受服务器返回的数据存到变量recv_data中,1024是可接收的最大字节数。
    recv_data = tcp_client_1.recv(1024)
    
    # 将接收到的服务器数据recv_data通过decode方法解码为utf-8
    print(recv_data.decode(encoding = 'utf-8'))

    # 5 最后关闭客户端套接字连接
    tcp_client_1.close()

Python中socket 类(服务器)的介绍
导入 socket 模块
import socket

创建服务端 socket 对象
socket.socket(AddressFamily, Type)

参数说明:
AddressFamily 表示IP地址类型, 分为IPv4和IPv6
Type 表示传输协议类型

方法说明:
bind((host, port)) 表示绑定端口号, host 是 ip 地址,port 是端口号,ip 地址一般不指定,表示本机的任何一个ip地址都可以。
listen (backlog) 表示设置监听,backlog参数表示最大等待建立连接的个数。
accept() 表示等待接受客户端的连接请求
send(data) 表示发送数据,data 是二进制数据
recv(buffersize) 表示接收数据, buffersize 是每次接收数据的长度

**在Python中创建一个tcp服务器:**

#导入socket模块
import socket

if __name__ == '__main__':
    # 创建tcp服务端套接字
    # 参数同客户端配置一致,这里不再重复
    tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
   
    **# 设置端口号复用,让程序退出端口号立即释放,否则的话在30秒-2分钟之内这个端口是不会被释放的,这是TCP的为了保证传输可靠性的机制。
    tcp_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)**
   
    # 给客户端绑定端口号,客户端需要知道服务器的端口号才能进行建立连接。IP地址不用设置,默认就为本机的IP地址。
    tcp_server.bind(("", 61234))
    ##s.bind(("0.0.0.0",1234))  #网卡 ip地址0.0.0.0b表示主机任意网卡都可以与此连接 

   
    # 设置监听
    # 128:最大等待建立连接的个数, 提示: 目前是单任务的服务端,同一时刻只能服务与一个客户端,后续使用多任务能够让服务端同时服务与多个客户端
    # 不需要让客户端进行等待建立连接
    # listen后的这个套接字只负责接收客户端连接请求,不能收发消息,收发消息使用返回的这个新套接字tcp_client来完成
    tcp_server.listen(128)
   
    # 等待客户端建立连接的请求, 只有客户端和服务端建立连接成功代码才会解阻塞,代码才能继续往下执行
    # 1. 专门和客户端通信的套接字: tcp_client
    # 2. 客户端的ip地址和端口号: tcp_client_address
    tcp_client, tcp_client_address= tcp_server.accept()
    
    # 代码执行到此说明连接建立成功
    print("客户端的ip地址和端口号:", tcp_client_address)
   
    # 接收客户端发送的数据, 这次接收数据的最大字节数是1024
    recv_data = tcp_client.recv(1024)
   
    # 对服务器发来的数据进行解码保存到变量recv_content中
    recv_content = recv_data.decode(encoding = "utf-8")
    print("接收客户端的数据为:", recv_content)
    
    # 准备要发送给服务器的数据
    send_data = "好的,消息已收到".encode(encoding = "utf-8")
   
    # 发送数据给客户端
    tcp_client.send(send_data)
   
    # 关闭服务与客户端的套接字, 终止和客户端通信的服务
    tcp_client.close()
   
    # 关闭服务端的套接字, 终止和客户端提供建立连接请求的服务 但是正常来说服务器的套接字是不需要关闭的,因为服务器需要一直运行。
    # tcp_server.close()

搭建持续性多用户版的服务器:

# 导入套接字模块
import socket
# 导入线程模块
import threading

# 定义个函数,使其专门重复处理客户的请求数据(也就是重复接受一个用户的消息并且重复回答,直到用户选择下线)
def dispose_client_request(tcp_client_1,tcp_client_address):
    # 5 循环接收和发送数据
    while True:
        recv_data = tcp_client_1.recv(4096)
        
        # 6 有消息就回复数据,消息长度为0就是说明客户端下线了
        if recv_data:
            print("客户端是:", tcp_client_address)
            print("客户端发来的消息是:", recv_data.decode())
            send_data = "消息已收到,正在处理中...".encode()
            tcp_client_1.send(send_data)
        else:
            print("%s 客户端下线了..." % tcp_client_address[1])
            tcp_client_1.close()
            break

if __name__ == '__main__':

    # 1 创建服务端套接字对象
    tcp_server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

    # 设置端口复用,使程序退出后端口马上释放
    tcp_server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True)
  
    # 2 绑定端口
    tcp_server.bind(("",61234))
  
    # 3 设置监听
    tcp_server.listen(128)
  
    # 4 循环等待客户端连接请求(也就是最多可以同时有128个用户连接到服务器进行通信)
    while True:
        tcp_client_1 , tcp_client_address = tcp_server.accept()
        # 创建多线程对象
        thd = threading.Thread(target = dispose_client_request, args = (tcp_client_1,tcp_client_address))
        
        # 设置守护主线程  即如果主线程结束了 那子线程中也都销毁了  防止主线程无法退出
        # thd.setDaemon(True)
        
        # 启动子线程对象
        thd.start()

    # 7 关闭服务器套接字 (其实可以不用关闭,因为服务器一直都需要运行)
    # tcp_server.close()

总结:可以看到TCP服务器同时连接了两个用户,并且与每个用户进行了多次通信,直到客户端下线。

学习记录1server

import socket
new_socket =socket.socket()
ip="127.0.0.1"
port=8080
new_socket.bind((ip,port))
new_socket.listen(5)
while True:
    new_cil,addr =new_socket.accept() #建立链接 addr 返回端口号和地址 阻塞到有客户端接入
    new_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True)##断开后 端口立马释放 不占用端口
    print("新进来的地址是",addr)

    print(new_cil.recv(8080).decode())#接受客户端来的数据  recv参数最大的接受字长 请求数据 read
    new_cil.send("答案是6".encode(encoding='utf-8'))#发送数据给客户端  回应数据 write
    new_cil.close() #关闭链接

首先,客户端和服务端会分别新建一个socket,服务端的socket需要通过bind()来绑定上端口,启动listen()进行实时监听,并等待客户端的接入,即accept()。而客户端则需要通过服务器IP和端口两个参数来建立connect()连接,此时,服务器会得到有新客户端连接的信息,启动read()等待客户端数据的传人,客户端如果成功接收到服务端的连接成功后,继续执行write()来向服务端发生数据,同理,服务端也使用这样的模式回馈客户端的数据,知道客户端关闭,服务端会收到客户端退出连接的消息,服务器重新进入等待状态,等待新客户端的进入。
client

import socket
ip ="127.0.0.1"
port =8080
new_socket =socket.socket()#创建socket对象
new_socket.connect((ip,port)) #链接
new_socket.send("服务器,帮我算一下5+1等于多少".encode(encoding='utf-8')) #发送数据 回应数据 write 对应server的read
back_str =  new_socket.recv(port).decode()#结束数据 请求数据 read 对应server的write
new_socket.close()

你可能感兴趣的:(笔记,python,udp,tcp/ip)