问题描述
我已经在我的课程中实现了服务器功能,并且希望通过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()
首先失败。