Sockets 套接字连接后的Python代码只执行一次

Sockets 套接字连接后的Python代码只执行一次,sockets,python-3.x,pyserial,Sockets,Python 3.x,Pyserial,该计划的目的是什么: 我想使用套接字将一些命令从客户机发送到服务器,然后服务器使用串口将这些命令发送到Arduino。我希望服务器将来做的另一件事是定期向Arduino发送其他命令,而不从客户端获取任何输入,因此套接字需要是非阻塞的,或者需要有另一种方法来运行与套接字代码分开的代码 问题是,应该向Arduino发送命令的部分只运行一次 在Pycharm中使用调试器后,我想到的是,问题是以下行在建立连接后阻塞,因此不允许运行其余代码 conn, addr = s.accept() 这是正确的,

该计划的目的是什么:

我想使用套接字将一些命令从客户机发送到服务器,然后服务器使用串口将这些命令发送到Arduino。我希望服务器将来做的另一件事是定期向Arduino发送其他命令,而不从客户端获取任何输入,因此套接字需要是非阻塞的,或者需要有另一种方法来运行与套接字代码分开的代码

问题是,应该向Arduino发送命令的部分只运行一次

在Pycharm中使用调试器后,我想到的是,问题是以下行在建立连接后阻塞,因此不允许运行其余代码

conn, addr = s.accept() 
这是正确的,还是有其他问题

我曾尝试将套接字设置为非阻塞,但当我这样做时,我得到一个错误

"BlockingIOError: [WinError 10035] A non-blocking socket operation could not be completed immediately"
我有一些C/C++和C#的基本知识,而且对Python还是新手

server.py

import socket
import serial
import sys
from _thread import *
import threading
import queue

# command that the client sends are "ON" and "OFF"

class serialConnect:
    comPort =' '
    baudrate = 115200
    myserial = serial.Serial('COM5', baudrate)
    def serialstart(self):
       # self.comPort = input('Comport: ')
        try:
            self.myserial.open()
        except IOError:
            print('Port is already open!')

    def serialRead(self):
        data = self.myserial.read(16)
        data.decode('UTF-8')
        return data

    def serialWrite(self, data):
        data += '\n'        #the arduino needs a \n after each command.
        databytes = data.encode('UTF-8')
        self.myserial.write(databytes)
        print('send data: ', databytes)


def threaded_client(conn, dataqueue):
    data = {bytes}
    conn.send(str.encode('welcome, type your info \n'))
    while True:
        data = conn.recv(2048)
        if not data:
            break
        reply = 'server output: ' + data.decode('UTF-8')
        dataqueue.put(data.decode('UTF-8'))
        print("Items in queue: ",dataqueue.qsize())
        #conn.sendall(str.encode(reply))
        print("Recieved data in threaded_client: ", data.decode('UTF-8') + '\n')

    conn.close()

def Main():

    ser = serialConnect()
    host = ''
    port = 5555
    dataRecieved = 'hello'
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(2)
    s.setblocking(1)   #when set to non-blocking error occurs : "BlockingIOError: [WinError 10035] A non-blocking socket operation could not be completed immediately"
    workQueue = queue.Queue(10)

    try:
        s.bind((host,port))
    except socket.error as e:
        print(str(e))

    s.listen(5)
    print('waiting for a connection')

    while True:
        try:
            conn, addr = s.accept() #once connection is established it blocks?
            print('connected to: ' + addr[0] + ':' + str())
            t = threading.Thread(target=threaded_client, args=(conn, workQueue))
            t.daemon = True
            t.start()

        except:
            e = sys.exc_info()
            print('Error:', e)

        # This section of code is only run once, doesn't matter if put inside try block or not. :(
        dataRecieved = workQueue.get()
        print('The recieved data: ', dataRecieved)
        ser.serialstart()
        ser.serialWrite(dataRecieved)


if __name__ == '__main__':
    Main()
import socket



def Main():
    host = '127.0.0.1'
    port = 5555

    message = "<,R,G,B,>"
    mySocket = socket.socket()
    mySocket.connect((host, port))

    while message != 'q':
        message = input(" -> ")
        mySocket.send(message.encode())
    mySocket.close()




if __name__ == '__main__':
    Main()
client.py

import socket
import serial
import sys
from _thread import *
import threading
import queue

# command that the client sends are "ON" and "OFF"

