客户端组织的Winsocket线程崩溃。

时间:2015-08-21 08:12:46

标签: c++ multithreading winsock

主要思想是:

第一个线程只是等待客户端的连接。所以这个线程是一个管理器(communicationthread)。 一旦accept == true,该线程就会创建另一个线程(线程向量),其中发生 recv 发送。 这是实施:

bool CServerClientCommunication::OpenConnectionForClient(int Port)
            {
            long rc;
            SOCKADDR_IN addr;

                rc=StartWinsock();
                if(rc!=0)
                {
                    return false;
                }

                server=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
                if(server==INVALID_SOCKET)
                {
                    return false;
                }

                memset(&addr,0,sizeof(SOCKADDR_IN));
                addr.sin_family=AF_INET;
                addr.sin_port=htons(Port);
                addr.sin_addr.s_addr=ADDR_ANY;

                rc=bind(server,(SOCKADDR*)&addr,sizeof(SOCKADDR_IN));
                if(rc==SOCKET_ERROR)
                {
                    return false;
                }

                long rc2=listen(server,10);
                if(rc2==SOCKET_ERROR)
                {
                    return false;
                }

            WAIT_FOR_CLIENT:
            if(Terminated)
            {
                return false;
            }
                // Accept Client to Serversocket
                client=accept(server,NULL,NULL);
                // Check if Accept failed
                if(client==INVALID_SOCKET)
                {
                    if( Clients.size()>0)
                       {
                           for (int i = 0; i < Clients.size(); i++)
                           {
                                if(Clients[i]->isKilled == true)
                                {
                                    Clients[i]->Terminate();
                                    Clients[i]->WaitFor();
                                    delete Clients[i];
                                    Clients[i] = NULL;
                                }
                           }
                       }
                    goto WAIT_FOR_CLIENT;
                }
                       CServerClientProcessing * ServerClientProcessing = new CServerClientProcessing(true);
                       ServerClientProcessing->FreeOnTerminate = false;
                       Clients.push_back(ServerClientProcessing);
                       ServerClientProcessing->client = client;
                       Sleep(100);
                       if( Clients.size()>0)
                       {
                           for (int i = 0; i < Clients.size(); i++)
                           {
                                if(Clients[i]->isKilled == true)
                                {
                                    Clients[i]->Terminate();
                                    Clients[i]->WaitFor();
                                    delete Clients[i];
                                    Clients[i] = NULL;
                                }
                           }
                       }
                       ServerClientProcessing->Resume();
                       goto WAIT_FOR_CLIENT;
            }

            int CServerClientCommunication::StartWinsock()
            {
                WSADATA wsa;
                return WSAStartup(MAKEWORD(2,0),&wsa);
            }

            bool CServerClientCommunication::GetConnectionStatus()
            {
                return server != -1;
            }

            //---------------------------------------------------------------------------
            void __fastcall CServerClientCommunication::Execute()
            {
                int Port = PortProperties->ClientPort;
                bool check=OpenConnectionForClient(Port);
            }

我们在这里有一个线程向量,它执行recv和send(处理线程)。如果我们松开与客户端的通信,我们将bool isKilled设置为true,因此communicationthread可以在vector中终止此线程。 这是processingthread的实现:

        void __fastcall CServerClientProcessing::Execute()
        {
        AnsiString Answer = "";
        AnsiString CheckCase = "GetTemperature";
        AnsiString CheckCase2 = "GetSetTemperature";
        AnsiString ToSend = "";
        AnsiString Error = "WRONG_ORDER";
        AnsiString AllUp;
        int ByteOffset = 0;
        int Receive = 0;
        int Send = 0;
        char recvbuf[255];

            while(!Terminated)
            {
                memset(recvbuf, 0x00, sizeof(recvbuf));
                int StartTime = GetTickCount(); //100
                ByteOffset = 0;
                while(GetTickCount()-StartTime<1000 && !Terminated && isKilled == false)
                {
                    // recv function to recieve information from server
                    // bitwise recieve information from client
                    Receive = recv(client,&recvbuf[ByteOffset],1,0);
                    // Receive > 0 true.
                    if (Receive > 0 )
                    {
                        // find last char \r and delete it
                        if(recvbuf[ByteOffset] == '\r')
                        {
                            recvbuf[ByteOffset] = '\0' ;
                            AnsiString temp =  recvbuf;
                            AllUp = recvbuf;
                            AllUp=AllUp.UpperCase();
                            break;
                        }
                        ByteOffset++;
                    }
                    if (Receive < 0)
                    {
                       int value = WSAGetLastError();
                       if (value == 10054 || value == 10093)
                       {
                            isKilled = true;
                            closesocket(client);
                            break;
                       }
                       else
                            continue;
                    }
                    if (Receive = 0)
                    {
                        isKilled = true;
                        closesocket(client);
                        break;
                    }
                }
                // check content of receive
                if(AllUp.Length()!= NULL)
                {
                    CheckCase = CheckCase.UpperCase();
                    if(AllUp == CheckCase)
                    {
                        ToSend = FloatToStr(ConnectionThread->CurrentTemperature/10.0);
                        Answer = ToSend + "\r";
                        // copy information into buffer to send the answer client
                        memcpy(recvbuf,Answer.c_str(), Answer.Length());
                    }
                    CheckCase2 = CheckCase2.UpperCase();
                    if( AllUp == CheckCase2)
                    {
                        ToSend = FloatToStr(ConnectionThread->TemperatureLimit1/10.0);
                        Answer = ToSend + "\r";
                        // copy information into buffer to send the answer client
                        memcpy(recvbuf,Answer.c_str(), Answer.Length());
                    }
                    if( AllUp == CheckCase && AllUp == CheckCase2 )
                    {
                        Error =  Error + "\r";
                        memcpy(recvbuf,Error.c_str(), Error.Length());
                    }
                }
                else
                {
                    Error = Error + "\r";
                    memcpy(recvbuf,Error.c_str(), Error.Length());
                }
                // send answer(buffer) to client
                    Send = send( client, recvbuf, sizeof(recvbuf), 0 );
                    Sleep(1000);
                    // check if failed sending
                    if (Send == SOCKET_ERROR)
                    {
                        closesocket(client);
                        isKilled = true;
                        WSACleanup();
                        break;
                    }
            }
        }

一旦我打开一个客户端,一切正常。但是当我关闭客户端时,会发生不需要的事情:我无法连接另一个客户端而新客户端会死掉。此外,两个客户同时也是不可能的。

是否需要关键部分,还是结构的逻辑问题?我也因为删除了矢量而获得访问冲突,即使我检查它是否为空。

1 个答案:

答案 0 :(得分:0)

我发现了错误:

这是一个糟糕的想法,因为我使用的是TCP_Socket,这可以实现安全的信息传输。所以我必须阅读这些信息。

而不是它,我找到\ r后分手了。消息的其余部分,大约有230个标志仍在流量中。

这就是它破坏连接的原因。我必须发送不是缓冲区的消息长度。