Клиент / сервер с системными .NET-сокетами в качестве клиента и c ++ winsock на сервере - PullRequest
0 голосов
/ 04 апреля 2011

В настоящее время я пишу два проекта, которые должны взаимодействовать друг с другом по TCP, причем клиент должен быть реализован с использованием System :: Net :: Sockets, а сервер - с помощью Win ++ c ++. В течение долгого времени я использовал эту прекрасную функцию для получения текста в winsock, где клиент сначала отправляет длину сообщения, а затем сообщение. Я не хочу ничего менять на стороне сервера с помощью этой функции, но с .NET я все сделаю. Это моя попытка.

bool WinSockObject::receiveText(std::string &out)
{
    //Create a temporary buffer to work with
    char buf[4096];
    //Stores textLength of incoming data
    long textLength = 0;
    //Receive the textLength that was sent first
    _result = ::recv(
        _socket, //socket we are receiving on
        reinterpret_cast< char *>(&textLength), //the length of the incoming text
        sizeof(textLength), //number of bytes
        0 //no additional flags necessary
    );
    //Make sure we got the text length
    if (_result == SOCKET_ERROR)
    {
        set_error("Unable to receive text length.");
        return false;
    }
    //Convert the textLength back to host bytes
    textLength = ::ntohl(textLength);
    //Receive the actual message
    _result = ::recv(
        _socket, //socket we are receiving on
        buf, //the input buffer
        textLength, //text length
        0 //no additional flags are necessary
    );
    //Make sure we got the actual message
    if (_result == SOCKET_ERROR)
    {
        set_error("Unable to receive text.");
        return false;
    }
    //Manually terminate the buffer
    buf[textLength] = '\0';
    //Copy the buffer to the output string
    out.append(buf);
    return true;
}

Но я застрял, посылая сначала длину, затем сообщение

Socket^ s = gcnew Socket(
    AddressFamily::InterNetwork,
    SocketType::Stream,
    ProtocolType::Tcp
);
s->Connect(server, port); //message to send
String^ howdy = "howdy";
int strLength = howdy->Length; //length of message
String^ length = strLength.ToString(); //convert it to String
//get the bytes
array<Byte>^msgLength = Encoding::ASCII->GetBytes(length);
//send the message length
int bytes = s->Send(msgLength);
//send the actual message
array<Byte>^msg = Encoding::ASCII->GetBytes(howdy);
bytes = s->Send(msg);

1 Ответ

2 голосов
/ 04 апреля 2011

После краткого чтения я вижу две проблемы:

  1. Вы отправляете строку длиной как строку, но сервер читает ее как двоичный файл.
  2. Сервер предполагает, что recv всегда будет считывать количество запрошенных байтов. Это не верно; recv может вернуть 0 (если другая сторона корректно закрыла соединение), любое значение в диапазоне [1, len] (если некоторые данные были получены успешно) или SOCKET_ERROR (если произошла ошибка).
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...