带有 winsock 的简单 C++ 服务器-客户端应用程序

Posted

技术标签:

【中文标题】带有 winsock 的简单 C++ 服务器-客户端应用程序【英文标题】:Simple C++ server-client application with winsock 【发布时间】:2013-03-07 19:50:28 【问题描述】:

我正在尝试编写一个简单的服务器-客户端应用程序,它所要做的就是: 客户端连接到服务器,服务器等待消息,客户端从用户那里获取输入,并将其发送到服务器。服务器收到此消息,并将其发送回客户端,客户端打印消息并循环并重新开始。 但是,由于某种原因,我遇到了一个相当奇怪的问题:当我发送第一条消息时,服务器会响应它,当我发送第二条消息时,服务器会再次响应第一条消息。当我发送第三条消息时,服务器会回复第二条消息,依此类推。

这是我处理连接的服务器代码:

class themusers 
    char ReMessage[200],SeMessage[200];

public:
    void * HandleConnections(SOCKET connector,int location) 

    std::string Converter;

        for (;;) 

        if (recv(connector,ReMessage,sizeof(ReMessage),NULL) == -1)
            std::cout << "Disconnected." << std::endl;
            discon.lock();
            sock_connection[location] = NULL;
            discon.unlock();
            break;
        


        else 
                   //this is the code that handles the receive/send operation
            msgmut.lock();
            //std:: cout << ReMessage << std::endl;
            memcpy(SeMessage, ReMessage, sizeof(ReMessage));
            send(connector, SeMessage, sizeof(SeMessage), NULL);
            msgmut.unlock();        
        

        


        return NULL;
        
;

这是我的客户端代码:

for (;;) 
    cin >> tell;
    send(sock, tell, sizeof(tell), NULL);
    recv(sock,Message,sizeof(Message),NULL);
    Converter = Message;
    cout << "Server: " << Converter << endl;

【问题讨论】:

可能是 'cin' 而不是套接字的问题?缓冲输入不会做奇怪的事情吗? 服务器代码中if后面不是少了一个花括号吗? 不,刚刚检查过。好像没有。 在 cin 后面加了一个 cout,看起来不是问题。 是的,您在此处发布的HandleConnections 函数中缺少 【参考方案1】:

[TCP] 套接字编程的经验法则 - 计算字节数。这意味着实际上要注意从send(2)recv(2) 返回的值。它们分别告诉您从网络发送和填充了多少缓冲区。

UDP 的情况有点不同,但这在这里可能并不重要。

【讨论】:

特别是,一个 200 字节的 send 可以在另一端以几个更小的块“recv”。【参考方案2】:

Boost ASIO 是一个非常好的 C++ 库,用于网络和套接字 i/o 使用,用于实现同步和异步操作。

你可以在这里找到它:

http://www.boost.org/doc/libs/1_53_0/doc/html/boost_asio.html

他们还提供了一些示例来说明如何为聊天服务器实现库,以及其他用途:

http://www.boost.org/doc/libs/1_53_0/doc/html/boost_asio/examples.html

如果您有兴趣学习如何构建异步操作,您应该研究前摄器设计模式。

【讨论】:

都是正确的,但对于这个简单的案例来说太过分了【参考方案3】:

我同意尼古拉的观点。记录返回的字节数很重要。此外,将默认 else 子句更改为以 recv() 的返回值为条件。

您的编译器是否将 NULL 定义为零?将 recv 函数中的 arg 也更改为零可能会更安全。

您还可以考虑在复制到发送缓冲区后修改/归零您的接收缓冲区。 (出于可追溯性目的)

【讨论】:

以上是关于带有 winsock 的简单 C++ 服务器-客户端应用程序的主要内容,如果未能解决你的问题,请参考以下文章

WebSocket客户端和WinSock2服务器,可以吗?

Winsock - 从 C++ 中的 Java 客户端读取整数

带有 winsock 和 std::thread 的 C++ 多线程服务器

winsock2 的替代品,带有 C++ 中的示例服务器源

如何检查客户端是不是通过 C++ 中的 Winsock 断开连接?

如何使用 C++ 在 Winsock 中将大字符串从客户端发送到服务器