2015-12-30 136 views
0

我在互聯網上發現了一些代碼,介紹了一些關於在C++中創建TCP/IP服務器的基礎知識。 我拿了這段代碼,添加了一些庫和一些代碼行。結果是,我能夠在Windows上作爲控制檯程序在Qt Creator中編譯和運行代碼/服務器。不過,我無法連接到服務器,因爲它只是運行代碼而不等待並接受來自TCP客戶端的連接。C++中的TCP/IP服務器不在等待客戶端

這是代碼: 編輯:代碼已更新,它現在工作。測試== -1是解決方案。

#define PORT 2000 
#define MAX_QUEUE 5 
#define BUF_SIZE 1024 

int main(int argc, char* const argv[]) 
{ 
cout << "Hello World!" << endl;  
     WSADATA wsaData; 
int wsaret = WSAStartup(MAKEWORD(4, 4), &wsaData); 
cout << "wsaret: " << wsaret << endl; 

cout << "Start TCP/IP Server" << endl; 

/* file descriptors for sockets */ 
SOCKET sock_1, sock_2; //switched from in to SOCKET //unsigned int sock_1, sock_2; 
int rec_value, length; 
char buf[BUF_SIZE]; 

//struct sockaddr_in server; 
struct sockaddr_in server; 

/* create stream socket in internet domain*/ 
sock_1 = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); 
//if(sock_1 < 0) 
if(sock_1 == -1) 
{ 
    cout << "socket: " << WSAGetLastError() << endl; //instead of //cout << "socket: " << strerror(errno) << endl; //cout << "socket wsaret: " << wsaret << endl; 
    exit(1); 
} 

/* build address in internet domain */ 
server.sin_family = AF_INET; 

/* everyone is allowed to connet to server */ 
server.sin_addr.s_addr = INADDR_ANY; //inet_addr("192.168.145.129"); 
server.sin_port = htons(2000); //server.sin_port = PORT; //Port: 2000 

/* bind socket */ 
//if(bind(sock_1, (struct sockaddr *)&server, sizeof(server))); 
int bindreturn = (bind(sock_1, (struct sockaddr *)&server, sizeof(server))); 
if(bindreturn == -1) 
{ 
    cout << "bind: " << WSAGetLastError() << endl; //instead of //cout << "bind: " << strerror(errno) << endl; //cout << "bind wsaret: " << wsaret << endl; 
    exit(1); 
} 

listen(sock_1,MAX_QUEUE); 
    /* start accepting connection */ 
    sock_2 = accept(sock_1,0,0); 
    if(sock_2 < 0) 
    { 
     cout << "accept: " << WSAGetLastError() << endl; 
     exit(1); 
    } 

    /* read from sock_2 */ 
    while(rec_value=recv(sock_2,buf,BUF_SIZE,0)) 
    { 
     if(rec_value < 0) 

     { 
     cout << "recv: " << WSAGetLastError() << endl; 
     exit(1); 
     } 
     else 
     { 
      cout << "else" << endl; 
      send(sock_2,"1,2,3",strlen("1,2,3"),0); 
     } 
    } 

    cout << "Ending connection" << endl; 
    closesocket(sock_1); 
    closesocket(sock_2); 
    cout << "End TCP/IP Server" << endl; 

    WSACleanup(); 
return 0; 
} 

控制檯顯示在一個秒或更少程序在運行過程中繼/:

Hello World! 
wsaret: 0 
Start TCP/IP Server 
bind: 0 

我能做些什麼,該服務器的連接夥伴等待?

在此先感謝。

問候 MATL

編輯:添加的代碼開頭的幾行,這是我之前忘了。 編輯:代碼更新 編輯:代碼更新

+0

Does not'you like you've included all code?首先,「Hello World!」的部分打印的行不包含在代碼中。也許如果你包含完整的代碼,會更容易發現問題出在哪裏?另外,如果我冒險猜測,我會說,當運行實際的可執行文件時,你需要包含綁定端口等命令行參數。 – Liang

+2

由於'bind'失敗,任何後續操作也都會失敗。很有可能是其他一些進程已經在監聽端口。檢查'errno'來確定哪裏出了問題。 – molbdnilo

+0

