Отправка несколько раз и recv несколько раз - PullRequest
0 голосов
/ 20 сентября 2019

Я очень, очень, очень, очень плохо знаком с программированием сокетов TCP / IP.есть значение 2 argv из client.c, и мне нужно отправить эти два в server.c

Я подумал, что если я отправлю () два раза из client.c и два раза recv в server.c, это будетбыть в порядке, но на самом деле это не так.Может кто-нибудь дать мне знать, как отправить два буфера в server.c?

в client.c

ssize_t byteNumSentAccName = send(clientSock, accountName, strlen(accountName), 0);
ssize_t byteNumSentCmd = send(clientSock, command, strlen(accountName), 0);

, где и accountName, и команда являются буфером символов.

в server.c

ssize_t byteNumRecvAccName = recv(clientSock, nameBuf, BUFSIZE-1, 0);
  ssize_t byteNumRecvCmd = recv(clientSock, cmdBuf, BUFSIZE-1, 0);

1 Ответ

1 голос
/ 20 сентября 2019

TCP - это поток байтов, между send() и recv() нет отношения 1: 1, как в UDP.

В TCP send() может отправлять меньше байтов, чем запрошено,и recv() может вернуть меньше байтов, чем запрошено.Таким образом, вы должны вызывать их в циклах, пока все байты не будут отправлены / получены.И вам необходимо сформировать данные таким образом, чтобы получатель знал, где заканчивается одно значение и начинается другое.Например, при отправке строки переменной длины вы можете либо

  • отправить длину строки в виде целого числа фиксированной ширины, прежде чем отправлять действительные символы строки.Затем получатель может сначала прочитать длину, а затем читать до тех пор, пока не будет получено указанное количество символов.
bool sendRaw(int sock, const void *data, int size)
{
    const char *buffer = (const char*) data;
    while (size > 0)
    { 
        ssize_t sent = send(sock, buffer, size, 0);
        if (sent < 0)
            return false;
        buffer += sent;
        size -= sent;
    }
    return true;
}

bool sendInt32(int sock, int32_t value)
{
    value = htonl(value);
    return sendRaw(sock, &value, sizeof(value));
}

bool sendString(int sock, const char *s)
{
    int32_t len = strlen(s);
    if (!sendInt32(sock, len))
        return false;
    return sendRaw(sock, s, len);
}

...

sendString(clientSock, accountName);
sendString(clientSock, command);
int readRaw(int sock, void *data, int size)
{
    char *buffer = (char*) data;
    while (size > 0)
    { 
        ssize_t recvd = recv(sock, buffer, size, 0);
        if (recvd < 0)
            return -1;
        if (recvd == 0)
            return 0;
        buffer += recvd;
        size -= recvd;
    }
    return 1;
}

int readInt32(int sock, int32_t *value)
{
    int ret = readRaw(sock, value, sizeof(*value));
    if (ret == 1)
        *value = ntohl(*value);
    return ret;
}

char* readString(int sock)
{
    int32_t len = 0;
    if (readInt32(sock, &len) <= 0)
        return NULL;

    char *ret = (char*) malloc(len+1);
    if (!ret)
        return NULL;

    if (readRaw(sock, ret, len) <= 0)
    {
        free(ret);
        return NULL;
    }

    ret[len] = '\0';
    return ret;
}

...

nameBuf = readString(clientSock);
cmdBuf = readString(clientSock);
...
free(nameBuf);
free(cmdBuf);
  • отправить уникальный разделитель после отправки действительных строковых символов(нулевой терминатор, разрыв строки, все, что вы хотите, до тех пор, пока он никогда не появится в строках).Получатель может читать до тех пор, пока этот разделитель не будет получен.
bool sendRaw(int sock, const void *data, int size)
{
    const char *buffer = (const char*) data;
    while (size > 0)
    { 
        ssize_t sent = send(sock, buffer, size, 0);
        if (sent < 0)
            return false;
        buffer += sent;
        size -= sent;
    }
    return true;
}

bool sendString(int sock, const char *s)
{
    int32_t len = strlen(s) + 1;
    return sendRaw(s, len);
}

sendString(clientSock, accountName);
sendString(clientSock, command);
int readRaw(int sock, void *data, int size)
{
    char *buffer = (char*) data;
    while (size > 0)
    { 
        ssize_t recvd = recv(sock, buffer, size, 0);
        if (recvd < 0)
            return -1;
        if (recvd == 0)
            return 0;
        buffer += recvd;
        size -= recvd;
    }
    return 1;
}

char* readString(int sock)
{
    char *ret = NULL, *tmp;
    size_t len = 0, cap = 0;
    char ch;

    do
    {
        if (readRaw(sock, &ch, 1) <= 0)
        {
            free(ret);
            return NULL;
        }

        if (ch == '\0')
            break;

        if (len == cap)
        {
            cap += 100;
            tmp = (char*) realloc(ret, cap);
            if (!tmp)
            {
                free(ret);
                return NULL;
            }
            ret = tmp;
        }

        ret[len] = ch;
        ++len;
    }
    while (true);

    if (len == cap)
    {
        tmp = (char*) realloc(ret, cap+1);
        if (!tmp)
        {
            free(ret);
            return NULL;
        }
        ret = tmp;
    }

    ret[len] = '\0';    
    return ret;
}

...

nameBuf = readString(clientSock);
cmdBuf = sendString(clientSock);
...
free(nameBuf);
free(cmdBuf);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...