【问题标题】:Socket programming, encode/ decode data/ text, more specific special characters send and receive through sockets套接字编程,编码/解码数据/文本,更具体的特殊字符通过套接字发送和接收
【发布时间】:2022-01-15 19:18:24
【问题描述】:

Win 10 64 位 C++ 中的服务器:

const int BufLen = 1024;
char RecvBuf[BufLen];
int result;
char SendBuf[BufLen] ;

const int PORT = 27015;
const char* HOST = "127.0.0.1";

int main()
{
    //SetConsoleOutputCP(65001);
    std::cout << "Hello World!\n";
    //std::cout << "á" << std::endl;
    WSADATA wsaData; 
    int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);   if (iResult != NO_ERROR) {
        printf("Error at WSAStartup()\n");     
        return 1;
    }
    // Create a SOCKET for listening for   // incoming connection requests. 
    SOCKET ListenSocket;
    ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    if (ListenSocket == INVALID_SOCKET) {
        printf("Error at socket(): %ld\n", WSAGetLastError());    
        WSACleanup();  
        return 1;
    
    }
    // The sockaddr_in structure specifies the address family,
    // IP address, and port for the socket that is being bound.

    sockaddr_in service;

    service.sin_family = AF_INET;
    //service.sin_addr.s_addr = inet_addr("127.0.0.1");
    inet_pton(AF_INET, HOST, &service.sin_addr);
    service.sin_port = htons(PORT);

    if (bind(ListenSocket, (SOCKADDR*)&service, sizeof(service)) == SOCKET_ERROR) { 
        printf("bind() failed.\n"); 
        closesocket(ListenSocket); 
        WSACleanup(); 
        return 1;
    }
    // Listen for incoming connection requests.
    // on the created socket
    if (listen(ListenSocket, 1) == SOCKET_ERROR) { 
        printf("Error listening on socket.\n");
        closesocket(ListenSocket); WSACleanup();
        return 1; 
    }

    // Create a SOCKET for accepting incoming requests. SOCKET AcceptSocket; printf("Waiting for client to connect...\n");
    SOCKET AcceptSocket;
    printf("Waiting for client to connect...\n");

    // Accept the connection.
    AcceptSocket = accept( ListenSocket, NULL, NULL );
    if (AcceptSocket == INVALID_SOCKET) {
        printf("accept failed: %d\n", WSAGetLastError()); 
        closesocket(ListenSocket);
        WSACleanup(); 
        return 1;
    }
    else printf("Client connected.\n");
    // Call the recvfrom function to receive datagrams 
    // on the bound socket.
    
    printf("Receiving datagrams...\n");
    result = recv(AcceptSocket, RecvBuf, BufLen, 0);
   
    printf("%d\n", result);
    std::cout << "Received:" << RecvBuf << std::endl;
    printf("%d", sizeof(RecvBuf));
    //strcpy_s(SendBuf, "Helloéáőúóü");
    printf("\n\n\n\n");
    strcpy_s(SendBuf, "abcá");
    std::cout << SendBuf << std::endl;
    result = send(AcceptSocket, SendBuf, BufLen, 0);
    printf("\nAfter sending: %d\n", result);
    std::cout << SendBuf;

Java 客户端:

 var socket = new Socket("127.0.0.1", 27015);
        //sending to the server
        var out = new PrintWriter(socket.getOutputStream(), true);
        out.println("Helloá");
        //receive from server
        var in = new InputStreamReader(socket.getInputStream());
        BufferedReader br = new BufferedReader(in);
        char[] buffer = new char[1024];
        int count = br.read(buffer, 0, 20);
        String reply = new String(buffer, 0, count);
        System.out.println(reply);

Python 客户端:

HOST = "127.0.0.1"
PORT =  27015
clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clientSocket.connect((HOST, PORT))
clientSocket.send("JAASFSKF".encode('utf-8'))
msg = clientSocket.recv(1024)
print(msg)
msg = msg.decode('utf-8')
print(msg)
clientSocket.close()

用特殊字符进行了一些实验,但客户端或服务器都无法处理。

java客户端结果: encoding done with utf-8 python 应用程序抛出异常,因为它无法解码从套接字接收的数据: Python 3.9.5 我试图以不同的编码保存服务器,但我认为情况并非如此,可能需要对套接字声明进行一些更改。 客户端与服务器是同一台机器。 这是我的实际问题,要克服这个问题

【问题讨论】:

  • 在问题中将错误消息显示为格式正确的文本,而不是图像或外部链接。
  • Python 错误:“D:\Python stuff\SimpleChatClient\Scripts\python.exe”“D:/Python stuff/SimpleChatClient/main.py”回溯(最近一次调用最后):文件“D :\Python stuff\SimpleChatClient\main.py", line 9, in msg = msg.decode('utf-8') UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe1 in position 3: invalid继续字节 b'abc\xe1\x00\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe' 进程以退出代码 1 结束
  • 只是添加注释。最直接的原因是您的 C++ 代码正在使用此处看到的传统 Windows 默认编码:en.wikipedia.org/wiki/Windows-1252。该编码可能内置于 C++ 编译器本身。您会注意到,该编码中的 á 字符是单字节十六进制 e1 (\xe1),它与您的 python 错误消息显示的内容相匹配。但e1 不是有效 UTF-8 字符的一部分。以下@user16632363 的回答中的所有内容都是正确的:特别是在处理非 ascii 字符时,您必须明确编码。

标签: python java c++ sockets


【解决方案1】:

TCP 套接字携带字节流,无需解释。没有“特殊字符”。

您的 C++ 代码显然是以字节为单位的;您的 Python 和 Java 代码期望这些字节代表编码为 UTF-8 的“字符”。这是设计不匹配。

如果您的意图是通信使用 UTF-8,则 C++ 代码应显式转换为/从 UTF-8。


此外,TCP 中没有“消息”。这是一个字节流协议。您需要一个约定,以便每一端都可以确定它是否收到了您的应用程序想要考虑的消息。

如果一方发送“xyz”(并没有立即关闭连接),另一方怎么知道“z”是最后一个字符?

由于您正在处理字符,一种方法是确保所有内容都以换行符“\n”终止。您可以使用面向行的方法。

【讨论】:

  • 实际上,Java 客户端代码并没有指定使用哪种字符编码。所以它实际上将使用 JVM 的默认字符编码。那可能是 UTF-8,也可能是别的东西。 (显然,OP当前正在运行代码的机器上是UTF-8 ...)
  • @Stephen C - 你就在那里。 “默认默认值”是 UTF-8,但最好是明确的代码。
猜你喜欢
  • 1970-01-01
  • 2012-02-12
  • 2017-10-06
  • 2018-06-14
  • 1970-01-01
  • 2015-02-04
  • 2018-05-15
  • 2016-12-08
  • 1970-01-01
相关资源
最近更新 更多