-1

クライアントからサーバーにソケットを介してファイルを送信すると、ファイル サイズが変化します。どこに問題があるのでしょうか?

クライアント側のコードは次のとおりです。

char chunk[512];
host_info = gethostbyname(server);
if (host_info == NULL) {
    perror("get host by name");
    exit(errno);
}

socket_desc = socket(AF_INET, SOCK_STREAM, 0);
if (socket_desc < 0) {
    perror("socket");
    exit(errno);
}

server_address.sin_family = host_info->h_addrtype;
memcpy((char *) &server_address.sin_addr.s_addr, host_info->h_addr_list[0], host_info->h_length);
server_address.sin_port = htons(PORT);

if (connect(socket_desc, (struct sockaddr *) &server_address, sizeof(server_address)) < 0) {
    perror("connect");
    exit(errno);
}


file_to_send = fopen (lfile,"rb");
if(!file_to_send) {
    perror("fopen");
    close(socket_desc);
    exit(errno);
} else {
    long file_size;
    fseek (file_to_send, 0, SEEK_END);     
    file_size = ftell (file_to_send);
    rewind(file_to_send);
while(totally_read < file_size){
    chunk[0] = '\0';
    bytes_read = fread(chunk, sizeof(char), sizeof(chunk), file_to_send);
    totally_read += bytes_read;
    int sent = send(socket_desc, chunk, bytes_read, 0);
    if(sent < 0){
        perror("connect");
        exit(errno);
    }
    totally_sent += sent;
    printf("read: %7db sent: %7db totally read: %7db totally sent: %7db\n", bytes_read, sent, totally_read, totally_sent);
}

そして、ここにサーバー側があります:

char chunk[512];
listen_socket = socket(AF_INET, SOCK_STREAM, 0);
if (listen_socket < 0) {
    perror("socket");
    close(listen_socket);
    exit(errno);
}

server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = htonl(INADDR_ANY);
server_address.sin_port = htons(PORT);

if (bind(listen_socket, (struct sockaddr *) &server_address, sizeof(server_address)) < 0) {
    perror("bind");
    close(listen_socket);
    exit(errno);
}

listen(listen_socket, 5);
client_address_length = sizeof(client_address);

while(1){    
    connect_socket = accept(listen_socket, (struct sockaddr *) &client_address, &client_address_length);
    if (connect_socket < 0) {
    perror("accept");
    close(listen_socket);
    exit(errno);
}

recv_file = fopen(filename,"wb");
int received = 0;
int totally_wrote = 0, totally_received = 0;
while(1){
    chunk[0] = '\0';
    received = recv(connect_socket, chunk, sizeof(chunk), 0);
    if(received < 0) {
        perror("recv");
    } else if(received > 0) {
        int wrote = fwrite(chunk, sizeof(char), received, recv_file);
        totally_wrote +=wrote;
        totally_received += received;
        printf("received: %7db wrote: %7db totally received: %7db torally wrote: %7db\n", received, wrote, totally_received, totally_wrote);
    } else {
        printf("Complete!\n");
        break;
    }
}

テキスト ファイルを送信すると、クライアント側で次の出力が得られます。

totally read:  299695b   |   totally sent:  299695b

しかし、サーバー側では:

totally received:  303279b   |   torally wrote:  303279b

エディターでファイルを開きました。送信されたファイルは、最初の奇妙なデータを除いて、ソース ファイルと実質的に同じです。転送されるファイルは、チャンクサイズが512バイトの場合、先頭に3584バイトのバイナリデータが追加されます。チャンク サイズを 256 バイトに変更すると、3840 バイトが追加されます。

4

1 に答える 1

1

send() からの戻り値をチェックしていません Send() は、-1 から 3 番目 (長さ) の引数までの任意の値を返すことができます。戻り値 > 0 は 3 番目の引数と等しいと仮定します。そうである必要はありません。

短い send() (または recv() (または read() / write())) を処理するには、次のようなものが必要です。

int sent, pos, bytes_read;
bytes_read = fread(chunk, sizeof(char), sizeof(chunk), file_to_send);

totally_read += bytes_read;

for (pos = 0; pos < bytes_read; pos += sent) {
    sent = send(socket_desc, chunk+pos, bytes_read-pos, 0)
    switch(sent) {
    case -1: /* handle errno here, especially EAGAIN/EINTR */
    case 0: /*handle EOF here */
        break;
    default:
        break;
        }
    }
totally_sent += pos;
于 2012-10-27T14:23:48.863 に答える