class serialConnect:
    comPort =' '
    baudrate = 115200
    myserial = serial.Serial('COM5', baudrate)
    def serialstart(self):
       # self.comPort = input('Comport: ')
        try:
            self.myserial.open()
        except IOError:
            print('Port is already open!')

    def serialRead(self):
        data = self.myserial.read(16)
        data.decode('UTF-8')
        return data

    def serialWrite(self, data):
        data += '\n'        #the arduino needs a \n after each command.
        databytes = data.encode('UTF-8')
        self.myserial.write(databytes)
        print('send data: ', databytes)


def threaded_client(conn, dataqueue):
    data = {bytes}
    conn.send(str.encode('welcome, type your info \n'))
    while True:
        data = conn.recv(2048)
        if not data:
            break
        reply = 'server output: ' + data.decode('UTF-8')
        dataqueue.put(data.decode('UTF-8'))
        print("Items in queue: ",dataqueue.qsize())
        #conn.sendall(str.encode(reply))
        print("Recieved data in threaded_client: ", data.decode('UTF-8') + '\n')

    conn.close()

def Main():

    ser = serialConnect()
    host = ''
    port = 5555
    dataRecieved = 'hello'
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(2)
    s.setblocking(1)   #when set to non-blocking error occurs : "BlockingIOError: [WinError 10035] A non-blocking socket operation could not be completed immediately"
    workQueue = queue.Queue(10)

    try:
        s.bind((host,port))
    except socket.error as e:
        print(str(e))

    s.listen(5)
    print('waiting for a connection')

    while True:
        try:
            conn, addr = s.accept() #once connection is established it blocks?
            print('connected to: ' + addr[0] + ':' + str())
            t = threading.Thread(target=threaded_client, args=(conn, workQueue))
            t.daemon = True
            t.start()

        except:
            e = sys.exc_info()
            print('Error:', e)

        # This section of code is only run once, doesn't matter if put inside try block or not. :(
        dataRecieved = workQueue.get()
        print('The recieved data: ', dataRecieved)
        ser.serialstart()
        ser.serialWrite(dataRecieved)


if __name__ == '__main__':
    Main()
import socket



def Main():
    host = '127.0.0.1'
    port = 5555

    message = "<,R,G,B,>"
    mySocket = socket.socket()
    mySocket.connect((host, port))

    while message != 'q':
        message = input(" -> ")
        mySocket.send(message.encode())
    mySocket.close()




if __name__ == '__main__':
    Main()

为感兴趣的人重构服务器代码。

我不确定这是否符合标准,但它正在发挥作用

import serial
import socket
import queue
import sys
import threading

class serialConnect:
    comPort = 'COM5'
    baudrate = 115200
    myserial = serial.Serial(comPort, baudrate)

    def serial_run(self):
       # self.comPort = input('Comport: ')
        try:
            if not self.myserial.isOpen():
                self.myserial.open()
            else:
                print('Port is already open!')
        except IOError as e:
            print('Error: ', e)

    def serial_read(self):
        data = self.myserial.read(16)
        data.decode('UTF-8')
        return data

    def serial_write(self, data):
        data += '\n'        #the arduino needs a \n after each command.
        databytes = data.encode('UTF-8')
        self.myserial.write(databytes)
        print('send data: ', databytes)


class socketServer:
    host = ''
    port = 5555
    soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    soc.setblocking(1)
    data_queue = queue.Queue(1)

    def __init__(self):
        try:
            self.soc.bind((self.host, self.port))
        except:
            print('Bind error: ', sys.exc_info())
        self.soc.listen(5)

    def socket_accept_thread(self):
        while True:
            try:
                print('Waiting for a new connection')
                conn, addr = self.soc.accept()
                client_thread = threading.Thread(target=self.threaded_client, args=(conn, self.data_queue))
                client_thread.daemon = True
                client_thread.start()
            except:
                print('Accept thread Error: ', sys.exc_info())

    def threaded_client(self, conn, data_queue):
        # conn.send(str.encode('welcome, type your info \n'))
        try:
            while True:
                data = conn.recv(2048)
                if not data:
                    break
                # reply = 'server output: ' + data.decode('UTF-8')
                data_queue.put(data.decode('UTF-8'))
                print("Items in queue: ", data_queue.qsize())
                # conn.sendall(str.encode(reply))
                print("Received data in threaded_client: ", data.decode('UTF-8'))
        except:
            print("Error: ", sys.exc_info())
        conn.close()

    def get_data(self):
        data = self.data_queue.get()
        return data


