为了账号安全,请及时绑定邮箱和手机立即绑定

作业社区

探索学习新天地,共享知识资源!

0 提交作业
0 布置作业
0 满分作业
得分 100
学习任务

邓文兵 的学生作业:

#define FILENAME_SZ 256 //定义上传文件名最大长度 /** * 利用TCP协议模拟文件传输过程,其中还采用了原始数据包添加头部,解决粘包问题策略 */ //定义文件传输协议头部 typedef struct file_protocol { size_t filesize;//指定文件大小 char filename[FILENAME_SZ];//文件名 }file_protocol_t; //服务器解析(文件协议头+文件数据) 的头部,封装进file_protocol_t结构体中 int recv_protocol_head(int new_fd,file_protocol_t *p_head) { //先对齐文件协议头首部,稍后填充文件协议头 char *buffer=(char*)p_head; //每次收到的字节数 int rbytes=0; //总共收到的字节数 ssize_t total_received=0; //开始接收数据 while(true) { //从客户端连接好的套接字文件描述符中接收数据,每次接完需要往buffer里面写,注意起始位置需要往后偏移当前收到的字节数个位置 //其中第三个参数为剩余的最大接收窗口长度 rbytes=recv_package(new_fd,buffer+total_received,sizeof(file_protocol_t)-total_received); if(rbytes==-1) { DEBUG_INFO("recv_package failed...\n"); return -1; }else if(rbytes==0) { DEBUG_INFO("connection closed...\n"); break; }else if(rbytes>0) { //累计每次接收到的字节数 total_received+=rbytes; //文件头部协议长度接收完毕 if(total_received==sizeof(file_protocol_t)) { break; } } } if(total_received!=sizeof(file_protocol_t)) { DEBUG_INFO("received failed\n"); return -1; } return 0; }

得分 100
学习任务

邓文兵 的学生作业:

//测试服务器通信 void test_server(int argc,char *argv[]) { //先判断读入参数是否符合格式要求 if(argc!=3) { fprintf(stderr,"Usage: %s \n",argv[0]); exit(EXIT_FAILURE); } //创建服务器专门用于监听客户端请求文件描述符与专用通信文件描述符 int sockfd,new_fd; //初始化成功连接客户端配置结构体 struct sockaddr_in client_info{}; socklen_t len=sizeof(struct sockaddr_in); //获取服务端套接字文件描述符 sockfd=create_TCPSERVER_socket(argv[1],atoi(argv[2])); if(sockfd==-1) { exit(EXIT_FAILURE); } //服务端绑定并监听端口接收客户端请求 new_fd=accept_client(sockfd,&client_info,&len); if(new_fd==-1) { exit(EXIT_FAILURE); } //三次握手成功建立连接打印客户端配置信息 print_tcp_network_address(&client_info); //开始与客户端进行收发通信 //服务端是有两个文件描述符需要关闭,一个用于监听连接,一个用于与客户端进行通信 close(sockfd); close(new_fd); } //测试客户端通信 void test_client(int argc,char *argv[]) { if(argc!=3) { fprintf(stderr,"Usage: %s \n",argv[0]); exit(EXIT_FAILURE); } int sockfd; //创建客户端socket套接字文件描述符,并于服务器进行连接 sockfd=create_TCPCLIENT_socket(argv[1],atoi(argv[2])); //处理连接失败异常 if(sockfd==-1) { exit(EXIT_FAILURE); } close(sockfd); }

得分 100
学习任务

邓文兵 的学生作业:

