网络编程——C/S架构

370 阅读3分钟

开发流程:

软件开发模式:C/S架构 B/S架构

C/S架构:Client/Server架构

客户端5步走:
    导入模块
    import socket
    创建套接字对象(IPV4/TCP协议):
    tcp_client_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    和服务器端套接字建立连接,参数要求是元组类型:
    tcp_client_socket.connect(('192.168.13.22',8080))
    发送数据到服务器端:
    data = ''.encode()
    tcp_client_socket.send(data)
    
    **注意:**数据必须是字节流类型,encode(编码格式)方法 把字符串类型的数据转换为bytes字节流数据
              decode()方法 把字节流转换为字符串,编码格式可以是gbk和utf-8,可以不写
    接收服务器端返回的数据recv(字节大小)
    recv_data = tcp_client_socket.recv(1024).decode()
    print('服务器端响应',recv_data)
    关闭套接字对象
    tcp_client_socket.close()
完整客户端代码:
    import socket
    # 创建套接字对象
    tcp_client_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    # 和服务器端套接字建立连接
    tcp_client_socket.connect(('192.168.13.30',8080))
    # 发送数据到服务器端
    data = '收到请回答'.encode('gbk')
    tcp_client_socket.send(data)
    #接受服务器端返回的数据recv(字节大小)
    recv_data = tcp_client_socket.recv(1024).decode('gbk')
    print('服务器端响应:',recv_data)
    #关闭套接字对象
    tcp_client_socket.close()
    
服务端7步走:
    导入模块 
    import socket
    创建套接字对象:
    tcp_server_socker = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    使用bind(host,port)方法绑定ip和端口:
    tcp_server_socker.bind(('192.168.13.30',8080))
    **注意:**绑定的ip地址可以为空,代表绑定本机
    使用listen()监听端口:
    tcp_server_socker.listen(128)
    **注意:**最大处理量为128,多余的请求需要等待
    准备接受客户端的连接请求:
    server_client_socket,ip_port = tcp_server_socker.accept()
    **注意:**返回一个元组,有两个元素,前者是一个套接字对象(是客户端连接到的服务器的信息),后者是一个客户端的ip和端口号
    **注意:**accept()有返回值,会产生一个新的套接字,后续的交互都通过这个新套接字来实现
    用新的套接字接收客户端的请求:
    recv_data = server_client_socket.recv(1024).decode('gbk')
    处理并返回数据给客户端:
    server_client_socket.send('返回客户端的信息').encode(‘gbk')
    关闭套接字对象:
    server_client_socket.close()
    tcp_client_socket.close()
完整服务端代码:
    # 导入模块
    import socket
    # 创建服务端对象
    tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    # 设置端口号
    tcp_server_socket.bind(('',8080))
    # 设置监听
    tcp_server_socket.listen(128)
    # 等待客户端发出请求,接受客户端的IP地址和端口号
    server_client_socket,ip_port = tcp_server_socket.accept()
    # 打印接受的内容
    print('客户端的ip地址和端口号:',ip_port)
    # 接收客户端发送的数据
    recv_data = server_client_socket.recv(1024)
    # 获取数据长度
    recv_data_length = len(recv_data)
    print('接收的数据长度为:',recv_data_length)
    #对接收到的数据进行编码
    recv_content = recv_data.decode('gbk')
    print('客户端发送的数据为:',recv_content)
    # 回复客户端(准备向客户端发送数据)
    send_data = '已收到请求'.encode('gbk')
    server_client_socket.send(send_data)
    # 关闭服务端与客户端的套接字连接
    server_client_socket.close()
    # 关闭客户端的连接
    tcp_server_socket.close()
服务端线程化:
    # 导入模块
    import socket
    import threading
    # 处理客户端的请求操作
    def handle_client_request(service_client_socket,ip_port):
        # 循环接收客户端发送的数据
        while True:
            # 接收客户端发送的数据
            recv_data = service_client_socket.recv(1024)
            if recv_data == True:
                    try:
                        print(recv_data.decode('gbk'),ip_port)
                        # 回复
                        # reply = input('请输入要回复客户端的内容:')
                        service_client_socket.send('服务器崩溃了...'.encode('gbk'))
                    except UnicodeDecodeError:
                        print(recv_data.decode('utf-8'), ip_port)
                        # 回复
                        # reply = input('请输入要回复客户端的内容:')
                        service_client_socket.send('服务器崩溃了...'.encode('utf-8'))
            else:
                print('客户端下线了:',ip_port)
                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(('', 8080))
        #设置监听
        tcp_server_socket.listen(128)
        # 循环等待接收客户端的连接请求
        while True:
            # 等待接收客户端的请求
            service_client_sockeet,ip_port = tcp_server_socket.accept()
            print('客户端连接成功:',ip_port)
            # 创建子线程,不同的子线程接收不同的客户端消息
            sub_thread = threading.Thread(target=handle_client_request,args=(service_client_sockeet,ip_port))
            # 守护主线程
            sub_thread.setDaemon(True)
            # 启动子线程
            sub_thread.start()
            
    **注意:**端口复用:为了让端口在服务器断开后迅速释放
                       在创建的套接字对象下面
                       tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)