def Main():
    server = socketServer()
    arduino_conn = serialConnect()
    accept_thread = threading.Thread(target=server.socket_accept_thread)

    data_received = 'Nothing received'

    while True:
        if not accept_thread.is_alive():
            accept_thread.daemon = True
            accept_thread.start()

        arduino_conn.serial_run()
        data_received = server.get_data()
        arduino_conn.serial_write(data_received)

if __name__ == '__main__':
    Main()

为感兴趣的人重构服务器代码。

我不确定这是否符合标准,但它正在发挥作用

import serial
import socket
import queue
import sys
import threading

class serialConnect:
    comPort = 'COM5'
    baudrate = 115200
    myserial = serial.Serial(comPort, baudrate)

    def serial_run(self):
       # self.comPort = input('Comport: ')
        try:
            if not self.myserial.isOpen():
                self.myserial.open()
            else:
                print('Port is already open!')
        except IOError as e:
            print('Error: ', e)

    def serial_read(self):
        data = self.myserial.read(16)
        data.decode('UTF-8')
        return data

    def serial_write(self, data):
        data += '\n'        #the arduino needs a \n after each command.
        databytes = data.encode('UTF-8')
        self.myserial.write(databytes)
        print('send data: ', databytes)


class socketServer:
    host = ''
    port = 5555
    soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    soc.setblocking(1)
    data_queue = queue.Queue(1)

    def __init__(self):
        try:
            self.soc.bind((self.host, self.port))
        except:
            print('Bind error: ', sys.exc_info())
        self.soc.listen(5)

    def socket_accept_thread(self):
        while True:
            try:
                print('Waiting for a new connection')
                conn, addr = self.soc.accept()
                client_thread = threading.Thread(target=self.threaded_client, args=(conn, self.data_queue))
                client_thread.daemon = True
                client_thread.start()
            except:
                print('Accept thread Error: ', sys.exc_info())

    def threaded_client(self, conn, data_queue):
        # conn.send(str.encode('welcome, type your info \n'))
        try:
            while True:
                data = conn.recv(2048)
                if not data:
                    break
                # reply = 'server output: ' + data.decode('UTF-8')
                data_queue.put(data.decode('UTF-8'))
                print("Items in queue: ", data_queue.qsize())
                # conn.sendall(str.encode(reply))
                print("Received data in threaded_client: ", data.decode('UTF-8'))
        except:
            print("Error: ", sys.exc_info())
        conn.close()

    def get_data(self):
        data = self.data_queue.get()
        return data


def Main():
    server = socketServer()
    arduino_conn = serialConnect()
    accept_thread = threading.Thread(target=server.socket_accept_thread)

    data_received = 'Nothing received'

    while True:
        if not accept_thread.is_alive():
            accept_thread.daemon = True
            accept_thread.start()

        arduino_conn.serial_run()
        data_received = server.get_data()
        arduino_conn.serial_write(data_received)

if __name__ == '__main__':
    Main()

您的命名约定是C风格的。Python对除类之外的任何东西都使用像这样的名称。此外,您应该使用
with
语句,而不是显式的
。close()
accept
应该阻塞,直到您获得连接。一旦您接受了第一个连接,您的代码就会产生一个单独的线程来处理该连接,但是主线程将运行其循环的其余部分(一次),然后再次执行
accept
。因此,它将阻塞,直到您获得另一个连接。如果这不是你想要的,你需要重新构造你的代码。谢谢你的评论。我已经重构了代码,现在它正按照我想要的方式工作(至少现在是这样)。查看新服务器代码的编辑,所有其他代码保持不变。请尝试将
sys.exc_info()
写入
SQL
。不要打印控制台所有异常!打印始终在
上工作构建应用程序时
,您已经获得了
SQL
连接(用于解决方案)。您的命名约定是C#风格。Python对除类之外的任何东西都使用像这样的名称。此外,您应该使用
with
语句,而不是显式的
。close()
accept
应该阻塞,直到您获得连接。一旦您接受了第一个连接,您的代码就会产生一个单独的线程来处理该连接,但是主线程将运行其循环的其余部分(一次),然后再次执行
accept
。因此,它将阻塞,直到您获得另一个连接。如果这不是你想要的,你需要重新构造你的代码。谢谢你的评论。我已经重构了代码,现在它正按照我想要的方式工作(至少现在是这样)。查看新服务器代码的编辑,所有其他代码保持不变。请尝试将
sys.exc_info()
写入
SQL
。不要打印控制台所有异常!打印始终在
上工作构建应用程序时
,您已获得
SQL
连接(用于解决方案)。