繁体   English   中英

从单个 python 脚本或 GUI 按钮运行服务器和客户端 python 脚本

[英]Running server and client python scripts from a single python script or GUI button

我一直在使用 python 服务器和客户端通信。 为了建立连接,通常,服务器需要先从单独的 python 脚本运行客户端,然后再运行客户端。

我现在想要的是让它自动化。 我想从单个 python 脚本或 GUI 按钮运行服务器和客户端。 我一直在尝试不同的方法,比如多处理和多线程,但它不起作用。

请指教。

下面的示例服务器和客户端代码:

服务器.py

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('0.0.0.0', 5005))
s.listen(1)
conn, addr = s.accept()
while 1:
    data = conn.recv(1024)
    print("received data",list(data))
    if not data:
        break
    conn.sendall(data)
conn.close()

客户端.py

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('0.0.0.0', 5005))
message = bytearray([1])
s.sendall(message)
data = s.recv(1024)
s.close()
print ('Received', repr(data))

我们可以通过分配两个不同的函数来处理它。 几点注意事项:

  • 当两个不同的线程试图在同一个 stream 中打印一些东西时,它们应该首先获取一个公共锁,以便它们按顺序打印一些东西。
  • 服务器开始侦听"0.0.0.0"意味着它已准备好接受来自任何地方的连接。 另一方面,当您在计算机上运行客户端时,您应该连接到localhost127.0.0.1而不是连接到0.0.0.0
import threading
import socket

stream_lock = threading.Lock()

def server_func():
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind(('0.0.0.0', 5005))
    s.listen(1)
    conn, addr = s.accept()
    while 1:
        data = conn.recv(1024)

        # Getting printing stream lock is important
        stream_lock.acquire()
        print("received data", list(data))
        stream_lock.release()
        if not data:
            break
        conn.sendall(data)
    conn.close()

def client_func():
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect(('127.0.0.1', 5005))
    message = bytearray([1, 2, 3])
    s.sendall(message)
    data = s.recv(1024)
    s.close()
    stream_lock.acquire()
    print('Received', repr(data))
    stream_lock.release()

t_server = threading.Thread(target=server_func).start()
t_client = threading.Thread(target=client_func).start()

# Output:
# received data [1, 2, 3]
# Received b'\x01\x02\x03'

我将@aminrd 的答案转换为 class object 并添加一些代码来存储从客户端接收到的数据还为需要了解每个步骤的人添加了一些注释

import socket
import threading
import json
import time


class Communication:
    stream_lock = threading.Lock()  # creating thread lock object

    def __init__(self):
        self.clientSocket = None
        self.serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # create socket and store
        self.STORED_DATA = {"function_name": "", "data": ""}  # sample stored data
        self.th = []  # threads list

    def server(self):
        self.serverSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,
                                     1)  # make reusing adress with different port
        self.serverSocket.bind(('0.0.0.0', 5005))  # bind socket with port
        self.serverSocket.listen(2)  # permitted client number
        print("Server is listening")
        while True:
            client, address = self.serverSocket.accept()  # welcome new client
            # send client data to new thread and process
            self.th.append(threading.Thread(target=self.listener, daemon=True, args=(client,)).start())

    def listener(self, client):
        while True:
            data = client.recv(2048)  # receive new data to store
            if data:
                # you can get data from any client and puch data to all clients(multiple status monitors)
                data_variable = json.loads(data.decode('utf-8'))  # decode byte to dict
                self.stream_lock.acquire()  # i'm not sure about usage of lock. wrong place ?
                if 'command' in data_variable and data_variable['command'] == 'write':
                    self.STORED_DATA = data_variable
                else:
                    # or you can do some server stuff and manipulate data
                    self.STORED_DATA['function_name'] = 1
                    self.STORED_DATA['data'] = 1
                self.stream_lock.release()
                data_string = json.dumps(self.STORED_DATA).encode('utf-8')  # convert stored data to bytes
                client.sendall(data_string)  # now send stored data to all clients

    def client(self):
        self.clientSocket.connect(('127.0.0.1', 5005))  # connect to server

    # this function is callable from outside of class
    # you can give new data to client to send to server
    def receive(self, new_data_string):
        self.clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # create socket for client
        self.clientSocket.connect(('127.0.0.1', 5005))  # connect to server
        data_string = json.dumps(new_data_string).encode('utf-8')  # convert data to bytes
        self.clientSocket.send(data_string)  # send to server
        data = self.clientSocket.recv(2048)  # receive server data
        if not data:
            print("no data")
            self.clientSocket.close()
        data_variable = json.loads(data.decode('utf-8'))  # convert data to dict
        self.stream_lock.acquire()
        self.stream_lock.release()
        self.clientSocket.close()
        return data_variable  # return received data


if __name__ == "__main__":
    x = Communication()
    t_server = threading.Thread(target=x.server, daemon=True).start()
    read = {"command": "read", "function_name": "", "data": ""}
    result = x.receive(read)
    print('Client Received', repr(result))
    time.sleep(1)
    write = {"command": "write", "function_name": "2", "data": "2"}
    result = x.receive(write)
    print('Client Received', repr(result))


暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM