В моем TCP-соединении клиент отправляет Hello, а сервер получает Hellob - PullRequest
0 голосов
/ 13 февраля 2020

, как вы можете видеть на этом рисунке

, если клиент пишет Ciao, сервер получает Ciaob; но иногда он правильно получает Ciao.

Это мой клиент. c file:

int main ()
{
    int clientSocket;
    struct sockaddr_in serverAddress;
    char buffer[1024];
    int connectionStatus;
    ssize_t nread;

// Creazione della socket
clientSocket = socket(AF_INET, SOCK_STREAM, 0);
if (clientSocket == -1) {
    perror("[-]Errore durante la creazione della socket\n");
    exit(-1);
}


memset(&serverAddress, '\0', sizeof(serverAddress));

// Riempimento dei campi della struct
serverAddress.sin_family = AF_INET;
serverAddress.sin_port = htons(PORT);
serverAddress.sin_addr.s_addr = INADDR_ANY;

// Connessione
connectionStatus = connect(clientSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress));
if (connectionStatus == -1) {
    perror("Errore con la connessione\n");
    exit(-1);
}

while (1) {

    printf("> ");
    fflush(stdin);
    scanf("%s", buffer);

    // Invio dei dati
    if (send(clientSocket, buffer, strlen(buffer), 0) <= 0) {
        perror("Errore con l'invio");
        exit(1);
    }

    // Riceve i dati dalla socket
    if ( (nread=recv(clientSocket, buffer, sizeof buffer -1, 0)) == -1) {
        perror("[-]Error in receiving data\n");
    }
    else {
        printf("nread is %ld\n", nread);
        buffer[nread] = '\0';
        printf("Server received: %s\n", buffer);
    }

}

close(clientSocket);

return 0;
}

и это мой сервер. c

#define PORT 4444
#define MAX_CONNESSIONI 100

int main ()
{
    int serverSocket, bindStatus;
    struct sockaddr_in serverAddress;
    int clientSocket;
    struct sockaddr_in newAddress;
    char buffer[1024];
    pid_t child;
    socklen_t addrSize;

    // Creazione della socket
    serverSocket = socket(AF_INET, SOCK_STREAM, 0);
    if (serverSocket == -1) {
        perror("[-]Errore durante la creazione della socket\n");
        exit(-1);
    }

    printf("[+]Echo-Server socket has been created\n");

    memset(&serverAddress, '\0', sizeof(serverAddress));

    // Riempimento dei campi della struct
    serverAddress.sin_family = AF_INET;
    serverAddress.sin_port = htons(PORT);
    serverAddress.sin_addr.s_addr = INADDR_ANY;

    // Binding della socket all'indirizzo specificato. Associa alla socket un indirizzo in modo da poter essere contattata dai client
    bindStatus = bind(serverSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress));
    if (bindStatus == -1) {
        perror("[-]Errore durante il binding\n");
        exit(1);
    }


    // Imposta la socket all'ascolto. I parametri sono il descrittore della socket e la massima lunghezza della coda di connessioni entranti
    if (listen(serverSocket, MAX_CONNESSIONI) != -1) {
        printf("Listening . . .\n\n");
    }
    else {
        perror("[-]Error during listening\n");
        exit(1);
    }


    while (1) {

        // Accettazione della connessione
        clientSocket = accept(serverSocket, (struct sockaddr*)&newAddress, &addrSize);
        if (clientSocket == -1) {
            exit(-1);
        }
        printf("%s:%d joined\n", inet_ntoa(newAddress.sin_addr), ntohs(newAddress.sin_port));

        child = fork();
        if (child == 0) {

            close(serverSocket);

            while (1) {

                // Ricezione del messaggio
                recv(clientSocket, buffer, 1024, 0);

                if (strcmp(buffer, ":exit") == 0) {
                    printf("%s:%d left\n", inet_ntoa(newAddress.sin_addr), ntohs(newAddress.sin_port));
                    break;
                }
                else {
                    printf("%s:%d wrote: %s\n", inet_ntoa(newAddress.sin_addr), ntohs(newAddress.sin_port), buffer);
                    // Invio del messaggio
                    send(clientSocket, buffer, strlen(buffer), 0);
                    bzero(buffer, sizeof(buffer));
                }

            }

        }

    }

    close(clientSocket);

    return 0;
}
  • Где ошибка?

Возможно, ошибка в этом файле при использовании функции scanf, но я не могу выяснить, почему это не работает должным образом. Или замените его, используя системный вызов read

. Обратите внимание:

Ciao, но идентификатор nread 6

1 Ответ

1 голос
/ 13 февраля 2020

Данные, которые вы отправляете и получаете, не включают в себя нулевой терминатор строки, вам нужно добавить это вручную:

Например:

ssize_t len = recv(clientSocket, buffer, sizeof buffer - 1, 0); // -1 for the zero terminator.
if(len <= 0)
    // process error.
buffer[len] = 0; // Zero-terminate received data.
printf("Server received: %s\n", buffer);

send и recv может отправить / получить меньше данных, чем вы просили. Код должен справиться с этим, изучив код возврата и вызвав send / recv в al oop.


. Я проверяю ваш код, запустив сервер эхо-сервера с socat:

$ socat -v tcp-l:2222,fork exec:'/bin/cat'
> 2020/02/13 11:36:42.099857  length=3 from=0 to=2
abc< 2020/02/13 11:36:42.099974  length=3 from=0 to=2
abc> 2020/02/13 11:36:48.589751  length=3 from=3 to=5
def< 2020/02/13 11:36:48.589843  length=3 from=3 to=5

Клиент:

$ ./debug/gcc/test 
> abc
Server received: abc
> def
Server received: def
>   C-c C-c
...