2013-03-02 158 views
-1

一個簡單的服務器和客戶端,我可以發送文件, 我需要你們看看這個源碼是否完成。 因爲我認爲它不會下載完整的文件。C++ Winsock發送文件

也許這個來源有一個限制?因爲我上載/下載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; 
} 

感謝。

+0

您是否嘗試在將其寫入文件之前檢查客戶端緩衝區的內容? – 2013-03-02 03:02:03

+0

你的意思是?我刪除了一些我沒有用過的東西。 – 2013-03-02 03:16:50

+0

我不清楚問題或問題究竟是什麼。 – jogojapan 2013-03-02 09:13:49

回答

4

如果您嘗試發送/接收大量數據,您的代碼可能會失敗。從send function的文檔:

返回值
如果沒有錯誤發生,發送返回的 發送的字節數的總數,其可以是小於所請求的數量將被髮送在 的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()也是如此。

+0

我在這個主題吸吮:/你可以把它添加到我的來源..?我試過了,但它對我不起作用; D – 2013-03-02 05:51:57

0

這是文件發送功能,它將以二進制形式讀取文件併發送數據。這是一個獨立的函數,只需傳遞需要發送數據的套接字的值以及我們需要發送的文件路徑。

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); 
    } 
}