1

Cのソケットに基づいて単純なクライアントとサーバーを作成しようとしています。クライアントはchar配列のサイズ(「\ 0」の最後のセルを含む)を送信してから、charの配列を送信します。サーバーはサイズを取得し、クライアントから文字の配列にメモリを割り当てようとします。この後、サーバーはスペースを探し、文字をインデックス0からスペースにコピーし、配列の最後に貼り付けてクライアントに送り返します(スペースがない場合、サーバーは2倍の配列を送信します)。

時々私が得ていることに気づきました-|00| | 02 | --サーバーから受信した配列の最後にあるchar。valgrindを使用してサーバーとクライアントを実行しましたが、サーバーに問題があることがわかりました。

以下のコード。

クライアント:

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>



int
main ()
{
    int sockfd;
    socklen_t len;
    struct sockaddr_in address;
    int result;

    char ch;
    char *string;
    int i;

    sockfd = socket (AF_INET, SOCK_STREAM, 0);

    address.sin_family = AF_INET;
    address.sin_addr.s_addr = inet_addr ("127.0.0.1"); 
    address.sin_port = htons (9734);
    len = sizeof (address);

    result = connect (sockfd, (struct sockaddr *) &address, len);

    if (result == -1)
    {
        perror ("oops: netclient");
        exit (1);
    }

    string = (char*)malloc(sizeof(char));

    for (i =0; ch = getchar(); i++)
    {
        string = (char*)realloc(string, (i+1)*sizeof(char));

        if(ch != '\n')
            string[i] = ch;
        else if (ch == '\n')
        {
            string[i]='\0';
            break;
        }
    }

    printf("%s\n", string);
    printf("%d\n", i);
    i=i+1;

    write (sockfd, &i, 4);

    write (sockfd, string, i);


    read (sockfd, &i, 4);


    string = (char*)realloc(string, i*sizeof(char));

    read (sockfd, string, i); 

    printf("String recieved: %s\n", string);

    close (sockfd);

    free(string);

    exit (0);
}

そしてサーバー:

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>

int
main ()
{
    int server_sockfd, client_sockfd; 
    socklen_t server_len, client_len; 
    struct sockaddr_in server_address; 
    struct sockaddr_in client_address; 

    server_sockfd = socket (AF_INET, SOCK_STREAM, 0); 
    server_address.sin_family = AF_INET; /*ipv4*/
    server_address.sin_addr.s_addr = htonl (INADDR_ANY); 
    server_address.sin_port = htons (9734);
    server_len = sizeof (server_address);
    bind (server_sockfd, (struct sockaddr *) &server_address, server_len); 


    listen (server_sockfd, 5); 
    signal (SIGCHLD, SIG_IGN);

    while (1)
    {
        char *string;
        int i, j, k, l=0; /*variables to iteration*/
        printf ("server waiting\n");


        client_len = sizeof (client_address);
        client_sockfd = accept (server_sockfd,
                (struct sockaddr *) &client_address,
                &client_len); 


        if (fork () == 0)
        {


            read (client_sockfd, &i, 4);
            printf("recieved int %d\n", i);
            string = (char*)malloc(sizeof(char) * (i));
            read (client_sockfd, string, i);
            printf("\nSTRING recieved: %s \n", string);

            for(j=0; string[j]!='\0'; j++)
            {
                if(string[j] == ' ')
                {
                    i = i+j; /*size to enlarge*/
                    break;
                }
            }

            /*sending new size*/
            write(client_sockfd, &i, 4);

            /*enlarge the string*/
            string = (char*)realloc(string, i*sizeof(char));

            for (k = i-j-1; k < i-1 ; k ++)
            {
                string[k] = string[l];
                l++;
            }
            string[k+1] = '\0';

            write(client_sockfd, string, i);


            close (client_sockfd);

            free(string);

            exit (0);
        }



        else
        {
            close (client_sockfd);
        }
    }
}
4

1 に答える 1

2

read()あなたのコードは:の戻り値を無視します

        read (client_sockfd, &i, 4);

この値を無視してはなりません。ソケットインターフェイスは、4バイトを要求したからといって、実際に4バイトが返されることを保証するものではありません。ソケットインターフェイスは、少なくとも1バイトが返されることを保証するだけです。必要read()なすべてのバイトを取得するまで、呼び出しを続ける必要があります。

数行後に文字列を読んだときにも同じことが言えます。

プログラムは現在機能しているように見えるかもしれませんが、これは、ビジー状態のマシンやネットワークなどの予測できない状況で突然発生し、再現できなくなり、プログラムの信頼性が低下するような問題です。

于 2012-04-24T01:36:43.160 に答える