C++中TCP通信实现文件传输

作为Computer networks课程的一个project,我们需要实现用TCP在mininet中client和server的相互通信,需要能够传输文本文件,binary file 和image file。整个project的目的还是比较明确的。我主要列出了一下几个问题,需要在代码中实现。

1. 实现main函数的接口

因为client和server 需要的参数需要通过命令行输入,所以需要用getoptlong函数来实现。

int main(int argc, char* argv[])
{
    int code;
    int flag;
    int server_port;
    int client_port;
    string hostname;
    string filename;
    while(1)
    {
      static struct option long_options[]={
           {"c", no_argument, &flag, 1},
            {"s", no_argument, &flag, 0},
            {"port", required_argument, 0, 'p'},
            {"host", required_argument, 0, 'h'},
            {"file", required_argument, 0, 'f'},
            {"sp", required_argument, 0, 'e'},
            {"cp", required_argument, 0, 'l'}
      };
      int option_index=0;
       code=getopt_long_only(argc,argv,"p:h:f:e:l:", long_options, &option_index);
       if(code==-1) break;
       switch(code)
       {
           case 'p': server_port=atoi(optarg); break;
            case 'h': hostname=string(optarg); break;
            case 'f': filename=string(optarg); break;
            case 'e': server_port=atoi(optarg);break;
            case 'l': client_port=atoi(optarg);break;
          default: break;
       }
    }
    if(flag)
        send_message(hostname.c_str(), server_port, filename.c_str(), client_port);
    else 
        run_server(server_port); 

 

2. 实现socket programming中的功能

在这个项目中提供了UDP的socket programming的接口,按照需要设置即可。

   // (1) Create a socket
    int sockfd = socket(AF_INET, SOCK_STREAM, 0); //hzd: socket interface structure

    // (2) Create a sockaddr_in to specify remote host and port
    struct sockaddr_in server_addr; // specify server's address
    server_addr.sin_family = AF_INET;

    // Step (2): specify socket address (hostname).
    // The socket will be a client, so call this unix helper function to convert a hostname string to a useable `hostent` struct.
    // hostname here may be 10.0.0.1
    struct hostent *host = gethostbyname(hostname); //hzd: instantiate a instance of host with name specified
    if (host == nullptr) {
        fprintf(stderr, "%s: unknown host\n", hostname);
        return -1;
    }
    memcpy(&(server_addr.sin_addr), host->h_addr, host->h_length);//hzd: copy the hostname to the server address

    // if we also we also want to bind client's socket to a port number...
    struct sockaddr_in my_addr;//hzd: the address of the client
    memset(&my_addr, 0, sizeof(my_addr));//hzd: alloctae memory for the my_addr.
    my_addr.sin_family = AF_INET;
    my_addr.sin_addr.s_addr = INADDR_ANY; //INADDRY_ANY == 0.0.0.0
    my_addr.sin_port = htons(client_port); //hzd: specify the port number of the client
    bind(sockfd, (struct sockaddr *) & my_addr, sizeof(my_addr));// hzd: bind the address of client to the socket


    // Step (3): Set the port value.
    // Use htons to convert from local byte order to network byte order.
    server_addr.sin_port = htons(port);//hzd: spcify the port of sever


    // (3) Connect to remote server
    if (connect(sockfd, (sockaddr *) &server_addr, sizeof(server_addr)) == -1) {
        perror("Error connecting stream socket");
        return -1;
    }
 

 

3. 连续send造成的粘包问题

由于TCP拥有优化算法,可以将多个send的数据被一个recv收到,所以造成粘包问题。本项目中会要求先发送文件长度,再发送文件,连续发送造成文件长度和文件粘合在一起,造成无法读出文件。解决办法是加入sleep()函数在两次send之间。这样就能将两次send分开了。

 

4. 大文件的接收问题

大文件的接受容易由于buffer长度的限制,造成丢失。因此需要设置一个MAX_MESSAGE_SIZE。分成多次完成接收。本来想要在send端也多次发送,效果不好。

5. 文件的读写

由于文件的类型不确定,打开文件都需要用binary格式,读写的时候一定要注意,用read()和write()函数,千万不要<<或者>>,因为后一种方式没法确定文件类型。

ifstream infile;
infile.open((const char*) msg,ios::in|ios::binary);
char* data;
infile.seekg(0, ios::end);
int length=infile.tellg();
infile.seekg(0, ios::beg);
data= new char[length];
infile.read(data,length);

 

原文链接: https://www.cnblogs.com/huzdong/p/13340522.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    C++中TCP通信实现文件传输

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/368305

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月2日 下午6:20
下一篇 2023年3月2日 下午6:20

相关推荐