0

ファイルを送信できるシンプルなサーバーとクライアントです。このソースが完成したかどうかを確認する必要があります。完全なファイルをダウンロードしないと思います。

そして多分このソースには限界がありますか?Cuz 200K ともう少しアップロード/ダウンロードした..

サーバ:

#include <WinSock2.h>
#include <Windows.h>
#include <stdio.h>

#pragma comment(lib, "Ws2_32.lib")

SOCKET Socket, Sub;
WSADATA Winsock;
sockaddr_in Addr;
int Addrlen = sizeof(sockaddr_in);
char Buffer[256];
char *Str;
sockaddr_in IncomingAddress;
int AddressLen = sizeof(IncomingAddress);

int main()
{
    WSAStartup(MAKEWORD(2, 2), &Winsock);    // Start Winsock

    if(LOBYTE(Winsock.wVersion) != 2 || HIBYTE(Winsock.wVersion) != 2)    // Check version
    {
        WSACleanup();
        return 0;
    }

     Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    ZeroMemory(&Addr, sizeof(Addr));
    Addr.sin_family = AF_INET;
    Addr.sin_port = htons(6091);  
    bind(Socket, (sockaddr*)&Addr, sizeof(Addr));

    if(listen(Socket, 1) == SOCKET_ERROR)
    {
        printf("listening error\n");
    }
    else
    {
        printf("listening ok\n");
    }

    if(Sub = accept(Socket, (sockaddr*)&IncomingAddress, &AddressLen))
    {
        char *ClientIP = inet_ntoa(IncomingAddress.sin_addr);
        int ClientPort = ntohs(IncomingAddress.sin_port);
        printf("Client conncted!\n");
        printf("IP: %s:%d\n", ClientIP, ClientPort);

        printf("Sending file .. \n");


        FILE *File;
        char *Buffer;
        unsigned long Size;

        File = fopen("C:\\Prog.exe", "rb");
        if(!File)
        {
            printf("Error while readaing the file\n");
            goto End;
        }

        fseek(File, 0, SEEK_END);
        Size = ftell(File);
        fseek(File, 0, SEEK_SET);

        Buffer = new char[Size];

        fread(Buffer, Size, 1, File);
        char cSize[MAX_PATH];
        sprintf(cSize, "%i", Size);

        fclose(File);

        send(Sub, cSize, MAX_PATH, 0); // File size
        send(Sub, Buffer, Size, 0); // File Binary
        free(Buffer);

End:
        closesocket(Sub);
        closesocket(Socket);
        WSACleanup();
    }

    getchar();
    return 0;
}

クライアント:

#include <WinSock2.h>
#include <Windows.h>
#include <stdio.h>

#pragma comment(lib, "Ws2_32.lib")

SOCKET Socket;
WSADATA Winsock;
sockaddr_in Addr;
int Addrlen = sizeof(Addr);

int main()
{
    WSAStartup(MAKEWORD(2, 2), &Winsock);    // Start Winsock

    if(LOBYTE(Winsock.wVersion) != 2 || HIBYTE(Winsock.wVersion) != 2)    // Check version
    {
        WSACleanup();
        return 0;
    }

     Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    ZeroMemory(&Addr, sizeof(Addr));    // clear the struct
    Addr.sin_family = AF_INET;    // set the address family
    Addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    Addr.sin_port = htons(6091);    // set the port

    if(connect(Socket, (sockaddr*)&Addr, sizeof(Addr)) < 0)
    {
        printf("Connection failed !\n");
        getchar();
        return 0;
    }

    printf("Connection successful !\n");

    printf("Receiving file .. \n");

    int Size;
    char *Filesize = new char[1024];

    if(recv(Socket, Filesize, 1024, 0)) // File size
    {
        Size = atoi((const char*)Filesize);
        printf("File size: %d\n", Size);
    }

    char *Buffer = new char[Size];

    if(recv(Socket, Buffer, Size, 0)) // File Binary
    {
        FILE *File;
        File = fopen("Prog.exe", "wb");
        fwrite((const char*)Buffer, 1, Size, File);
        fclose(File);
    }

    getchar();
    closesocket(Socket);
    WSACleanup();
    return 0;
}

ありがとう。

4

2 に答える 2

5

大量のデータを送受信しようとすると、コードが失敗する可能性があります。send 関数のドキュメントから:

戻り値
エラーが発生しない場合、send は送信された合計バイト数を返します。これは、len パラメータで送信するように要求された数よりも少ない場合があります。それ以外の場合は、 の値SOCKET_ERRORが返され、 を呼び出すことで特定のエラー コードを取得できますWSAGetLastError

の戻り値を確認し、send()送信要求されたバイト数よりも小さい場合はsend()、残りのデータを再度呼び出す必要があります。例:

char *data = Buffer; // data to be sent
int len = Size;      // number of bytes to be sent
while (len > 0) {
    int amount = send(Sub, data, len, 0);
    if (amount == SOCKET_ERRROR) {
        // handle error ...
    } else {
        len -= amount;
        data += amount;
    }
}

recv()同じことがクライアントでの呼び出しにも当てはまります。

于 2013-03-02T04:45:31.047 に答える
1

これは、ファイルをバイナリとして読み取り、データを送信するファイル送信関数です。これは独立した関数で、v がデータを送信する必要があるソケットの値と、送信する必要があるファイル パスを渡すだけです。

void FileSend(SOCKET FileSendSocket,char *FilePath)
{
    streampos filesize = 0;
    ifstream in(FilePath,ios::binary);
    ZeroMemory( &sendbuf, sendbuflen);

    if(in.is_open())
    {
        while(1)
        {
            in.read(sendbuf,sendbuflen);
            if(in.eof())
            {
                cout << "End of File sending from Client" <<  endl; 
                in.close();
                break;
            }
            else
            {
                send(FileSendSocket,sendbuf,sendbuflen,0);
                ZeroMemory( &sendbuf, sendbuflen);
            }
        }
    }

}

これはクライアント側の受信関数であり、受信関数のすぐ隣で呼び出す必要があります。この関数は、サーバーが送信するデータを継続的に書き込みます。

ofstream out("C:\\Prog.exe",ios::binary);
void FileReceive(char* recvbuf, int recvbuflen)
{
    if(out.is_open())
    {
            out.write(recvbuf,recvbuflen);
            ZeroMemory(&recvbuf,recvbuflen);
    }
}
于 2013-03-02T10:22:47.953 に答える