使用Python

时间:2016-06-24 13:51:12

标签: python c++ multithreading sockets tcp

首先,我想提一下,在尝试将其集成到我自己的GUI之前,我已经经历了很多套接字线程教程,但我仍然认为自己对这个主题还是比较新的。

我有一个用python编写的服务器,它打开一个套接字并通过localhost启动一个线程,并监听客户端的端口:

def StartThread():
     tcpsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
     tcpsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
     tcpsock.bind((TCP_IP, TCP_PORT))
     threads = []
     tcpsock.listen(5)
     print "Waiting for incoming connections from client..."
     (conn, (ip,port)) = tcpsock.accept()
     print 'Got connection from ', (ip,port)
     newthread = ClientThread(ip,port,conn, 1)
     newthread.start()
     return newthread

这是ClientThread类:

class ClientThread(Thread):

     def __init__(self,ip,port,sock, status):
         Thread.__init__(self)
         self.ip = ip
         self.port = port
         self.sock = sock
         self.status = 1
         print " New thread started for "+ip+":"+str(port)

运行服务器代码后,单击C ++ GUI上的一个按钮,该按钮根据Microsoft Winsock客户端模板运行客户端代码StartConnection()。

void CPSR_CRSDlg::OnBnClickedInit2()
{
    if(!checkTimerStarted())
    // Set mmtimer to aquire the data
    {
        m_ntimerID = timeSetEvent(  TIMERINTRRVAL,                               
                                    1,                                   
                                    timerHandler,                         
                                    0,                        
                                    TIME_PERIODIC);  
        SetTimer(1,TIMERINTRRVAL_2,NULL); 
        m_bTimer_started = true;

    }
    StartConnection();
}

连接确实成功启动,python代码打印出连接和线程的地址,但随后我的GUI冻结,这样我就无法点击任何其他按钮来实际通过连接发送数据。

为什么我的申请会冻结?我没有正确地实例化线程吗?

StartConnection()代码不在msdn网站上,但如果需要,这里是我稍加修改的版本:

void StartConnection(){ 
    //printf("Connection Starting... \n");
    WSADATA wsaData;
    ConnectSocket = INVALID_SOCKET;
    struct addrinfo *result = NULL,
                    *ptr = NULL,
                    hints;

    int argc = 2;

    // Validate the parameters
    if (argc != 2) {
        printf("usage: %s server-name\n", "client");
        return;
    }

    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (iResult != 0) {
        printf("WSAStartup failed with error: %d\n", iResult);
        return;
    }

    ZeroMemory( &hints, sizeof(hints) );
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    // Resolve the server address and port
    //iResult = getaddrinfo(argv[1], DEFAULT_PORT, &hints, &result);
    iResult = getaddrinfo("localhost", DEFAULT_PORT, &hints, &result);
    if ( iResult != 0 ) {
        printf("getaddrinfo failed with error: %d\n", iResult);
        WSACleanup();
        return;
    }

    // Attempt to connect to an address until one succeeds
    for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) {

        // Create a SOCKET for connecting to server
        ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, 
            ptr->ai_protocol);
        if (ConnectSocket == INVALID_SOCKET) {
            printf("socket failed with error: %ld\n", WSAGetLastError());
            WSACleanup();
            return;
        }

        // Connect to server.
        iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
        if (iResult == SOCKET_ERROR) {
            closesocket(ConnectSocket);
            ConnectSocket = INVALID_SOCKET;
            continue;
        }
        break;
    }

    freeaddrinfo(result);

    if (ConnectSocket == INVALID_SOCKET) {
        printf("Unable to connect to server!\n");
        WSACleanup();
        return;
    }
    return;
}

void StopConnection(){
    closesocket(ConnectSocket);
    WSACleanup();
    return;
}

void SendJointValues(double *joints){
    iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
    j = parseJSON(joints[0],joints[1],joints[2],joints[3], \
        joints[4],joints[5]);
    int x = send(ConnectSocket, j, strlen(j), 0);
    //iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
}

修改

在我通过服务器发送数据后,GUI会再次响应,然后客户端成功发回一次数据。但是在这次交换之后,GUI再次冻结,直到发送更多数据。

以下是服务器的发送+接收部分:

def receiveData(self):
    while (self.status == 1):
        joints = [0,0,0,0,0,0]
        self.sock.sendall('send')
        print "Data Sent!"
        data = self.sock.recv(4096)
        print "Data received: ", data
        self.checkStatus(data)
        print "Status is: ", self.status

        if (self.status == 1):
            data_loaded = json.loads(data)
            joints = self.createJointArr(data_loaded['Joints'])
            time.sleep(0.5)
            print joints
            return joints

在此Timer函数中调用客户端中的SendJointValues():

void CPSR_CRSDlg::OnTimer(UINT_PTR nIDEvent)
{

    CString str;
    long Position;
    double engPosition;
    double dblPosition;
    double dblSpeed;
    bool ret;

    // Arch
    USB4_01.Controller_3.getEncoderPosition(Position);
    countTodegree(Position,engPosition,ARCH);
    str.Format(_T("%10.2f"),engPosition);
    m_staPosArch.SetWindowText(str);

    // Wrist Pitch
    USB4_01.Controller_2.getEncoderPosition(Position);
    countTodegree(Position,engPosition,TILT);
    str.Format(_T("%10.2f"),engPosition);
    m_staPosPitch.SetWindowText(str);

    // Linear
    USB4_02.Controller_1.getEncoderPosition(Position);
    countTodegree(Position,engPosition,LINEAR);
    str.Format(_T("%10.2f"),engPosition);
    m_staPosLinear.SetWindowText(str);

    // Turret
    USB4_02.Controller_2.getEncoderPosition(Position);
    countTodegree(Position,engPosition,TURRET);
    str.Format(_T("%10.2f"),engPosition);
    m_staPosTurret.SetWindowText(str);

    // Roll
    USB4_02.Controller_4.getEncoderPosition(Position);
    countTodegree(Position,engPosition,ROLL);
    str.Format(_T("%10.2f"),engPosition);
    m_staPosRoll.SetWindowText(str);

    // Drill/Tool
    USB4_02.Controller_3.getEncoderPosition(Position);
    countTodegree(-Position,engPosition,DRILL);
    str.Format(_T("%10.2f"),engPosition);
    m_staPosDrill.SetWindowText(str);

    // For Penetrate joint
    if(JntPenetration.isInitialized())
    {
        // Get Position feedback
        ret = JntPenetration.getPosition(dblPosition); 
        if(ret) // get position feedback successfully
        {
            Position = (long) dblPosition;
            countTodegree(Position,engPosition,PENETRATE);
            str.Format(_T("%10.2f"),engPosition);
            m_staPosPenetrate.SetWindowText(str);
            m_dCurentPentrationPosition = engPosition;
        }
        // Get Speed feedback;
        if(m_bDrilling_started)
        {
            // Penetration position close enough AND At least on cycle reached
            if( (abs(engPosition - m_dDrilling_target_position) < 0.1) &&(m_Direction_Changed == true))
                m_bPenetrationStopped = true;
            else
                m_bPenetrationStopped = false;
            //JntPenetration.getSpeed(dblSpeed); 
            //if(dblSpeed < .05 )
            //  m_bPenetrationStopped = true;
            //else
            //  m_bPenetrationStopped = false;      
        }

    }

    SendJointValues(JointArray);

    // For drilling motion control
    if(m_bDrilling_started)
        drilingProcedure();

    CDialog::OnTimer(nIDEvent);
}

0 个答案:

没有答案