1

私はcを使用してサーバークライアントプログラムを構築しており、send()およびrecv()関数を使用してファイル全体を送信することに問題があります。これらを含むファイル全体を送信する必要がありますが、これらの関数でできることは文字列を送信することだけです。主な問題は、exe またはその他のバイナリ形式のデータを送信することです。htons または htonl func を使用する必要がありますか? 私は単なる初心者なので、これらに沿ってそれらを使用する方法がわかりません。

私はこれで立ち往生しており、あなたの助けが大好きです. ありがとう!!

これがサーバー側のrecv関数です::

if (socket_type != SOCK_DGRAM)
    {

            fi = fopen (final,"wb");
            retval = recv(msgsock, recv_buf, strlen(recv_buf), 0);
            /*recv_buf[retval] = '\0';
            fprintf (fi,"%s",recv_buf);*/

            int i;
            i=atoi(recv_buf);
            char *q;
            q=(char *)malloc(i*sizeof(char));
            retval = recv(msgsock, q, strlen(q), 0);
            //printf ("%s",q);
            fwrite(q,i,1,fi);
            fclose(fi);

    }
    else
    {
        retval = recvfrom(msgsock,recv_buf, sizeof(recv_buf), 0, (struct sockaddr *)&from, &fromlen);
        printf("Server: Received datagram from %s\n", inet_ntoa(from.sin_addr));
        printf ("SOCK_DGRAM");
    }

    if (retval == SOCKET_ERROR)
    {
        fprintf(stderr,"Server: recv() failed: error %d\n", WSAGetLastError());
        closesocket(msgsock);
        //continue;
    }
    else
        printf("Server: recv() is OK.\n");

    if (retval == 0)
    {
        printf("Server: Client closed connection.\n");
        closesocket(msgsock);
            //continue;
    }
    printf("Server: Received %d bytes, data from client\n", retval);

クライアント側送信関数 :::

void send_command() { int バイト送信; ファイル *file_out; //file_out = fopen(file_path,"rb"); char str_all[100000];//フラグ [30]="終了";

///////////////////////getsize//////////////
char fsize[5];
int filesize;
file_out = fopen(file_path, "rb");
fseek(file_out, 0, SEEK_END);
filesize = ftell(file_out);
rewind (file_out);
itoa (filesize,fsize,10);
/////////////////////////////////////////////
send (ConnectSocket, fsize, strlen (fsize), 0);

char *r = (char *)malloc (filesize * sizeof(char));

fread(r,filesize,1,file_out);
bytesent = send( ConnectSocket, r, strlen(r), 0 );
printf("\nClient: Bytes sent: %ld\n", bytesent);
fclose (file_out);

/*while (fscanf(file_out,"%s",&str_all) != EOF)
{
    bytesent = send( ConnectSocket, str_all, strlen(str_all), 0 );
    printf("\nClient: Bytes sent: %ld\n", bytesent);
    //Sleep(500);
}*/

/*printf("%s",flag);
send( ConnectSocket, flag, strlen(flag), 0 );*/
WSACleanup();
//return 0;
}
4

4 に答える 4

3

その機能を自分で実装するか、そうするライブラリを使用する必要があります。 send(2)生のバイトバッファを送信するだけです。ファイルを送信する場合は、クライアントとサーバーの両方が理解できる何らかのプロトコルを使用する必要があります。

最も単純なプロトコルは、クライアントにファイル名、ファイルの長さ、そして未加工のファイル データを送信させることです。例(わかりやすくするためにエラーチェックは省略):

// Server:
const char *filename = ...;
uint32_t filenameLen = strlen(filename);
uint32_t filenameLenNet = htonl(filenameLen);
send(fd, &filenameLenNet, sizeof(filenameLenNet), 0);
send(fd, filename, filenameLen, 0);

// You should probably use a 64-bit file length; also, for large files, you
// don't want to read the entire file into memory, you should just stream it
// from disk to network in reasonably-sized chunks.
const void *fileData = ...;
uint32_t fileLen = ...;
uint32_t fileLenNet = htonl(fileLen);
send(fd, &fileLenNet, sizeof(fileLenNet), 0);
send(fd, fileData, fileLen, 0);

// Client:
char *filename;
uint32_t filenameLen;
recv(fd, &filenameLen, sizeof(filenameLen), 0);
filenameLen = ntohl(filenameLen);
filename = malloc(filenameLen + 1);
recv(fd, filename, filenameLen, 0);
filename[filenameLen] = 0;
uint32_t fileLen;
recv(fd, &fileLen, sizeof(fileLen), 0);
fileLen = ntohl(fileLen);
void *fileData = malloc(fileLen);
recv(fd, fileData, fileLen, 0);
// Write file Data to the output file.  Again, for large files, it would be
// better to stream it in in chunks instead of reading it all in at once.

また、部分的な送受信にも注意してください。sendおよびからの戻り値を確認してくださいrecv。送信または受信するデータのサブセットしか送信または受信できないことが多いためです。その場合、意図したデータをすべて処理するか、エラーが発生するまで、ループで再送信または再受信して回復する必要があります。

独自のプロトコルを使用する代わりに、libftplibcurlなどのライブラリで既存のプロトコルを使用できます。

于 2010-01-17T21:42:46.433 に答える
3

send() は文字列を送信するのではなく、バイト配列を送信します。バッファーを作成し、それを埋め、バッファーを送信し、その中のバイト数を send() に渡し、そこから渡します。

于 2010-01-17T21:18:06.283 に答える
2

sendfile使用しているオペレーティング システムによっては、コマンドがある場合があります。ただし、異なるオペレーティング システム間で移植可能に動作することは保証されていません。最も移植性の高い方法はread()、ファイルをチャンクでバッファに入れ、それwrite()から取り出すことです (send()ソケットを使用している場合は、それもwrite()問題なく動作するはずです)。

本質的に同じことを尋ねるこの前の質問に対する私の回答を参照してください。

于 2010-01-17T21:21:21.827 に答える
1

あなたがしなければならないことは、一度に 1 つのチャンクで、いくつかのチャンクでデータを送信することです。したがって、基本的には、ファイルを一度に N バイトずつバッファーに読み込み、それらの N バイトを send() します。

于 2010-01-17T21:23:44.053 に答える