From 30fd144f7cea04c4d8184c687a3033032a60c990 Mon Sep 17 00:00:00 2001 From: xinghen <2593026969@qq.com> Date: Fri, 26 Dec 2025 15:22:17 +0800 Subject: [PATCH] 2 --- linux_chat.c | 67 ++++++++++++++++++++++++++++++++------------------ windows_chat.c | 67 +++++++++++++++++++++++++++++++++----------------- 2 files changed, 88 insertions(+), 46 deletions(-) diff --git a/linux_chat.c b/linux_chat.c index e35e11c..c57bc27 100644 --- a/linux_chat.c +++ b/linux_chat.c @@ -4,9 +4,42 @@ #include #include #include +#include #include "common.h" +typedef struct { + int sock; + uint8_t *recv_seq; + struct sockaddr_in6 *peer; +} recv_args; + +void *receiver(void *arg) { + recv_args *a = (recv_args *)arg; + while (1) { + fd_set fds; + FD_ZERO(&fds); + FD_SET(a->sock, &fds); + struct timeval tv = {0, 100000}; + + if (select(a->sock + 1, &fds, NULL, NULL, &tv) > 0) { + struct packet rcv; + recvfrom(a->sock, &rcv, sizeof(rcv), 0, NULL, NULL); + rcv.payload[sizeof(rcv.payload) - 1] = '\0'; + if (rcv.type == TYPE_DATA) { + if (rcv.seq == *a->recv_seq) { + printf("\npeer: %s\n", rcv.payload); + *a->recv_seq ^= 1; + } + rcv.type = TYPE_ACK; + sendto(a->sock, &rcv, 2, 0, + (struct sockaddr *)a->peer, sizeof(*a->peer)); + } + } + } + return NULL; +} + /* 停等协议发送(带超时重传) */ void send_with_stopwait(int sock, struct sockaddr_in6 *peer, @@ -60,39 +93,25 @@ int main(int argc, char *argv[]) memset(&peer, 0, sizeof(peer)); peer.sin6_family = AF_INET6; peer.sin6_port = htons(PORT); - inet_pton(AF_INET6, argv[1], &peer.sin6_addr); + if (inet_pton(AF_INET6, argv[1], &peer.sin6_addr) != 1) { + printf("无效的 IPv6 地址\n"); + return 1; + } uint8_t send_seq = 0; uint8_t recv_seq = 0; - struct packet pkt, rcv; + struct packet pkt; memset(&pkt, 0, sizeof(pkt)); - memset(&rcv, 0, sizeof(rcv)); printf("Linux UDP IPv6 Stop-Wait Chat\n"); + // 启动接收线程 + recv_args args = {sock, &recv_seq, &peer}; + pthread_t recv_thread; + pthread_create(&recv_thread, NULL, receiver, &args); + while (1) { - /* 非阻塞接收 */ - fd_set fds; - FD_ZERO(&fds); - FD_SET(sock, &fds); - struct timeval tv = {0, 100000}; - - if (select(sock + 1, &fds, NULL, NULL, &tv) > 0) { - recvfrom(sock, &rcv, sizeof(rcv), 0, NULL, NULL); - rcv.payload[sizeof(rcv.payload) - 1] = '\0'; - if (rcv.type == TYPE_DATA) { - if (rcv.seq == recv_seq) { - printf("\npeer: %s\n", rcv.payload); - recv_seq ^= 1; - } - rcv.type = TYPE_ACK; - sendto(sock, &rcv, 2, 0, - (struct sockaddr *)&peer, sizeof(peer)); - } - } - - /* 发送 */ printf(">> "); if (!fgets(pkt.payload, sizeof(pkt.payload), stdin)) break; diff --git a/windows_chat.c b/windows_chat.c index c991470..ff3e817 100644 --- a/windows_chat.c +++ b/windows_chat.c @@ -2,11 +2,43 @@ #include #include #include +#include #include "common.h" #pragma comment(lib, "ws2_32.lib") +typedef struct { + SOCKET sock; + uint8_t *recv_seq; + struct sockaddr_in6 *peer; +} recv_args; + +void receiver(void *arg) { + recv_args *a = (recv_args *)arg; + while (1) { + fd_set fds; + FD_ZERO(&fds); + FD_SET(a->sock, &fds); + TIMEVAL tv = {0, 100000}; + + if (select(a->sock + 1, &fds, NULL, NULL, &tv) > 0) { + struct packet rcv; + recvfrom(a->sock, (char *)&rcv, sizeof(rcv), 0, NULL, NULL); + rcv.payload[sizeof(rcv.payload) - 1] = '\0'; + if (rcv.type == TYPE_DATA) { + if (rcv.seq == *a->recv_seq) { + printf("\npeer: %s\n", rcv.payload); + *a->recv_seq ^= 1; + } + rcv.type = TYPE_ACK; + sendto(a->sock, (char *)&rcv, 2, 0, + (struct sockaddr *)a->peer, sizeof(*a->peer)); + } + } + } +} + void send_with_stopwait(SOCKET sock, struct sockaddr_in6 *peer, struct packet *pkt, int pkt_len) @@ -14,6 +46,7 @@ void send_with_stopwait(SOCKET sock, int addr_len = sizeof(*peer); while (1) { + printf("Sending seq %d\n", pkt->seq); sendto(sock, (char *)pkt, pkt_len, 0, (struct sockaddr *)peer, addr_len); @@ -26,10 +59,13 @@ void send_with_stopwait(SOCKET sock, tv.tv_usec = 0; int ret = select(sock + 1, &fds, NULL, NULL, &tv); + printf("Select returned %d\n", ret); if (ret > 0) { struct packet ack; recvfrom(sock, (char *)&ack, sizeof(ack), 0, NULL, NULL); + printf("Received ack seq %d type %d\n", ack.seq, ack.type); if (ack.type == TYPE_ACK && ack.seq == pkt->seq) { + printf("Correct ACK received\n"); return; } } @@ -58,37 +94,24 @@ int main(int argc, char *argv[]) struct sockaddr_in6 peer = {0}; peer.sin6_family = AF_INET6; peer.sin6_port = htons(PORT); - inet_pton(AF_INET6, argv[1], &peer.sin6_addr); + if (inet_pton(AF_INET6, argv[1], &peer.sin6_addr) != 1) { + printf("无效的 IPv6 地址\n"); + return 1; + } uint8_t send_seq = 0; uint8_t recv_seq = 0; - struct packet pkt, rcv; + struct packet pkt; memset(&pkt, 0, sizeof(pkt)); - memset(&rcv, 0, sizeof(rcv)); printf("Windows UDP IPv6 Stop-Wait Chat\n"); + // 启动接收线程 + recv_args args = {sock, &recv_seq, &peer}; + _beginthread(receiver, 0, &args); + while (1) { - fd_set fds; - FD_ZERO(&fds); - FD_SET(sock, &fds); - TIMEVAL tv = {0, 100000}; - - if (select(sock + 1, &fds, NULL, NULL, &tv) > 0) { - recvfrom(sock, (char *)&rcv, sizeof(rcv), 0, NULL, NULL); - rcv.payload[sizeof(rcv.payload) - 1] = '\0'; - if (rcv.type == TYPE_DATA) { - if (rcv.seq == recv_seq) { - printf("\npeer: %s\n", rcv.payload); - recv_seq ^= 1; - } - rcv.type = TYPE_ACK; - sendto(sock, (char *)&rcv, 2, 0, - (struct sockaddr *)&peer, sizeof(peer)); - } - } - printf(">> "); if (!fgets(pkt.payload, sizeof(pkt.payload), stdin)) break;