作为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大佬
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/368305
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!