2012-09-26 59 views
0

我有一個從(純文本)流套接字到「可以發送文件的東西」的小問題。一個月前,我寫了一個基本的聊天客戶端。現在我希望能夠發送和接收任何類型的文件。讓我們繼續閱讀PDF或圖片。我將列出我正在使用的資源,我認爲是正確的方向。我只需要幫助連接點。如何使用c socket api發送文件。

從我的研究看來,我需要先把文件,將其轉換爲二進制文件,然後發送。我猜我想要一個TCP風格,因爲我非常關心一個文件的數據包是否按順序排列。

我已閱讀插座上的Beej.us。我也沒有找到發送數據的部分。我確實發現發送不同的「數據類型」部分,即浮動等。

我猜我想要一個「數據報」而不是流。如果您知道本書中的部分,我確實有我的Unix網絡編程副本。我沒有找到看起來像這樣的部分。經過2,3個小時的研究後,我確實沒有發現任何簡單或清晰的事情。大多隻是沒有答案的論壇問題。

這就是我要開始。後來我會用自定義IP,端口等來改變它。 從Beej中獲取數據報 - 發送者。從命令行參數發送文本..

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <errno.h> 
#include <string.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <netdb.h> 

#define SERVERPORT "4950" // the port users will be connecting to 

int main(int argc, char *argv[]) 
{ 
    int sockfd; 
    struct addrinfo hints, *servinfo, *p; 
    int rv; 
    int numbytes; 

    if (argc != 3) { 
     fprintf(stderr,"usage: talker hostname message\n"); 
     exit(1); 
    } 

    memset(&hints, 0, sizeof hints); 
    hints.ai_family = AF_UNSPEC; 
    hints.ai_socktype = SOCK_DGRAM; // datagrams.. 

    if ((rv = getaddrinfo(argv[1], SERVERPORT, &hints, &servinfo)) != 0) { 
     fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); 
     return 1; 
    } 

    // loop through all the results and make a socket. 
    //I'm not sure about the need for a loop 
    for(p = servinfo; p != NULL; p = p->ai_next) { 
     if ((sockfd = socket(p->ai_family, p->ai_socktype, 
       p->ai_protocol)) == -1) { 
      perror("talker: socket"); 
      continue; 
     } 

     break; 
    } 

    if (p == NULL) { 
     fprintf(stderr, "talker: failed to bind socket\n"); 
     return 2; 
    } 
// here is where we would send a file. Lets say ./img.png 
// If I had to guess I'd need to write a custom packet, turn the file into binary, then to 
//a packet. Then call send while we still have packets. 
// Am I on the right track? 
    if ((numbytes = sendto(sockfd, argv[2], strlen(argv[2]), 0, 
      p->ai_addr, p->ai_addrlen)) == -1) { 
     perror("talker: sendto"); 
     exit(1); 
    } 

    freeaddrinfo(servinfo); 

    printf("talker: sent %d bytes to %s\n", numbytes, argv[1]); 
    close(sockfd); 

    return 0; 
} 

回答

1

啊,從哪裏開始....?

首先,你需要TCP(流),而不是UDP(數據報)。數據報的大小有限,UDP本質上不可靠。

其次,「將文件轉換爲二進制文件」:我想你會發現它是如何存儲在磁盤上的。 ;-)

第三,你可能想在實際文件之前發送某種頭文件。標題通常包含文件名,文件大小以及允許您將它與通過同一端口發送的任何其他消息(聊天?)區分開來的內容。

頭文件可能是固定大小的二進制數據塊,或者更像HTTP頭文件的可讀文件。

+0

是的。我遇到問題,從哪裏開始。對,數據報是UDP!如果我可以使用上個月的客戶端/服務器代碼,那很好。啊,當然他們是二元的。所以少做一件事,好。所以下一部分。發送標題。我想我明白。將一個簡單的文本字符串工作,或者有一個結構(我很快會谷歌)。現在我想知道我是否大規模推翻了這一點。這聽起來像,除了頭部我只需要發送讀取文件在它的原始狀態。 – L4nce0