2015-12-30 90 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编写的。你包括什么标题? –

相关问题