int accept_client(int sockfd) { int new_fd; //初始化客户端的配置结构体 struct sockaddr_in client_info; socklen_t len=sizeof(struct sockaddr_in); //服务器从传入的专门用于监听客户端连接的文件描述符接收到客户端的连接请求,并获取专门用于与客户端收发使用的新的文件描述符 //可以从TCP数据包中获取客户端的配置信息,可选择获取与否,不获取后两个参数填nullptr,nullptr new_fd=accept(sockfd,(struct sockaddr*)&client_info,&len); //处理连接建立异常 if(new_fd==-1) { DEBUG_INFO("accept failed...\n"); return -1; } //返回专用与客户端通信的文件描述符 return new_fd; } int create_TCPCLIENT_socket(char *ip,unsigned short port) { int sockfd; int ret; //创建客户端文件描述符 sockfd=socket(AF_INET,SOCK_STREAM,0); if(sockfd==-1) { DEBUG_INFO("Socket creation failed...\n"); return -1; } //服务器配置结构体初始化 struct sockaddr_in server_info{}; socklen_t len=sizeof(struct sockaddr_in); server_info.sin_family=AF_INET; server_info.sin_port=htons(port); server_info.sin_addr.s_addr=inet_addr(ip); //客户端尝试与服务器连接 ret=connect(sockfd,(struct sockaddr*)&server_info,len); //连接异常处理 if(ret==-1) { DEBUG_INFO("Connect failed...\n"); return -1; } //返回连接成功的客户端文件描述符 return sockfd; }

得分 100
学习任务

邓文兵 的学生作业:

//Tcp服务端,使用方式 ./server ip port void TCP_SERVER_THREAD(int argc, char *argv[]) { //定义的两个文件描述符,前者专门用于监听客户端的连接请求,后者用来成功建立连接以后与客户端进行的通信 int sockfd,new_fd; int ret; //定义服务端端收发数据字节数 ssize_t sbytes,rbytes; //定义收发数据缓冲区 char buffer[1024]; pthread_t tid; memset(&buffer,0,sizeof(buffer)); //服务器配置结构体,客户端配置结构体 sockaddr_in server_addr,client_addr; //参数判断 if(argc!=3) { //提示正确用法 printf("Usage: %s \n", argv[0]); exit(EXIT_FAILURE); } //创建套接字,传入TCP格式的,获取文件fd用于给客户端收发消息 sockfd=socket(AF_INET, SOCK_STREAM, 0); //判断是否创建套接字成功 if(sockfd==-1) { perror("socket create failed"); exit(EXIT_FAILURE); } //创建成功,开始绑定服务器的ip地址与port端口号 socklen_t len = sizeof(server_addr); //设置协议族,设置端口号、网址 server_addr.sin_family=AF_INET; server_addr.sin_port=htons(atoi(argv[2])); server_addr.sin_addr.s_addr=inet_addr(argv[1]); //服务器将套接字文件描述符与服务器配置结构体进行一个绑定 ret=bind(sockfd,(struct sockaddr*)&server_addr,len); //处理绑定异常 if(ret==-1) { perror("[ERROR] bind failed"); close(sockfd); exit(EXIT_FAILURE); } //套接字绑定好以后,开始使用listen接口监听,listen内部会做两件事 //1.将套接字文件描述符设置为监听状态。2.建立监听队列用于监听来自客户端的连接请求,主要是设置监听队列的最大长度,当超出最大长度时,说明过多的客户端请求连接 //后续的更多的客户端请求连接,将会遭到服务器的拒绝(监听队列时用来缓存客户端的连接请求) ret=listen(sockfd,BACKLOG); if(ret==-1) { perror("[ERROR] listen failed"); close(sockfd); exit(EXIT_FAILURE); } //准备工作做好,可以开始尝试处理客户端的连接通信请求 //传入监听文件描述符,客户端配置信息结构体,结构体的长度,获取到一个新的专门用于与客户端进行通信收发的文件描述符 new_fd=accept(sockfd,(struct sockaddr*)&client_addr,&len); if(new_fd==-1) { perror("[ERROR] connection failed"); //退出以前需要关闭套接字资源 close(sockfd); exit(EXIT_FAILURE); } //为了验证连接建立成功,可以尝试打印获取到的客户端的配置信息,打印时,将网络字节序转换为本地ip地址与端口号 std::cout

得分 100
学习任务

邓文兵 的学生作业:

为了使接收方传输层TCP协议能够区分应用层数据包的开始与结束,双方约定在发送时,在原始数据包头增加固定长度的描述字段,示意接下来的完整的数据包的长度;接收方每次先接收固定长度的头部,读取到即将接收的数据包的长度,采用循环接收直到收到的字节数达到解析出来的长度为止,此时为一个完整的数据包接收。从而解决粘包问题。 客户端,发送数据包时,在发出的数据前增加固定长度的头部描述完整数据包的长度 //客户端发送逻辑 putchar('>'); //从标准输入中接收客户端希望发送的消息 fgets(buffer,sizeof(buffer),stdin); buffer[strlen(buffer)-1]='\0';//将换行符换成字符串结束符 //发送数据以前需要检查用户是否期望quit退出通信 if(strncmp(buffer,"quit",4)==0) {//比较buffer的前4个字节是否为quit break;//退出循环 } //在原始数据包前增加长度头部逻辑,先读取原本的数据包长度,增加4个字节长度描述长度 length=strlen(buffer); pbuffer=new char[length+4]; //先往pbuffer里面写入数据包长度 memcpy(pbuffer,&length,4); //将原始内容拷贝至pbuffer,但是起始位置变为pbuffer+4的位置 memcpy(pbuffer+4,buffer,length); //客户端往服务器发送信息,发送的格式为----长度头部+buffer原始数据包 sbytes=send(sockfd,pbuffer,length+4,0); //处理发送异常 if(sbytes==-1) { perror("[ERROR] send failed"); close(sockfd); exit(EXIT_FAILURE); }else { //发送成功,console打印发送消息 std::cout

得分 100
学习任务

邓文兵 的学生作业:

//Tcp服务端,使用方式 ./server ip port void TCP_SERVER(int argc, char *argv[]) { //定义的两个文件描述符,前者专门用于监听客户端的连接请求,后者用来成功建立连接以后与客户端进行的通信 int sockfd,new_fd; int ret; //定义服务端端收发数据字节数 ssize_t sbytes,rbytes; //定义收发数据缓冲区 char buffer[1024]; memset(&buffer,0,sizeof(buffer)); //服务器配置结构体,客户端配置结构体 sockaddr_in server_addr,client_addr; //参数判断 if(argc!=3) { //提示正确用法 printf("Usage: %s \n", argv[0]); exit(EXIT_FAILURE); } //创建套接字,传入TCP格式的,获取文件fd用于给客户端收发消息 sockfd=socket(AF_INET, SOCK_STREAM, 0); //判断是否创建套接字成功 if(sockfd==-1) { perror("socket create failed"); exit(EXIT_FAILURE); } //创建成功,开始绑定服务器的ip地址与port端口号 socklen_t len = sizeof(server_addr); //设置协议族,设置端口号、网址 server_addr.sin_family=AF_INET; server_addr.sin_port=htons(atoi(argv[2])); server_addr.sin_addr.s_addr=inet_addr(argv[1]); //服务器将套接字文件描述符与服务器配置结构体进行一个绑定 ret=bind(sockfd,(struct sockaddr*)&server_addr,len); //处理绑定异常 if(ret==-1) { perror("[ERROR] bind failed"); close(sockfd); exit(EXIT_FAILURE); } //套接字绑定好以后,开始使用listen接口监听,listen内部会做两件事 //1.将套接字文件描述符设置为监听状态。2.建立监听队列用于监听来自客户端的连接请求,主要是设置监听队列的最大长度,当超出最大长度时,说明过多的客户端请求连接 //后续的更多的客户端请求连接,将会遭到服务器的拒绝(监听队列时用来缓存客户端的连接请求) ret=listen(sockfd,BACKLOG); if(ret==-1) { perror("[ERROR] listen failed"); close(sockfd); exit(EXIT_FAILURE); } //准备工作做好,可以开始尝试处理客户端的连接通信请求 //传入监听文件描述符,客户端配置信息结构体,结构体的长度,获取到一个新的专门用于与客户端进行通信收发的文件描述符 new_fd=accept(sockfd,(struct sockaddr*)&client_addr,&len); if(new_fd==-1) { perror("[ERROR] connection failed"); //退出以前需要关闭套接字资源 close(sockfd); exit(EXIT_FAILURE); } //为了验证连接建立成功,可以尝试打印获取到的客户端的配置信息,打印时,将网络字节序转换为本地ip地址与端口号 std::cout

得分 100
学习任务

邓文兵 的学生作业:

//Tcp服务端,使用方式 ./server ip port void TCP_SERVER(int argc, char *argv[]) { //定义的两个文件描述符,前者专门用于监听客户端的连接请求,后者用来成功建立连接以后与客户端进行的通信 int sockfd,new_fd; int ret; //定义服务端端收发数据字节数 ssize_t sbytes,rbytes; //定义收发数据缓冲区 char buffer[1024]; memset(&buffer,0,sizeof(buffer)); //服务器配置结构体,客户端配置结构体 sockaddr_in server_addr,client_addr; //参数判断 if(argc!=3) { //提示正确用法 printf("Usage: %s \n", argv[0]); exit(EXIT_FAILURE); } //创建套接字,传入TCP格式的,获取文件fd用于给客户端收发消息 sockfd=socket(AF_INET, SOCK_STREAM, 0); //判断是否创建套接字成功 if(sockfd==-1) { perror("socket create failed"); exit(EXIT_FAILURE); } //创建成功,开始绑定服务器的ip地址与port端口号 socklen_t len = sizeof(server_addr); //设置协议族,设置端口号、网址 server_addr.sin_family=AF_INET; server_addr.sin_port=htons(atoi(argv[2])); server_addr.sin_addr.s_addr=inet_addr(argv[1]); //服务器将套接字文件描述符与服务器配置结构体进行一个绑定 ret=bind(sockfd,(struct sockaddr*)&server_addr,len); //处理绑定异常 if(ret==-1) { perror("[ERROR] bind failed"); close(sockfd); exit(EXIT_FAILURE); } //套接字绑定好以后,开始使用listen接口监听,listen内部会做两件事 //1.将套接字文件描述符设置为监听状态。2.建立监听队列用于监听来自客户端的连接请求,主要是设置监听队列的最大长度,当超出最大长度时,说明过多的客户端请求连接 //后续的更多的客户端请求连接,将会遭到服务器的拒绝(监听队列时用来缓存客户端的连接请求) ret=listen(sockfd,BACKLOG); if(ret==-1) { perror("[ERROR] listen failed"); close(sockfd); exit(EXIT_FAILURE); } //准备工作做好,可以开始尝试处理客户端的连接通信请求 //传入监听文件描述符,客户端配置信息结构体,结构体的长度,获取到一个新的专门用于与客户端进行通信收发的文件描述符 new_fd=accept(sockfd,(struct sockaddr*)&client_addr,&len); if(new_fd==-1) { perror("[ERROR] connection failed"); //退出以前需要关闭套接字资源 close(sockfd); exit(EXIT_FAILURE); } //为了验证连接建立成功,可以尝试打印获取到的客户端的配置信息,打印时,将网络字节序转换为本地ip地址与端口号 std::cout

得分 100
学习任务

邓文兵 的学生作业:

#include #include #include #include #include #include //Tcp客户端,使用方式 ./client ip port int main(int argc, char *argv[]) { int sockfd; int ret; //定义客户端收发数据字节数 ssize_t sbytes,rbytes; //定义收发数据缓冲区 char buffer[1024]; memset(&buffer,0,sizeof(buffer)); sockaddr_in server_addr; //参数判断 if(argc!=3) { //提示正确用法 printf("Usage: %s \n", argv[0]); exit(EXIT_FAILURE); } //创建套接字,传入TCP格式的,获取文件fd用于往服务器发送消息 sockfd=socket(AF_INET, SOCK_STREAM, 0); //判断是否创建套接字成功 if(sockfd==-1) { perror("socket create failed"); exit(EXIT_FAILURE); } //创建成功,开始绑定服务器的ip地址与port端口号 socklen_t len = sizeof(server_addr); //设置协议族,设置端口号、网址 server_addr.sin_family=AF_INET; server_addr.sin_port=htons(atoi(argv[2])); server_addr.sin_addr.s_addr=inet_addr(argv[1]); //准备工作做好,可以开始tcp三次挥手尝试与服务器建立连接 //传入文件描述符,服务器配置信息结构体,结构体的长度 ret=connect(sockfd, (struct sockaddr*)&server_addr, len); if(ret==-1) { perror("[ERROR] connect failed"); //退出以前需要关闭套接字资源 close(sockfd); exit(EXIT_FAILURE); } //建立成功可以与服务器进行收发通信,在循环中进行不断地收发过程 while(true) { //客户端发送逻辑 putchar('>'); //从标准输入中接收客户端希望发送的消息 fgets(buffer,sizeof(buffer),stdin); buffer[strlen(buffer)-1]='\0';//将换行符换成字符串结束符 //发送数据以前需要检查用户是否期望quit退出通信 if(strncmp(buffer,"quit",4)==0) {//比较buffer的前4个字节是否为quit break;//退出循环 } //客户端往服务器发送信息 sbytes=send(sockfd,buffer,sizeof(buffer),0); //处理发送异常 if(sbytes==-1) { perror("[ERROR] send failed"); close(sockfd); exit(EXIT_FAILURE); }else { //发送成功,console打印发送消息 std::cout

微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号