【操作体系】Linux之网络编程(UDP)(头歌作业)

[复制链接]
发表于 2024-11-25 14:28:00 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
第1关:UDP套接字创建与端口绑定

  1. #include <sys/types.h>
  2. #include <sys/socket.h>
  3. #include <arpa/inet.h>
  4. #include <stdio.h>
  5. #include <errno.h>
  6. #include <string.h>
  7. /************************
  8. * port: 需要绑定的端口号
  9. * 返回值: 调用成功返回0,否则返回-1
  10. *************************/
  11. int UDPSocket(unsigned short port)
  12. {
  13.         int ret = -1;
  14.         /********** BEGIN **********/
  15.         int sockfd;
  16.     struct sockaddr_in server_addr;
  17.     // 创建UDP套接字
  18.     sockfd = socket(AF_INET, SOCK_DGRAM, 0);
  19.     if (sockfd == -1)
  20.     {
  21.         printf("创建UDP套接字失败: %s\n", strerror(errno));
  22.         return -1;
  23.     }
  24.     // 初始化服务器地址结构体
  25.     memset(&server_addr, 0, sizeof(server_addr));
  26.     server_addr.sin_family = AF_INET;
  27.     server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  28.     server_addr.sin_port = htons(port);
  29.     // 绑定端口
  30.     ret = bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
  31.     if (ret == -1)
  32.     {
  33.         printf("绑定端口失败: %s\n", strerror(errno));
  34.         close(sockfd);
  35.         return -1;
  36.     }
  37.     ret = 0;
  38.        
  39.         /********** END **********/
  40.        
  41.         return ret;
  42. }
