From 85ec7b0f4311dd0ef380b9ffca567f8fe96740f1 Mon Sep 17 00:00:00 2001 From: xinghenLuyus <2593026969@qq.com> Date: Fri, 26 Dec 2025 14:33:01 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20linux=5Fchat.c?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- linux_chat.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 linux_chat.c diff --git a/linux_chat.c b/linux_chat.c new file mode 100644 index 0000000..f2b7bb1 --- /dev/null +++ b/linux_chat.c @@ -0,0 +1,105 @@ +#include +#include +#include +#include +#include +#include + +#include "common.h" + +/* 停等协议发送(带超时重传) */ +void send_with_stopwait(int sock, + struct sockaddr_in6 *peer, + struct packet *pkt) +{ + socklen_t len = sizeof(*peer); + + while (1) { + sendto(sock, pkt, sizeof(*pkt), 0, + (struct sockaddr *)peer, len); + + fd_set fds; + FD_ZERO(&fds); + FD_SET(sock, &fds); + + struct timeval tv; + tv.tv_sec = TIMEOUT_SEC; + tv.tv_usec = 0; + + int ret = select(sock + 1, &fds, NULL, NULL, &tv); + if (ret > 0) { + struct packet ack; + recvfrom(sock, &ack, sizeof(ack), 0, NULL, NULL); + if (ack.type == TYPE_ACK && ack.seq == pkt->seq) { + return; // 正确 ACK + } + } + printf("[timeout] retransmit\n"); + } +} + +int main(int argc, char *argv[]) +{ + if (argc != 2) { + printf("用法: %s <对方IPv6地址>\n", argv[0]); + return 1; + } + + int sock = socket(AF_INET6, SOCK_DGRAM, 0); + + /* 绑定本地 IPv6 端口 */ + struct sockaddr_in6 local; + memset(&local, 0, sizeof(local)); + local.sin6_family = AF_INET6; + local.sin6_addr = in6addr_any; + local.sin6_port = htons(PORT); + bind(sock, (struct sockaddr *)&local, sizeof(local)); + + /* 对端地址 */ + struct sockaddr_in6 peer; + memset(&peer, 0, sizeof(peer)); + peer.sin6_family = AF_INET6; + peer.sin6_port = htons(PORT); + inet_pton(AF_INET6, argv[1], &peer.sin6_addr); + + uint8_t send_seq = 0; + uint8_t recv_seq = 0; + struct packet pkt, rcv; + + printf("Linux UDP IPv6 Stop-Wait Chat\n"); + + 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); + 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, sizeof(rcv), 0, + (struct sockaddr *)&peer, sizeof(peer)); + } + } + + /* 发送 */ + printf(">> "); + if (!fgets(pkt.payload, sizeof(pkt.payload), stdin)) + break; + + pkt.seq = send_seq; + pkt.type = TYPE_DATA; + + send_with_stopwait(sock, &peer, &pkt); + send_seq ^= 1; + } + + close(sock); + return 0; +}