C ++ Winsock发送文件[关闭]

Posted

技术标签:

【中文标题】C ++ Winsock发送文件[关闭]【英文标题】:C++ Winsock Sending file [closed] 【发布时间】:2013-03-02 02:53:09 【问题描述】:

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

也许对这个来源有限制?因为我上传/下载了 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;

谢谢。

【问题讨论】:

在将缓冲区写入文件之前,您是否尝试在客户端检查缓冲区的内容? 你是什么意思? p.s 我删除了一些我没用过的东西。 我不清楚问题或问题到底是什么。 【参考方案1】:

如果您尝试发送/接收大量数据,您的代码可能会失败。来自send function的文档:

返回值 如果没有发生错误,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()调用也是如此。

【讨论】:

我对那个主题很感兴趣:/你能把它添加到我的源代码中吗?我试过了,但它对我不起作用;D【参考方案2】:

这是文件发送函数,它将以二进制形式读取文件并发送数据。这是一个独立的函数,只是传递 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);
    

【讨论】:

以上是关于C ++ Winsock发送文件[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Winsock 中发送文件(http 方式)

vb以二进制打开excel后用winsock发送,结果接收后打开的是乱码,发送别的文件没问题,为啥?

Winsock 发送函数

用winsock发送位图

C++ Winsock 结构发送/接收

Winsock 不发送,显示连接失败