您正在報告錯誤,然後完全忽略它們並繼續進行,好像它們沒有發生過一樣。監聽或綁定錯誤是*致命的。*之後沒有任何工作可以工作。而僅僅打印-1也是不可接受的。你必須通過'perror()'或'strerror()'打印*錯誤。不要這樣寫代碼。 – EJP

回答

2

我要詳細評論您發佈的原始代碼。

cout << "Start TCP/IP Server" << endl; 

//int sock_1,sock_2;  /* file descriptors for sockets */ 
int sock_1, sock_2; 
int rec_value, length; 
char buf[BUF_SIZE]; 

//struct sockaddr_in server; 
sockaddr_in server; 

/* create stream socket in internet domain*/ 
sock_1 = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);//0); 

這裏缺少測試。你必須沿着這些線路測試結果爲-1:

if (sock_1 == -1) 
{ 
    cout << "socket creation error: " << WSAGetLastError() << endl; 
    exit(1); // or some other measure to prevent continuation 
} 

返回代碼:

/* build address in internet domain */ 
server.sin_family = AF_INET; 

/* everyone is allowed to connet to server */ 
server.sin_addr.s_addr = INADDR_ANY; //inet_addr("192.168.145.129"); 
server.sin_port = PORT; //Port: 2000 

這應該是

server.sin_port = htons(PORT); 

返回代碼:

/* bind socket */ 
int bindreturn = bind(sock_1, (struct sockaddr *)&server, sizeof(server)); 
cout << "bindreturn: " << bindreturn << endl; 

不足。這裏再次需要測試-1,並打印WSAGetLastError()並退出,如果你有它。

listen(sock_1,MAX_QUEUE); 

未經測試。這裏再次需要測試-1等。

/* start accepting connection */ 
    //system("pause"); 
    sock_2 =accept(sock_1,0,0); 
    //system("pause"); 
    cout << "acceptreturn: " << sock_2 << endl; 

再次不足,請參閱上文。

/* read from sock_2 */ 
    while(rec_value=recv(sock_2,buf,BUF_SIZE,0)) 
    { 
     if(rec_value<0) 
     { 
     cout << "error: " << rec_value << endl; 
     exit(1); 
     } 

測試不正確。系統調用通過精確返回-1來指示錯誤,而不僅僅是任何值< 0.例如由socket()accept()返回的套接字FD可以是負數,或者是除-1之外的任何值。

 else 
     { 
      cout << "else" << endl; 
      send(sock_2,"1,2,3",strlen("1,2,3"),0); 
     } 
    } 
closesocket(sock_1); 
closesocket(sock_2); 

cout << "End TCP/IP Server" << endl; 

return 0; 

距離closesocket()調用您使用Winsock的,在這種情況下,兩個WSAStart()WSACleanup()缺少明顯。

2

PORT如何定義?

你應該使用:

server.sin_port = htons(PORT); //Port: 2000 

是您的IP地址是否正確?

您的所有來電都收到SOCKET_ERROR(-1),因此您應該檢查lasterror以獲取更多信息。

不知道(在Windows上),但不應該是unsigned int的?

int sock_1, sock_2; 

更新

好吧,你似乎可以用Qt的Windows上。對於Qt,你不妨使用Qt libraries

在Windows上,您可以使用免費的MS Visual Studio。

您還需要調用WSAStartup()這樣的:

WSADATA wsaData; 
int wsaret = WSAStartup(MAKEWORD(4, 4), &wsaData); 
// check wsaret 

// more code here 

WSACleanup(); 

還可以使用SOCKET

SOCKET sock_1, sock_2; 

檢查與WSAGetLastError()的ErrorCode的。

+0

我正在Windows機器上用Qt Creator創建一個小型的C++控制檯程序,而不需要Qt。如果我沒有錯「server.sin_addr.s_addr = INADDR_ANY;」 allwos每個IP地址。我使用「server.sin_port = htons(2000);」現在,但bind()仍然失敗。 – matl

+0

@matl - 你用新代碼得到多少?另外,不要忘記'htons(PORT)'。還要檢查listen()中的returncode。而你的'accept()'需要更好的參數。 –

+0

然後你是否使用winsock2? (你可能需要SOCKET而不是int)。或者任何Qt庫?因爲你發現的代碼幾乎肯定是爲Linux編寫的。你包括什麼標題? –

相關問題