【问题标题】:Socket communication between Java and C++Java 和 C++ 之间的套接字通信
【发布时间】:2012-01-26 07:17:35
【问题描述】:

我正在尝试在 Java 服务器和 C++ 客户端之间建立连接。但是当我在客户端读取数据时,我总是有相同的奇怪字符(¬í)。我试图改变双方的编码,但没有任何效果。

这是我的 Java 代码:

public class Serveur
{
    public static void main(String[] args) throws Exception
    {
        final int PORT = 13370;
        try
        {
            ServerSocket service= new ServerSocket(PORT);
            Socket connection = service.accept();
            PrintWriter pw = new PrintWriter(connection.getOutputStream());
            String s = Integer.toString(5);
            while(true)
            {
                pw.print(s.getBytes("UTF-8"));
                pw.flush();
                pw.close();
            }
            connection.close();
        }
}

我还尝试使用 OutputStream、DataOutputStream 和 BufferedOutputStream。

这里是 C++ 代码:

int main(int argc, char* argv[])
{
    WSADATA WSAData;
    WSAStartup(MAKEWORD(2,0), &WSAData);
    SOCKET sock;
    SOCKADDR_IN sin;
    char buffer[512];
    sin.sin_addr.s_addr = inet_addr("127.0.0.1");
    sin.sin_family      = AF_INET;
    sin.sin_port        = htons(13370);
    sock = socket(AF_INET,SOCK_STREAM,0);
    if(connect(sock, (SOCKADDR*)&sin, sizeof(sin)) != SOCKET_ERROR)
{
    cout<<"connection"<<endl;
    if(recv(sock, buffer, sizeof(buffer), 0) != SOCKET_ERROR)
    {
        string s = buffer;
        wchar_t *pwchello = L"Hi";
        wchar_t *pwc      = (wchar_t *)malloc( sizeof( wchar_t ));
        char    *pmbhello = buffer;
        int i = mbstowcs(pwc,pmbhello, MB_CUR_MAX);
        cout << i << endl;
        cout<<"cout : "<<pwc<<endl;
        cout <<buffer<<endl;
        printf("printf : %s\n", buffer);

        cout << "wsagetlasterror() : "<<WSAGetLastError();
        closesocket(sock);
        WSACleanup();
        free(m_pBuffer);
    }
    return 0;
}

如您所见,我尝试了不同的解决方案但没有成功。

提前谢谢,对不起,我的英语可能不太好

【问题讨论】:

  • 这是 C 还是 C++?从外观上看,它是 C,(即:您使用的是 malloc)。
  • 这是winapi吗?也许你想这样标记它?在任何情况下,了解如何使用诸如wireshark 之类的工具是很有用的,这样您就可以看到线路上的实际内容,以确定首先查看哪些程序。
  • 可能是因为 UTF-8,我会尝试 ASCII
  • @netcoder 除了如果它是 C 就不会编译。面对现实,所有那些你嘲笑为“丑陋”的东西都是你选择的语言的一部分。 :-) 现在“惯用”或具有适当的 C++ 风格是另一个问题...
  • @asveikau:实际上,它也不会在 C++ 中编译。缺少}

标签: java c++ sockets networking


【解决方案1】:

您混合了许多不同的编码转换和 I/O 策略。您应该尝试以下简化版本:

if(connect(sock, (SOCKADDR*)&sin, sizeof(sin)) != SOCKET_ERROR)
{
    cout << "connection" << endl;

    // the result of 'recv()' is either SOCKET_ERROR or
    // the number of bytes received.  don't though away
    // the return value.
    const int result = recv(sock, buffer, sizeof(buffer), 0);
    if(result != SOCKET_ERROR)
    {
        // use length (in bytes) returned by 'recv()'
        // since buffer is not null terminated.
        string s(buffer,result);

        // 's' is in UTF-8 no converstion to wide strings
        // should be necessary.
        cout << "message: '" << s << "'." << endl;
    }

    closesocket(sock);
}
WSACleanup();

但是,请注意标准输出在当前代码页中,通常 UTF-8 不是默认代码页。在 Windows 中将 Unicode 数据输出到控制台需要配置一些其他库调用。

【讨论】:

    【解决方案2】:

    recv 不会将其目标缓冲区转换为以空字符结尾的字符串。它填充缓冲区中的多个字节,但不附加 0。

    您需要执行此操作(当然要进行错误检查):

    ssize_t bytesRead = recv(buffer, ...);
    string str(buffer, bytesRead);
    

    另外,请注意,recv 不保证在一次调用中发送的内容会在一次调用中收到(除非您使用的是 UDP)。

    【讨论】:

    • 如果我总是发送一个简单的整数或字符串,它会在一次调用中收到吗?我该如何在 UDP 和 TCP 之间进行选择?
    • TCP 传递字节序列,而 UDP 传递数据包序列(字节数组)。 UDP 提供了内置的消息“边界”(一个数据包就是一个消息,作为一个单元最多传递 64K 字节),而使用 TCP,您需要在应用程序级别将流拆分为消息(例如,将每 4 个字节视为单个消息或在消息之间插入 0)。 TCP 是有保证的交付:您以正确的顺序获取每个字节,否则您将失去连接。允许 UDP 丢弃数据包。
    • 至于发送“简单整数或字符串”,确实没有保证。传递给 send() 的数据的大小越小,它就越有可能在一个 recv() 中交付。然而,这都是关于时间和数据包边界的。你传递给 send() 的数据被拆分成数据包通过 IP 传递,recv() 将返回迄今为止到达的所有数据包中的数据。
    【解决方案3】:

    您在这里只为单个 wchar_t 分配空间:

    wchar_t *pwc = (wchar_t *)malloc( sizeof( wchar_t ));

    您也将缓冲区分配给字符串 s,但似乎从不使用 s

    【讨论】:

      【解决方案4】:

      从昨晚开始我就遇到了同样的问题。最后发现我的服务器无法识别编码(用C编写)。因此,我改变了我的客户

      someOutputStream.writeUTF(someSillyString);
      

      someOutputStream.write(someSillyString.getBytes());
      

      这样,我什至不需要在服务器端进行类型转换。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-05-29
        • 1970-01-01
        • 1970-01-01
        • 2016-11-26
        • 1970-01-01
        • 2021-06-20
        相关资源
        最近更新 更多