#include #include #include #include #include #include #include #include // atoi void *recv_task(void *arg); // 接收数据的线程任务函数 void *send_task(void *arg); // 发送数据的线程任务函数 int main(int argc, char const *argv[]) { if (argc != 2) { printf("usage: %s port\n", argv[0]); return 1; } int sfd = socket(AF_INET, SOCK_DGRAM, 0); if (sfd < 0) { perror("socket"); return -1; } // 绑定 ip 和端口号 (开启 UDP 服务) struct sockaddr_in bind_addr; bzero(&bind_addr, sizeof(bind_addr)); bind_addr.sin_family = AF_INET; bind_addr.sin_port = htons(atoi(argv[1])); bind_addr.sin_addr.s_addr = htonl(INADDR_ANY); // 主机 ip 中的任意一个都可以使用 if (bind(sfd, (struct sockaddr *)&bind_addr, sizeof(bind_addr)) != 0) { perror("bind"); close(sfd); return -1; } pthread_t t1, t2; pthread_create(&t1, NULL, recv_task, (void *)&sfd); pthread_create(&t2, NULL, send_task, &sfd); pthread_join(t2, NULL); pthread_cancel(t1); // 发完后,取消接收 pthread_join(t1, NULL); // 等待接收线程结束 close(sfd); return 0; } void *recv_task(void *arg) { int sock_fd = *((int *)arg); // 取出传入的 socket 描述符 printf("启动recv_task %d\n", sock_fd); char buf[128] = ""; struct sockaddr_in src_addr; // 发送数据的源地址 socklen_t sock_len; // 原地址 socket 的长度 while (1) { bzero(buf, sizeof(buf)); bzero(&src_addr, sizeof(src_addr)); ssize_t len = recvfrom(sock_fd, buf, sizeof(buf), 0, (struct sockaddr *)&src_addr, &sock_len); if (len < 0) { perror("recvfrom"); } char ip[INET_ADDRSTRLEN] = ""; int port = ntohs(src_addr.sin_port); inet_ntop(AF_INET, &src_addr.sin_addr.s_addr, ip, INET_ADDRSTRLEN); printf("%s:%d 说: %s\n", ip, port, buf); } } void *send_task(void *arg) { int sock_fd = *((int *)arg); // @192.168.1.2:8000 // hi,hello // good,disen // haha // yes // @:8500 // very,good char ip[INET_ADDRSTRLEN] = ""; int port = 0; struct sockaddr_in dst_addr; // 目标地址 while (1) { char buf[128] = ""; fgets(buf, sizeof(buf), stdin); buf[strlen(buf) - 1] = 0; // 去掉最后的换行 if (buf[0] == '@') { if (buf[1] == ':') { strcpy(ip, "127.0.0.1"); port = atoi(buf + 2); } else { strcpy(ip, strtok(buf + 1, ":")); port = atoi(strtok(NULL, ":")); } printf("ip:port is %s:%d\n",ip,port); // 重置 bzero(&dst_addr, sizeof(dst_addr)); dst_addr.sin_family = AF_INET; dst_addr.sin_port = htons(port); // inet_pton(AF_INET, ip, &dst_addr.sin_addr.s_addr); // 按ipv4转地址 dst_addr.sin_addr.s_addr = inet_addr(ip); // inet_pton(sock_fd, ip, &dst_addr.sin_addr.s_addr); // bug地方 } else { if (strncmp(buf, "exit", 4) == 0) { break; } if (port == 0) { printf("请先确认发送的目的ip和端口号\n"); continue; } // 发送数据 if (sendto(sock_fd, buf, strlen(buf), 0, (struct sockaddr *)&dst_addr, sizeof(dst_addr)) < 0) { perror("sendto"); } } } }