2012-02-28 124 views
0

我正试图在局域网上的程序之间建立一个简单的聊天程序。我的问题是我可以轻松地连接并从服务器发送消息到客户端,但不是相反。我试图让它像这样工作。服务器< - >客户端在两个程序之间不断发送和接收,显然这将需要一个循环连续输入,但我不太确定如何去做。这是服务器和客户端的代码。服务器 - >客户端之间的C++ Winsock通信,反之亦然

//THIS IS THE SERVER 
    int main(int argc, char *argv[]) 
{ 
    WSADATA wsaData; 
    int starterr = WSAStartup(MAKEWORD(2,2), &wsaData); 
    if (starterr != 0) 
    { 
     cout << "WSADATA Failed to startup!" << endl; 
     cout << "Error Code: " << WSAGetLastError() << endl; 
     system("pause >nul"); 
     WSACleanup(); 
     return 0; 
    } 

    cout << "WSADATA Startup Successful!" << endl; 
    SOCKET mysock = socket(AF_INET, SOCK_STREAM, 0); 
    if (mysock == INVALID_SOCKET) 
    { 
     cout << "Socket Creation Failed!" << endl; 
     cout << "Error Code: " << WSAGetLastError() << endl; 
     system("pause >nul"); 
     WSACleanup(); 
     return 0; 
    } 
    cout << "Socket Creation Successful!" << endl; 
    sockaddr_in sin; 
    sin.sin_port = htons(80); 
    sin.sin_addr.s_addr = INADDR_ANY; 
    sin.sin_family = AF_INET; 
    if (bind(mysock,(sockaddr*)&sin, sizeof(sin)) == SOCKET_ERROR) 
    { 
     cout << "Socket failed to bind!" << endl; 
     cout << "Error Code: " << WSAGetLastError() << endl; 
     system("pause >nul"); 
     WSACleanup(); 
     return 0; 
    } 
    cout << "Socket Binded Successfuly!" << endl; 

    //Listen to the socket until successful on receiving input 
    while (listen(mysock, SOMAXCONN) == SOCKET_ERROR); 
    SOCKET client; 

    int lin = sizeof(sin); 
    client = accept(mysock,(sockaddr*) &sin, &lin); 
    cout << "Connection Established!" << endl; 
    char buf[200] = "Message from server to client\n"; 


    //Send an initial message to the client 

    send(client, buf, sizeof(buf), 0); 

    //but then how do I wait for a message from the client again here?? 
    //ive tried recv here before with no luck :/ 







    closesocket(mysock); 
    closesocket(client); 
    WSACleanup(); 
    system("pause >nul");  
    return 0; 
} 





    //Client program here 
    int main(int argc, char *argv[]) 
    { 
     WSADATA wsaData; 
     int starterr = WSAStartup(MAKEWORD(2,2), &wsaData); 
     if (starterr != 0) 
     { 
      cout << "WSADATA startup has failed!" << endl; 
      cout << "Error Code: " << WSAGetLastError() << endl; 
      system("pause >nul"); 
      WSACleanup(); 
      return 0; 
     } 
     cout << "WSADATA Startup Successful!" << endl; 
     SOCKET mysock = socket(AF_INET, SOCK_STREAM, 0); 

     if (mysock == INVALID_SOCKET) 
     { 
      cout << "Socket Creation Failed!" << endl; 
      cout << "Error Code: " << WSAGetLastError() << endl; 
      system("pause >nul"); 
      WSACleanup(); 
      return 0; 
     } 

     cout << "Socket Creation Successful!" << endl; 
     sockaddr_in sin; 
     sin.sin_port = htons(80); 
     sin.sin_addr.s_addr = inet_addr("127.0.0.1");//ip for connection 
     sin.sin_family = AF_INET; 
     if (connect(mysock,(sockaddr*)&sin, sizeof(sin)) == INVALID_SOCKET) 
     { 
      cout << "Socket Connection Failed" << endl; 
      cout << "Error Code: " << WSAGetLastError() << endl; 
      system("pause >nul"); 
      closesocket(mysock); 
      WSACleanup(); 
      return 0; 
     } 
     cout << "Socket Has Connected Successfuly!" << endl; 


     //Same applies here, receive message but exactly how do I send one back 

     char buf[200]; 
     recv(mysock, buf, sizeof(buf), 0); 
     cout << buf; 

     //send here seemed to bring up a bunch of symbols 

     system("pause >nul");  
     WSACleanup(); 

     closesocket(mysock); 

     return 0; 
    } 

回答

0

如果你想要全双工通信(即服务器端和客户端都可以随时发送和接收),你可以使用多线程(我不建议这样做,因为多线程引入竞争条件和死锁,除非你真的知道你在做什么),或者使用非阻塞I/O,使用select()或poll()或类似方法进行多路复用。使用多路复用时,基本上告诉select()/ poll()调用“在有趣的事情发生之前不要返回”,其中“有趣的事情”定义为“数据到达套接字”,或者(如果有数据要发送)“现在在套接字上有可用缓冲区空间来放置一些传出数据”。然后,当select()/ poll()返回时,您会检查哪些事件已被标记为ready,并根据需要调用send()/ recv()(因为您将套接字设置为非阻塞,所以这些调用不会阻塞/ O模式),然后再回到select()/ poll()内部休眠,直到发生下一个事件。

通过这种方式,您的程序能够有效地处理send()和recv(),而不需要旋转CPU,也不需要每次都有recv()阻止send()(反之亦然)。

+0

我遵循你的建议,并尝试了非阻塞IO,我现在得到它很好地工作,谢谢你的伟大答案 – user1143896 2012-02-28 18:34:52

0

看看这里: Client-Server communiation

但你也必须要熟悉多线程,因为你有一个侦听传入消息客户端和服务器的例子无限循环此链接,例如,所以你必须把它们放在线程中,你将能够异步地发送和收听消息。如果你不把它们放在线程中,你将不能异步发送和接收消息,因为无限循环会阻止超出它们的所有操作。 我认为这是建立沟通最简单的方法。

相关问题