接受TCP / IPv4服务器

问题描述

我已经在我的课程中实现了服务器功能,并且希望通过accept接受远程连接,但不幸的是,接受了通过端口0从0.0.0.0开始的连接。

在这里几次发现了这个问题,但是解决adr_len未初始化为sockaddr_in客户端大小的问题,这导致在将其传递给(with 0)到接受功能。但是我用相应的大小(16)初始化了我的我,但是我仍然有这种行为。

终端输出

Initialization successfully completed
Start TCP/-IPv4 server service
Server thread is decoupled
Waiting for remote connection status: 0
adrLen = 16
0.0.0.0 connection via port 0
Wait for remote connection status: 4
Connected to 0.0.0.0: established!

connection.cpp:

#include "connection.h"
//Für aus Chrono generierter resume Zeit
using namespace std::literals::chrono_literals;

//Standart-Konstruktor
connection::connection(const SOCKET &listenSock_Handle)
: Status(0),isWaitRead(false),isWrite(false),listenSock(listenSock_Handle)
{
    //Speicherbereiche initialiseren
    ZeroMemory((SOCKET*)&remoteSock,sizeof(remoteSock));
    ZeroMemory((sockaddr_in*)&client,sizeof(client));
    ZeroMemory(remoteName,NI_MAXHOST);
    ZeroMemory(remoteService,NI_MAXSERV);
    ZeroMemory(recvBuffer,sizeof(recvBuffer));
    ZeroMemory(sendBuffer,sizeof(sendBuffer));  
}
//Standart-Destruktor 
connection::~connection()
{
    //Socket schliessen
    closesocket(remoteSock);
}
//Eingehende Verbindungen annehmen  und Client abspalten
//Diese Klasse bildet dann die Verbindung mit diesem Client ab
//Danach wird durch den Thread auf Daten an dem Socket gewartet und diese
//in den Reiceved Buffer geladen
void connection::startUp(){
    std::thread wait_for_Request { [&] (){
        //adrLen muss zuerst mit der sockadr_in größe initialisert werden bevor diese an accept übergeben wird
        int adrLen = sizeof(client);
        std::cout << "adrLen = " << adrLen << std::endl;
        mx_Status.lock();
        Status = 1;                                                                             
        mx_Status.unlock();
        remoteSock = accept(listenSock,(sockaddr*)&client,&adrLen);
        if (remoteSock == INVALID_SOCKET){
            WSAGetLastError();
            mx_Status.lock();
            Status = -1;  
            mx_Status.unlock();   
        }
        mx_Status.lock();
        Status = 2;
        mx_Status.unlock();
        if(getnameinfo((sockaddr*)&client,adrLen,remoteName,NI_MAXHOST,remoteService,NI_MAXSERV,0) == 0){
            mx_Status.lock();
            Status = 3; 
            mx_Status.unlock();   
        }
        else{
            inet_ntop(AF_INET,&client.sin_addr,NI_MAXHOST);
            // this->remoteService = ntohs(this->client.sin_port);
            std::cout << remoteName << " verbindnung ueber port " << ntohs(client.sin_port) << std::endl;  
            mx_Status.lock();
            Status = 4;
            mx_Status.unlock();
        }
        //Client Verbindung hergestellt beginne Daten von Socket zu lesen
        do
        {
            //Lese daten von Socket und schreibe diese in Puffer.
            mx_isWaitRead.lock();
            isWaitRead = true;
            mx_isWaitRead.unlock();
            mx_recvBuff.lock();
            int bytesReceived = recv(remoteSock,recvBuffer,4095,0);
            mx_recvBuff.unlock();
            mx_isWaitRead.lock();
            isWaitRead = false;
            mx_isWaitRead.unlock();
            if (bytesReceived < 0){
                WSAGetLastError();
                mx_Status.lock();
                int Status = -1;
                mx_Status.unlock();
            }else if (bytesReceived == 0){
                mx_Status.lock();
                Status = 5;
                mx_Status.unlock();
            }
            //Resume Zeit 75MS
            std::this_thread::sleep_for(0.075s);
        } while (true);     
    }}; 
    wait_for_Request.join();
}

main.cpp:

int main(int argc,char* argv[])
{
    //Server-Dienst 
    std::shared_ptr<SOCKET> listening(new SOCKET(0));                           //ptr auf Socket handle erstellen.
    //TCP-Server Dienst initialiseren                                           //Wenn erfolgreich dann Status 0
    if (initialisierung::initialize_Server(0,listening) == 0){                                    //WinSock initial. & Bind (TCP/IPv4 + PORT) = 0 default Port 
        //Initialisierung war erfolgreich
        //dann erstelle neues "connection Objekt"
        connection * Verbindung = new connection(*listening);
        
        //Thread für neue Verbindung starten
        std::cout<<"TCP/-IPv4 Serverdienst starten"<<std::endl;
        std::thread manageRemoteVerbindung ([&]{Verbindung->startUp();});
        std::cout<< "Serverthread ist entkoppelt"<< std::endl;
        
        //Warte auf eingehende Verbindung
        while(Verbindung->getState() == 0 || Verbindung->getState() == 1) 
        {
            std::cout<< "Warte auf Remote Verbindungsstatus: "<< Verbindung->getState() << std::endl;          
            Sleep(1500);
        }        
        std::cout<< "Warte auf Remote Verbindungsstatus: "<< Verbindung->getState() << std::endl;
        std::cout<< "Verbunden mit "<< Verbindung->getClientInfo() <<" hergestellt!"<< std::endl;
        while(getchar() != '\n');
    

解决方法

由于实际上已经有人联系,所以问题很明显是太早调用了getpeername()或其本地等效项,或者根本没有。仅在getpeername()返回的套接字上调用accept()。因此,您认为0.0.0.0已连接。

或更可能是您忽略了listen()的返回值(代码不存在)。尽管accept()可能失败,但几乎永远不会失败。失败的原因之一是listen()首先失败。