Przeglądaj źródła

多线程处理

杨振 4 lat temu
rodzic
commit
82a290a1a2
3 zmienionych plików z 46 dodań i 36 usunięć
  1. 1 1
      .gitignore
  2. 31 26
      server.py
  3. 14 9
      test.py

+ 1 - 1
.gitignore

@@ -2,4 +2,4 @@
 .vscode
 
 *.pyc
-run.log
+*.log

+ 31 - 26
server.py

@@ -7,29 +7,31 @@ from threading import Thread
 from datetime import datetime
 
 # 广播端口
-port_broadcast = 8888
+broadcast_port = 8888
 
 # 管理端口
-port_manager = 9999
-
-server_info = json.dumps({'port_manager': port_manager})
+manager_port = 9999
 
 
 # 监听广播消息
 def listen_broadcast():
     s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
     s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
-    s.bind(('', port_broadcast))
-    logging.info('Listening broadcast at %s' % str(s.getsockname()))
+    s.bind(('', broadcast_port))
+    logging.info('* Listening broadcast at %s' % str(s.getsockname()))
 
     while True:
         data, address = s.recvfrom(2048)
         # 接收到客户端广播消息
         client_info = json.loads(data.decode('utf-8'))
-        logging.info('recv --> %s:%s' % (address, client_info))
-
-        # 将服务器信息发送给客户端
-        logging.info('send --> %s:%s' % (address, server_info))
+        logging.info('broadcast msg: %s from %s' % (client_info, address[0]))
+
+        # 将服务端配置信息发送给客户端
+        server_info = json.dumps({
+            'version': '0.1',
+            'manager_port': manager_port
+        })
+        logging.info('send to %s, %s' % (address[0], server_info))
         s.sendto(server_info.encode('utf-8'), address)
 
 
@@ -39,12 +41,12 @@ def message_handle(client_conn, client_info):
         try:
             msg_bytes = client_conn.recv(2048)
             msg_str = msg_bytes.decode(encoding='utf8')
-            logging.info('recv --> %s' % str(msg_str))
+            logging.info('recv from %s, %s' % (client_info[0], str(msg_str)))
             # msg_json = json.loads(msg_str)
             str_now = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
             client_conn.send(str_now.encode())
         except Exception as e:
-            logging.error(e)
+            logging.warning('client %s offline, %s' % (client_info[0], e))
             break
 
 
@@ -64,23 +66,26 @@ def init_logging(log_filename):
 
 
 if __name__ == '__main__':
-    init_logging('run.log')
+    init_logging('server.log')
     # 启动接收广播线程
     thread_broadcast = Thread(target=listen_broadcast)
     thread_broadcast.setDaemon(True)
     thread_broadcast.start()
 
     # 服务端监听
-    socket_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-    socket_server.bind(('', port_manager))
-    socket_server.listen(255)
-    logging.info('Server start at %s, wait for client connecting...' % str(socket_server.getsockname()))
-
-    while True:
-        client, info = socket_server.accept()
-        logging.info('client %s connect success' % str(info))
-
-        # 为每个客户端启一个线程
-        thread = Thread(target=message_handle, args=(client, info))
-        thread.setDaemon(True)
-        thread.start()
+    try:
+        socket_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        # 立即释放端口
+        socket_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+        socket_server.bind(('', manager_port))
+        socket_server.listen(128)
+        logging.info('* Server start at %s, waiting for client...' % str(socket_server.getsockname()))
+
+        while True:
+            # 为每个客户端启一个线程
+            client, info = socket_server.accept()
+            thread = Thread(target=message_handle, args=(client, info))
+            thread.setDaemon(True)
+            thread.start()
+    except KeyboardInterrupt as ki:
+        logging.warning('KeyboardInterrupt %s' % ki)

+ 14 - 9
test.py

@@ -5,36 +5,41 @@ import logging
 import socket
 import threading
 
-# 监听广播端口
-port_broadcast = 8888
+# 广播端口
+broadcast_port = 8888
 
 
 def listen_broadcast():
     s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
     s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
 
-    client_info = json.dumps({'hostname': 'kylin', 'mac_addr': '00:23:24:e4:f0:0b'})
+    client_info = json.dumps({
+        'hostname': 'kylin', 'mac_addr': '00:23:24:e4:f0:0b'
+    })
     logging.info('send --> %s' % client_info)
-    s.sendto(client_info.encode('utf-8'), ('<broadcast>', port_broadcast))
+    s.sendto(client_info.encode('utf-8'), ('<broadcast>', broadcast_port))
 
     data, address = s.recvfrom(2048)
     # 获取服务端信息
     server_info = json.loads(data.decode('utf-8'))
     logging.info('recv --> %s:%s' % (address, server_info))
 
-    # 连接服务端的socket
+    # 连接服务器管理
     threading.Thread(target=listen_socket, args=(address, server_info)).start()
 
 
 def listen_socket(address, server_info):
-    client = socket.create_connection((address[0], int(server_info['port_manager'])))
+    client = socket.create_connection((address[0], int(server_info['manager_port'])))
     logging.info('connect %s successfully.' % str(address))
-    client.send(b'hello server, i am client')
+    client_info = json.dumps({
+        'hello': 'hello'
+    })
+    client.send(client_info.encode('utf-8'))
 
     while True:
         response = client.recv(2048)
         logging.info('recv --> %s' % response.decode())
-        msg = input('please enter a answer: ')
+        msg = input('enter some message: ')
         ret = {'data': msg}
         json_str = json.dumps(ret)
         client.send(json_str.encode('utf-8'))
@@ -56,5 +61,5 @@ def init_logging(log_filename):
 
 
 if __name__ == '__main__':
-    init_logging('run.log')
+    init_logging('client.log')
     threading.Thread(target=listen_broadcast).start()