0

I am trying to send cyrillic messages through socket and I have problem. The message doesn't go through. If I use char (on both sides), on the other side I receive, the cyrilic part incorrect. If I use WCHAR (on both sides), I receive the message until the first cyrillic character. If I send only ASCII characters everything is ok. So here is the client code. If it is necessary I can put the server code as well.

Client:

  char ip_addr[] = "192.168.0.102";
  int port = 30000;
  wchar_t message[] = L"TEST ТЕСТ MESSAGE ПОРАКА";
  //char message[] = "TEST ТЕСТ MESSAGE ПОРАКА";
  WSADATA wsaData;
  int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
  if (iResult != 0) {
    wprintf(L"WSAStartup failed: %d\n", iResult);
    return 1;
  }

  struct sockaddr_in messageServer;
  memset(&messageServer, 0, sizeof(messageServer));
  messageServer.sin_family = AF_INET;
  messageServer.sin_addr.S_un.S_addr = inet_addr(ip_addr);
  messageServer.sin_port = htons(port);
  SOCKET outsocket;
  outsocket = socket(AF_INET, SOCK_STREAM, 0);

  if (outsocket == -1) {
    std::cout << "ERROR";
    exit(-1);
  }

  int connRes = 0;
  connRes = connect(outsocket, (struct sockaddr *)&messageServer, sizeof(messageServer));
  if (connRes < 0) {
    std::cout << "ERRROR CONNECT " << WSAGetLastError() <<  std::endl;
    system("pause");
    exit(-1);
  }

  int result;
  result = send(outsocket, (char*)message, sizeof(message), 0);
  if (result == SOCKET_ERROR) {
    wprintf(L"send failed with error: %d\n", WSAGetLastError());
    closesocket(outsocket);
    WSACleanup();
    return 1;
  } else {
    std::wcout << "Return code: " << result << std::endl;
  }
  closesocket(clientSocket);

Server:

  int port = 30000;
  char ip_addr[] = "192.168.0.102";
  struct sockaddr_in serverAddr, clientAddr;

  memset(&serverAddr, 0, sizeof(serverAddr));
  memset(&clientAddr, 0, sizeof(clientAddr));

  std::locale::global(std::locale("Russian_Russia"));

  WSADATA wsaData;
  int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
  if (iResult != NO_ERROR) {
    wprintf(L"Error at WSAStartup()\n");
    return 1;
  }

  serverAddr.sin_family = AF_INET;
  serverAddr.sin_addr.S_un.S_addr = inet_addr(ip_addr);
  serverAddr.sin_port = htons(port);

  SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, 0);
  int bindRes = 0;
  bindRes = bind(serverSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr));
  if (bindRes < 0) {
    std::wcout << "ERRROR BIND" << WSAGetLastError() <<  std::endl;
    system("pause");
    exit(-1);
  }

  if (listen(serverSocket, 5) < 0)
  {
    std::wcout << "ERRRORRR LISTEN" << std::endl;
    system("pause");
    exit(-1);
  }

  for (;;)
  {
    std::wcout << "WAITING..." << std::endl;
    int length = sizeof(clientAddr);

    wchar_t message[500];
    ZeroMemory(&message, sizeof(message));
    SOCKET clientSocket = accept(serverSocket, (struct sockaddr *) &clientAddr, &length);
    int bR = 0;
    bR = recv(clientSocket, (char*)message, sizeof(message), 0);
    if(bR == -1) {
      std::wcout << "ERRRRORORORORRR";
    }

    std::wcout << "Received bytes: " << bR << std::endl;
    std::wcout << "Message: " << message << std::endl;

    closesocket(clientSocket);
  }

I have also made a capture with Wireshark. And here is the output: HEX:

54:00:45:00:53:00:54:00:20:00:22:04:15:04:21:04:22:04:20:00:4d:00:45:00:53:00:53:00:41:00:47:00:45:00:20:00:1f:04:1e:04:20:04:10:04:1a:04:10:04:00:00:cc

TEST "!" MESSAGE

nikolakoco
  • 1,343
  • 1
  • 12
  • 22
  • Have you checked what data is sent (eg. using Wireshark)? Then you'll narrow down the problem to see if it's client or server issue. Then you can check what bytes you actualy send, receive and if your code doesn't stop reading with something peculiar (like '\0'). – Maciek Jan 09 '14 at 16:23
  • 1
    Show us receiving side. – zoska Jan 10 '14 at 09:51
  • I have posted the server side and wireshark output. Sorry for the delay – nikolakoco Jan 14 '14 at 13:58
  • Can you try `std::wcout << L"TEST ТЕСТ MESSAGE ПОРАКА";` ? (I've been shocked just how bad C++'s wide character support can be in the past..) – Roddy Jan 14 '14 at 14:33
  • Also, you should really consider sending/receiving data as UTF8. Wide chars are just a pain! http://www.utf8everywhere.org/ – Roddy Jan 14 '14 at 14:37
  • That works, cuz previously I have this line: std::locale::global(std::locale("Russian_Russia")); That apparently sets the locale for the console. – nikolakoco Jan 14 '14 at 14:47
  • The Wireshark capture shows the sender is working OK. I can see the cyrillic in there like 22:04 . I still think this is likely a console display problem. Try printing the received data a byte at a time, and I'm expect it will match the wireshard data. – Roddy Jan 14 '14 at 15:50
  • I have saved the file in visual studio with utf-8 encoding and the message transfer is ok. But isn't there a better way to transfer the message, as you have mentioned previously to send the char as utf-8 encoded – nikolakoco Jan 15 '14 at 13:45

1 Answers1

1

Based on what you posted its kind of hard to tell what is wrong.

First of all, the usual problem, recv / send may not give you the data you asked for since it's just a hint. What makes it more confusing that on localhost it succeeds almost all the time meaning that send will most likely send the data in one call and recv will receive it in one call.

Take a look at recv and send especially the remarks section about the buffer and it's length.

Secondly, strings are generally don't behave well when sent over the network, assuming that the server part is also windows it may work but still, you have to make sure you always send based on char count * char size for ASCII char size is 1 Byte for unicode it is 2 Bytes for windows but linux used 4 Bytes thus you have to make sure you know how long is your string then calculate it's size in bytes. On top of all this you have to make sure you know where your data ends, for both send and the string displaying functions that is usually a '\0' but you can let the network function know how long it actually is before sending the string data and when the data is recvd then you manually put a null '\0' at the end.

So based on what you posted it should work because C automatically adds a \0 at the end of each static string, and since you run this on localhost the send/recv should also work, so you either have a network problem or something else is wrong. Post more info if you can since it hard to tell just from this what could be wrong.

DrakkLord
  • 645
  • 4
  • 8
  • I have posted the server side as well. And basically I have to windows machines and I am trying to send a message. The general problem is that I have a lot bigger problem where I am senging some html code via socket that contains cyrilic values. – nikolakoco Jan 14 '14 at 13:58