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

作业社区

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

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

胡汉三66 的学生作业:

udp_server.c #include /* See NOTES */ #include // socket() sendto() #include #include // inet_addr() htons() #include // memset() #include // fgets() #include // close() #include // exit() #include // signal() #include // waitpid() #include // pthread_create() #define LOGIN_SUCCESS 1 // 宏定义 登录成功 1 #define LOGIN_FAILURE 0 // 宏定义 登录失败 0 typedef struct{ // 线程参数结构体 char *ip; // IP unsigned char flag; // 标记 struct sockaddr_in *peer_addr; // 目标地址 结构体 }thread_type; void recv_data(int new_sockfd){ // 接收数据 int n = 0; char buf[1024] = {0}; struct sockaddr_in client_addr; // 客户端地址 int len = sizeof(client_addr); // 客户端地址大小 while(1){ memset(buf,0,sizeof(buf)); // 重置 buf空间为 0 n = recvfrom(new_sockfd,buf,sizeof(buf),0,(struct sockaddr *)&client_addr,&len); // 接收信息 if(n < 0){ perror("Fail to recvfrom"); exit(EXIT_FAILURE); } printf("================================\n"); printf("Recv from IP = %s\n", inet_ntoa(client_addr.sin_addr)); // 打印 客户端 IP printf("Recv from Port = %d\n", ntohs(client_addr.sin_port)); // 打印 客户端 端口 printf("Recv %d bytes : %s\n",n,buf); // 打印 接收的文件大小 接收的内容 if(strncmp(buf,"quit",4) == 0) // 如果输入 "quit" 退出程序 break; } close(new_sockfd); return ; } int init_socket(const char *ip,const char *port){ // 创建 子线程 套接字的 文件描述符 int sockfd; struct sockaddr_in my_addr; // 目标 地址结构体 int len = sizeof(my_addr); // 1.通过socket创建文件描述符 sockfd = socket(AF_INET,SOCK_DGRAM,0); // 子进程的 文件描述符 if(sockfd < 0){ perror("Fail to socket!"); exit(EXIT_FAILURE); } // 2.填充服务器的ip + port memset(&my_addr,0,sizeof(my_addr)); // 重置 my_addr空间为 0 my_addr.sin_family = AF_INET; // 设置 协议族(IP4) my_addr.sin_port = htons(atoi(port)); // 设置 目标网络端口 // port为0,系统 自动生成 一个端口 my_addr.sin_addr.s_addr = inet_addr(ip); // 设置 目标网络IP //3.把ip + port与socket绑定 if(bind(sockfd,(struct sockaddr *)&my_addr,len) < 0){ perror("Fail to bind"); exit(EXIT_FAILURE); } printf("wait recv data!\n"); return sockfd; // 返回 子进程 套接字的 文件描述符. } void *message_thread(void *arg){ thread_type *packet = (thread_type *)arg; // 线程参数 结构体 int new_sockfd; // 保存 子线程的 套接字 文件描述符 // 1.给用户 回复的 秘钥正确信息 char *ip = packet->ip; // ip unsigned char login_flag = packet->flag; // 标记 struct sockaddr_in *addr = packet->peer_addr; // 客户端地址 结构体 new_sockfd = init_socket(ip,"0"); // 创建 新的套接字 和 端口 准备用于通信 sendto(new_sockfd,&login_flag,sizeof(login_flag),0,(struct sockaddr *)addr,sizeof(struct sockaddr)); // 接收信息 // 2.接收数据 recv_data(new_sockfd); pthread_exit(NULL); // 退出线程 } void user_login(const char *ip,const char *port){ // 用户登录, 返回 子进程 套接字文件描述符 int sockfd; int n = 0; char buf[20] = {0}; struct sockaddr_in client_addr; // 客户端地址 int len = sizeof(client_addr); // 客户端地址大小 unsigned char login_flag; // 登录标记 pthread_t tid; // 线程 ID thread_type packet; // 线程参数 结构体 // 1.创建套接字 sockfd = init_socket(ip,port); // 2.接收登录信息, 父进程负责验证秘匙信息, 子进程负责与用户进行数据交互. while(1){ memset(buf,0,sizeof(buf)); // 重置 buf空间为 0 n = recvfrom(sockfd,buf,sizeof(buf),0,(struct sockaddr *)&client_addr,&len); // 接收信息 if(n < 0){ perror("Fail to recvfrom"); exit(EXIT_FAILURE); } printf("key = %s\n",buf); login_flag = (strncmp(buf,"root",4) == 0) ? LOGIN_SUCCESS : LOGIN_FAILURE; // 如果输入 密码正确为root, 返回标记为1 // 此时说明秘钥正确 if(login_flag == LOGIN_SUCCESS) // 如果 登录成功 { packet.flag = login_flag; // 标记 packet.ip = (char *)ip; // 服务端IP packet.peer_addr = &client_addr; // 客户端地址 结构体 // 创建子线程,子线程准备接收当前用户的数据 // 主线程负责接收用户的秘钥 pthread_create(&tid,NULL,message_thread,(void *)&packet); // 创建子线程 }else{ // 如果 登录失败 // 用父进程套接字 给客户端回复---登录失败 sendto(sockfd,&login_flag,sizeof(login_flag),0,(struct sockaddr *)&client_addr,len); // 接收信息 } pthread_detach(tid); // 把线程设置为分离式,线程结束后,系统会自动回收资源 } return ; } // ./a.out ip port int main(int argc, const char *argv[]) { int sockfd; if(argc != 3){ // 判断 输入数据 是否有3个 fprintf(stderr,"Usage : %s ip port!\n",argv[0]); exit(EXIT_FAILURE); } // 1.接收用户的秘钥, 准备登录 user_login(argv[1],argv[2]); // 2. 关闭文件描述符 close(sockfd); return 0; } udp_client.c #include /* See NOTES */ #include // socket() sendto() #include #include // inet_addr() htons() #include // memset() #include // fgets() #include // close() #include // exit() #define LOGIN_SUCCESS 1 // 宏定义 登录成功 1 #define LOGIN_FAILURE 0 // 宏定义 登录失败 0 void send_data(int sockfd,struct sockaddr_in *addr,int len){ int n = 0; char buf[1024] = {0}; while(1) { printf("Input : "); // 输入标志 memset(buf,0,sizeof(buf)); // 重置 buf空间为 0 fgets(buf,sizeof(buf),stdin); // 获取 输入信息 保存到 buf中 buf[strlen(buf) - 1] = '\0'; // '\n'--->'\0' n = sendto(sockfd,buf,strlen(buf),0,(struct sockaddr *)addr,len); // 发送 buf信息 到目标地址 if(n < 0) { perror("Fail to sendto"); exit(EXIT_FAILURE); } if(strncmp(buf,"quit",4) == 0) // 如果输入 "quit" 退出程序 break; } return ; } void user_login(int sockfd,struct sockaddr_in *addr,struct sockaddr_in *new_addr,int len){ int n = 0; char buf[1024] = {0}; unsigned char flag = LOGIN_FAILURE; // 登录标记 默认失败 while(1){ putchar('>'); // 输入标志 memset(buf,0,sizeof(buf)); // 重置 buf空间为 0 fgets(buf,sizeof(buf),stdin); // 获取 输入信息 保存到 buf中 buf[strlen(buf) - 1] = '\0'; // '\n'--->'\0' n = sendto(sockfd,buf,strlen(buf),0,(struct sockaddr *)addr,len); // 发送 buf信息 到目标地址 if(n < 0){ perror("Fail to sendto"); exit(EXIT_FAILURE); } recvfrom(sockfd,&flag,sizeof(flag),0,(struct sockaddr *)new_addr,&len); // 从服务端 接收 登录标记 // 用户登录标记 if(flag == LOGIN_SUCCESS) // 如果成功, 结束输入 break; else // 如果失败, 继续输入 printf("key is invalid,try again!\n"); } return ; } // ./a.out ip port int main(int argc, const char *argv[]) { int sockfd; struct sockaddr_in peer_addr; // 目标服务器 地址结构体 struct sockaddr_in server_addr; // 子进程服务器 地址结构体 int len = sizeof(peer_addr); if(argc != 3){ fprintf(stderr,"Usage : %s ip port!\n",argv[0]); exit(EXIT_FAILURE); } // 1.通过socket创建文件描述符 sockfd = socket(AF_INET,SOCK_DGRAM,0); if(sockfd < 0){ perror("Fail to socket!"); return -1; } // 2.填充服务器的ip + port memset(&peer_addr,0,sizeof(peer_addr)); // 重置 peer_addr空间为 0 peer_addr.sin_family = AF_INET; // 设置 协议族(IP4) peer_addr.sin_port = htons(atoi(argv[2])); // 设置 目标网络端口 peer_addr.sin_addr.s_addr = inet_addr(argv[1]); // 设置 目标网络IP // 3.发送登录数据 memset(&server_addr,0,sizeof(server_addr)); // 重置 server_addr空间为 0 user_login(sockfd,&peer_addr,&server_addr,len); // 用户登录 // 4.发送交互数据 send_data(sockfd,&server_addr,len); // 5.关闭文件描述符 close(sockfd); return 0; }

微信客服

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

帮助反馈 APP下载

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

公众号

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