树莓派之linux网络编程:socket非阻塞模式实现,方便调试PID

最近开始左pid调节了,多环串级PID,总共6个参数,每次都要改参数,重新启动太麻烦,于是计划用pythonGUI编程结合socket通信,做一个假单多pid调节。花了几天时间,功能实现了,虽然bug还不少,能用了。
树莓派之linux网络编程:socket非阻塞模式实现,方便调试PID_第1张图片
界面很简单,里面用到了python,tkinter,socket,多线程等库。由于socket默认是阻塞多,这里需要做成非阻塞的形式,才不至于等待数据多接收而等待,这样程序没有意义了。

刚才试了,确实可以实时改变PID的数值,而且飞机也有反应。

def on_start(self):
global online
try:
while True:
try:
server.bind((IP, PORT)) #绑定IP和端口
break
except BlockingIOError as e:
continue
server.listen(10)
online = True
start_new_thread(self.accept_connections, ()) #如果有新多连接,开始2刚线程
except Exception as e:
raise(e)
return True

def accept_connections(self):
    global online
    global clients
    global conn
    print("wait for new accept")
    while online:
        try:
            conn_found = False
            conn, addr = server.accept()
          #  flags = fcntl(connetfd, F_GETFL, 0);
        #fcntl(connetfd, F_SETFL, flags | O_NONBLOCK);
            print("new accept")
            start_new_thread(self.recv, (conn,) )#一个线程接收,一个线程发送。
            start_new_thread(self.send, (conn,) )
            break
        except BlockingIOError as e:
            continue
        except Exception as e:
            raise(e)

def recv(self, c):

    while True :
        msg=c.recv(2048).decode()
       # print(float(msg))
        if not msg :
            break
        lock.acquire() 
        self.data[0] = float(msg)
        lock.release()  

def send(self, c):
    while True:
        if self.Flag :
            lock.acquire() 

            da = '#'.join(str(i) for i in self.data)
            print(len(da))
            c.sendall(da.encode())
            self.Flag = False
            lock.release()
        else:
            pass  

关键代码就上面这些。这是服务端。而客户端如下:

/*将套接字绑定到服务器的网络地址上*/
if(connect(client_sockfd,(struct sockaddr *)&remote_addr,sizeof(struct sockaddr))<0)
{
    perror("connect error");
    return 1;
}
 int fdflags = fcntl(client_sockfd, F_GETFL, 0);
if(fcntl(client_sockfd, F_SETFL, fdflags | O_NONBLOCK) < 0)
{
    syslog(LOG_ERR, "%s:%d, fcntl set nonblock failed", __FILE__, __LINE__);
    close(client_sockfd);
    exit(1);
}

客户端关键代码就是fcntl这里,设置非阻塞模式。这样当调用recv的时候,可以实现非阻塞的模式。非常方便。如果发现无法和server连接,考虑是否是防火墙的问题。

你可能感兴趣的:(树梅派,linux)