复制代码
第2关:UDP数据传送

  1. #include <sys/types.h>
  2. #include <sys/socket.h>
  3. #include <arpa/inet.h>
  4. #include <stdio.h>
  5. #include <errno.h>
  6. #include <string.h>
  7. #include <unistd.h>
  8. #define PORT 8888
  9. int main()
  10. {
  11.         int sockfd;
  12.         sockfd = socket(AF_INET, SOCK_DGRAM, 0);
  13.         if(sockfd == -1)
  14.         {
  15.                 return -1;
  16.         }
  17.         struct sockaddr_in addr;
  18.         bzero(&addr, sizeof(addr));    //清空
  19.         addr.sin_family = AF_INET;
  20.         addr.sin_port = htons(PORT);
  21.         addr.sin_addr.s_addr = htonl(INADDR_ANY);
  22.         //与PORT端口进行绑定
  23.         if(bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
  24.         {
  25.                 return -1;
  26.         }
  27.        
  28.         char data[100];
  29.         //接收客户端传来的数据,并打印出来(提示:换行打印)
  30.         //同时将接收到的数据原样发送给客户端
  31.         //当接收到"exit"字符串时,退出当前程序,不打印出"exit"字符串
  32.         //提示:在每次接收字符串前要将存放字符串的变量清空
  33.         /********** BEGIN **********/
  34.         struct sockaddr_in clientAddr;
  35.     socklen_t clientAddrLen = sizeof(clientAddr);
  36.     while (1)
  37.     {
  38.         // 每次接收前清空存放字符串的变量
  39.         memset(data, 0, sizeof(data));
  40.         ssize_t recvLen = recvfrom(sockfd, data, sizeof(data), 0, (struct sockaddr *)&clientAddr, &clientAddrLen);
  41.         if (recvLen == -1)
  42.         {
  43.             printf("接收数据失败: %s\n", strerror(errno));
  44.             continue;
  45.         }
  46.         else if (recvLen > 0)
  47.         {
  48.             // 去掉字符串末尾可能的换行符等空白字符
  49.             while (data[recvLen - 1] == '\n' || data[recvLen - 1] == '\r' || data[recvLen - 1] == '\t' || data[recvLen - 1] == ' ')
  50.             {
  51.                 data[recvLen - 1] = '\0';
  52.                 recvLen--;
  53.             }
  54.             if (strcmp(data, "exit") == 0)
  55.             {
  56.                 break;
  57.             }
  58.             // 换行打印接收到的数据
  59.             printf("%s\n", data);
  60.             // 将接收到的数据原样发送给客户端
  61.             ssize_t sendLen = sendto(sockfd, data, recvLen, 0, (struct sockaddr *)&clientAddr, clientAddrLen);
  62.             if (sendLen == -1)
  63.             {
  64.                 printf("发送数据失败: %s\n", strerror(errno));
  65.             }
  66.         }
  67.     }
  68.        
  69.         /********** END **********/
  70.         close(sockfd);
  71.        
  72.         return 0;
  73. }
复制代码
第3关:项目实战

  1. #include <stdio.h>
  2. #include <sys/types.h>
  3. #include <sys/socket.h>
  4. #include <netinet/in.h>
  5. #include <arpa/inet.h>
  6. #include <string.h>
  7. #include <errno.h>
  8. #include <sys/types.h>
  9. #include <sys/stat.h>
  10. #include <fcntl.h>
  11. #include <unistd.h>
  12. //定义数据块大小
  13. char data[16];
  14. //定义服务器端口和服务器地址
  15. #define PORT 8889
  16. #define SERVER_IP "127.0.0.1"
  17. int main(int argc, char *argv[])
  18. {
  19.         int sockfd;
  20.         sockfd = socket(AF_INET, SOCK_DGRAM, 0);
  21.         if(sockfd == -1)
  22.         {
  23.                 return -1;
  24.         }
  25.         struct sockaddr_in servAddr;
  26.         int servAddrLen = sizeof(servAddr);
  27.         bzero(&servAddr, sizeof(servAddr));
  28.         servAddr.sin_family = AF_INET;
  29.         servAddr.sin_port = htons(PORT);
  30.         servAddr.sin_addr.s_addr = inet_addr(SERVER_IP);
  31.        
  32.         //由用户传入的要下载文件的名称
  33.         char *downLoadFileName = argv[1];
  34.         printf("%s\n", argv[1]);
  35.         //先在本地创建要下载的文件
  36.         int fd = fd = open(downLoadFileName, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
  37.         //向服务器发送要上传文件的名称
  38.         sendto(sockfd, downLoadFileName, strlen(downLoadFileName), 0, (struct sockaddr *)&servAddr, servAddrLen);
  39.        
  40.     /********** BEGIN **********/
  41.         char ack[16];
  42.     int recvLen;
  43.     // 循环接收服务器发送的数据块
  44.     while (1)
  45.     {
  46.         // 接收服务器发送的数据块
  47.         recvLen = recvfrom(sockfd, data, sizeof(data), 0, (struct sockaddr *)&servAddr, &servAddrLen);
  48.         if (recvLen == -1)
  49.         {
  50.             printf("接收数据失败: %s\n", strerror(errno));
  51.             continue;
  52.         }
  53.         // 根据数据块类型判断是否下载完成
  54.         if (data[0] == 'e')
  55.         {
  56.             // 下载完成,关闭文件并退出程序
  57.             close(fd);
  58.             break;
  59.         }
  60.         else if (data[0] == 'c')
  61.         {
  62.             // 数据块为文件内容,将内容写入本地文件
  63.             write(fd, &(data[1]), recvLen - 1);
  64.         }
  65.         // 向服务器发送接收确认请求
  66.         sendto(sockfd, "OK", strlen("OK"), 0, (struct sockaddr *)&servAddr, servAddrLen);
  67.         // 清空数据块数据部分(除了类型标识字节)
  68.         memset(&(data[1]), 0, sizeof(data) - 1);
  69.     }
  70.        
  71.         /********** END **********/
  72.        
  73.         close(sockfd);
  74.        
  75.         return 0;
  76. }
复制代码
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表