// 群聊 #include #include #include #include #include #include #include #include #include /* * ./a.out port */ void *recv_task(void *arg); void *send_task(void *arg); int bind_port; int main(int argc, char const *argv[]) { if (argc < 2) { printf("usage: %s port\n", argv[0]); return -1; } int sock_fd = socket(AF_INET, SOCK_DGRAM, 0); if (sock_fd < 0) { perror("socket"); return EXIT_FAILURE; // 1 } bind_port = atoi(argv[1]); // 绑定端口 struct sockaddr_in bind_addr; memset(&bind_addr, 0, sizeof(bind_addr)); bind_addr.sin_family = AF_INET; bind_addr.sin_port = htons(bind_port); bind_addr.sin_addr.s_addr = htonl(INADDR_ANY); bind(sock_fd, (struct sockaddr *)&bind_addr, sizeof(bind_addr)); // 绑定文件描述符和地址端口 // 设置 socket 选项为广播 int val = 1; int ret = setsockopt(sock_fd, SOL_SOCKET, SO_BROADCAST, &val, sizeof(val)); if (ret != 0) { perror("setsockopt"); } pthread_t tid1, tid2; pthread_create(&tid1, NULL, recv_task, &sock_fd); pthread_create(&tid2, NULL, send_task, &sock_fd); pthread_join(tid2, NULL); pthread_cancel(tid1); pthread_join(tid1, NULL); printf("---over---\n"); close(sock_fd); return 0; } void *recv_task(void *arg) { int sock_fd = *((int *)arg); while (1) { struct sockaddr_in data_addr; socklen_t data_addr_len = sizeof(data_addr); bzero(&data_addr, data_addr_len); char buf[128] = ""; ssize_t recv_len = recvfrom(sock_fd, buf, 128, 0, (struct sockaddr *)&data_addr, &data_addr_len); if (recv_len > 0) { char ip[16] = ""; inet_ntop(AF_INET, &data_addr.sin_addr.s_addr, ip, 16); printf("%s(%d): %s\n", ip, ntohs(data_addr.sin_port), buf); } } } void *send_task(void *arg) { int sock_fd = *((int *)arg); while (1) { char buf[128] = ""; if (fgets(buf, 128, stdin) != NULL) { buf[strlen(buf) - 1] = 0; struct sockaddr_in addr; bzero(&addr, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(bind_port); addr.sin_addr.s_addr = inet_addr("10.35.188.255"); // 一定是广播地址 sendto(sock_fd, buf, strlen(buf) + 1, 0, (struct sockaddr *)&addr, sizeof(addr)); if (strncmp(buf, "bye", 3) == 0) { break; } if (strncmp(buf, "clear", 5) == 0) { system("clear"); } } } }