0

一个简单的服务器和客户端,我可以发送文件,我需要你们看看这个源是否完成。因为我认为它不会下载完整的文件。

也许对这个来源有限制?因为我上传/下载了 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 返回发送的总字节数,可以小于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 回答