Files
stopwait_chat_ipv6/linux_chat.c
2025-12-26 15:00:11 +08:00

95 lines
2.6 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/time.h>
#include "common.h"
#define LOCAL_PORT 9000
#define PEER_PORT 9001
#define TIMEOUT_MS 200
int main(int argc, char *argv[]) {
if (argc != 2) {
printf("Usage: %s <Windows IPv6>\n", argv[0]);
return 1;
}
int sock = socket(AF_INET6, SOCK_DGRAM, 0);
struct sockaddr_in6 local = {0};
local.sin6_family = AF_INET6;
local.sin6_port = htons(LOCAL_PORT);
local.sin6_addr = in6addr_any;
bind(sock, (struct sockaddr*)&local, sizeof(local));
struct sockaddr_in6 peer = {0};
peer.sin6_family = AF_INET6;
peer.sin6_port = htons(PEER_PORT);
inet_pton(AF_INET6, argv[1], &peer.sin6_addr);
struct timeval tv = {0, TIMEOUT_MS * 1000};
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
uint8_t send_seq = 0;
uint8_t waiting_ack = 0;
packet_t last_pkt;
while (1) {
/* 尝试接收 */
packet_t pkt;
struct sockaddr_in6 from;
socklen_t fromlen = sizeof(from);
int n = recvfrom(sock, &pkt, sizeof(pkt), 0,
(struct sockaddr*)&from, &fromlen);
if (n > 0) {
if (pkt.type == TYPE_DATA) {
printf("\nPeer: %s", pkt.data);
packet_t ack = {0};
ack.type = TYPE_ACK;
ack.seq = pkt.seq;
sendto(sock, &ack, sizeof(ack), 0,
(struct sockaddr*)&peer, sizeof(peer));
}
else if (pkt.type == TYPE_ACK &&
waiting_ack && pkt.seq == send_seq) {
waiting_ack = 0;
send_seq ^= 1;
}
}
/* 如果不在等 ACK则允许发送 */
if (!waiting_ack) {
char buf[DATA_LEN];
printf("You: ");
fflush(stdout);
if (fgets(buf, sizeof(buf), stdin) == NULL)
continue;
memset(&last_pkt, 0, sizeof(last_pkt));
last_pkt.type = TYPE_DATA;
last_pkt.seq = send_seq;
last_pkt.length = strlen(buf);
memcpy(last_pkt.data, buf, last_pkt.length);
sendto(sock, &last_pkt, sizeof(last_pkt), 0,
(struct sockaddr*)&peer, sizeof(peer));
waiting_ack = 1;
} else {
/* 超时重传 */
sendto(sock, &last_pkt, sizeof(last_pkt), 0,
(struct sockaddr*)&peer, sizeof(peer));
usleep(TIMEOUT_MS * 1000);
}
}
}