多线程实现socket通信服务器端代码
- import socket
- import threading
- class MyServer(object):
- def __init__(self):
- # 初始化socket
- self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- # 设置服务器IP地址
- host = '192.168.152.1'
- # 设置服务器端口号
- port = 4321
- # 绑定IP地址和端口
- self.server.bind((host, port))
- # 设置最大监听数
- self.server.listen(5)
- # 设置一个字典,用来保存每一个客户端的连接和身份信息
- self.socket_mapping = {}
- # 设置接收的最大字节数
- self.maxSize = 1024
- def run(self):
- while True:
- socket, addr = self.server.accept()
- # 发送信息,提示客户端已成功连接
- socket.send('success!'.encode('utf-8'))
- # 将客户端socket等信息存入字典
- self.socket_mapping[socket] = addr
- # 创建线程,负责获取键盘输入并发送给客户端
- threading.Thread(target=self.send_to_client, args=(socket,)).start()
- # 创建线程,负责接收客户端信息并转发给其他客户端
- threading.Thread(target=self.recv_from_client, args=(socket,)).start()
- def send_to_client(self, socket):
- """
- 获取键盘输入并发送给客户端
- :param socket:
- :return:
- """
- while True:
- info = input()
- if info == "quit":
- socket.close()
- for socket in self.socket_mapping.keys():
- socket.send(info.encode("utf-8"))
- def recv_from_client(self, socket):
- """
- 接收客户端信息并转发给其他客户端
- :param socket:
- :return:
- """
- while True:
- recv_info = socket.recv(self.maxSize).decode('utf-8')
- print('client{} say: '.format(self.socket_mapping[socket]), recv_info)
- for i_socket in self.socket_mapping.keys():
- if i_socket != socket:
- i_socket.send(recv_info.encode("utf-8"))
- my_server = MyServer()
- my_server.run()
复制代码 多进程实现socket通信服务器端代码
存在的问题:在与客户端连通后,需要服务器先发送两条消息,之后才能正常通信。- import os
- import socket
- import sys
- from multiprocessing import Process, Manager
- class MyServer(object):
- def __init__(self):
- # 初始化socket
- self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- # 设置服务器IP地址
- host = '192.168.152.1'
- # 设置服务器端口号
- port = 4321
- # 绑定IP地址和端口
- self.server.bind((host, port))
- # 设置最大监听数
- self.server.listen(5)
- # 设置一个字典,用来保存每一个客户端的连接和身份信息
- self.socket_mapping = Manager().dict()
- # 设置接收的最大字节数
- self.maxSize = 1024
- # 进程锁
- self.share_lock = Manager().Lock()
- def run(self):
- fn = sys.stdin.fileno()
- while True:
- socket, addr = self.server.accept()
- # 发送信息,提示客户端已成功连接
- socket.send('success!'.encode('utf-8'))
- # 将客户端socket等信息存入字典
- self.modify_mapping(self.socket_mapping, addr, socket, self.share_lock)
- # 创建进程,负责获取键盘输入并发送给客户端
- Process(target=self.send_to_client, args=(addr, fn)).start()
- # 创建进程,负责接收客户端信息并转发给其他客户端
- Process(target=self.recv_from_client, args=(addr,)).start()
- def send_to_client(self, addr, fn):
- """
- 获取键盘输入并发送给客户端
- :param addr:
- :return:
- """
- sys.stdin = os.fdopen(fn)
- while True:
- info = sys.stdin.readline()
- if info == "quit":
- self.socket_mapping[addr].close()
- for socket in self.socket_mapping.values():
- socket.send(info.encode("utf-8"))
- def recv_from_client(self, addr):
- """
- 接收客户端信息并转发给其他客户端
- :param addr:
- :return:
- """
- while True:
- recv_info = self.socket_mapping.get(addr).recv(self.maxSize).decode('utf-8')
- print('client{} say: '.format(addr), recv_info)
- for i_addr in self.socket_mapping.keys():
- if i_addr != addr:
- self.socket_mapping.get(i_addr).send(recv_info.encode("utf-8"))
- @staticmethod
- def modify_mapping(share_var, share_key, share_value, share_lock):
- # 获取锁
- share_lock.acquire()
- # 修改数据
- share_var[share_key] = share_value
- # 释放锁
- share_lock.release()
- if __name__ == "__main__":
- my_server = MyServer()
- my_server.run()
复制代码 异步IO实现socket通信服务器端代码
存在的问题:通信时需要相互发送几次消息后,各自才会收到之前的消息并打印。- import socket
- import asyncio
- import select
- class MyServer(object):
- def __init__(self):
- # 初始化socket
- self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- # 设置服务器IP地址
- host = '192.168.152.1'
- # 设置服务器端口号
- port = 4321
- # 绑定IP地址和端口
- self.server.bind((host, port))
- # 设置最大监听数
- self.server.listen(5)
- # 设置一个字典,用来保存每一个客户端的连接和身份信息
- self.socket_mapping = {self.server: None} # 这里存入self.server是为了充当select.select参数
- # 设置接收的最大字节数
- self.maxSize = 1024
- # 进入事件循环
- self.loop = asyncio.get_event_loop()
- def run(self):
- while True:
- # select监听请求对象
- rret, _, _ = select.select(self.socket_mapping.keys(), [], [])
- for r_socket in rret:
- if r_socket is self.server:
- socket, addr = r_socket.accept()
- # 发送信息,提示客户端已成功连接
- socket.send('success!'.encode('utf-8'))
- # 将客户端socket等信息存入字典
- self.socket_mapping[socket] = addr
- else:
- task = [self.send_to_client(r_socket), self.recv_from_client(r_socket)]
- self.loop.run_until_complete(asyncio.gather(*task))
- async def send_to_client(self, socket):
- """
- 获取键盘输入并发送给客户端
- :param socket:
- :return:
- """
- info = input()
- if info == "quit":
- socket.close()
- for socket in self.socket_mapping.keys():
- if socket != self.server:
- socket.send(info.encode("utf-8"))
- async def recv_from_client(self, socket):
- """
- 接收客户端信息并转发给其他客户端
- :param socket:
- :return:
- """
- recv_info = socket.recv(self.maxSize).decode('utf-8')
- print('client{} say: '.format(self.socket_mapping[socket]), recv_info)
- for i_socket in self.socket_mapping.keys():
- if i_socket != socket and i_socket != self.server:
- i_socket.send(recv_info.encode("utf-8"))
- my_server = MyServer()
- my_server.run()
复制代码 客户端代码(使用多线程)
- import socket
- import threading
- class MyClient(object):
- def __init__(self):
- # 初始化socket
- self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- # 设置服务器IP地址
- self.host = '192.168.152.1'
- # 设置服务器端口号
- self.port = 4321
- # 设置接收的最大字节数
- self.max_size = 1024
- def run(self):
- # 与服务器建立连接
- self.client.connect((self.host, self.port))
- # 创建线程,负责获取键盘输入并发送给服务器
- threading.Thread(target=self.sned_to_server).start()
- # 创建线程,接收服务器信息
- threading.Thread(target=self.recv_from_server).start()
- def sned_to_server(self):
- """
- 获取键盘输入并发送给服务器
- """
- while True:
- send_msg = input()
- self.client.send(send_msg.encode('utf-8'))
- if send_msg == 'quit':
- break
- self.client.close()
- def recv_from_server(self):
- """
- 接收服务器信息
- """
- while True:
- recv_info = self.client.recv(self.max_size).decode('utf-8')
- print('server{} say: '.format((self.host, self.port)), recv_info)
- my_client = MyClient()
- my_client.run()
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |