diff --git a/linux_chat.c b/linux_chat.c index c571732..d063c52 100644 --- a/linux_chat.c +++ b/linux_chat.c @@ -10,7 +10,7 @@ #define LOCAL_PORT 9000 #define PEER_PORT 9001 -#define TIMEOUT_MS 500 +#define TIMEOUT_MS 200 int main(int argc, char *argv[]) { if (argc != 2) { @@ -19,16 +19,11 @@ int main(int argc, char *argv[]) { } int sock = socket(AF_INET6, SOCK_DGRAM, 0); - if (sock < 0) { - perror("socket"); - return 1; - } 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}; @@ -36,46 +31,64 @@ int main(int argc, char *argv[]) { peer.sin6_port = htons(PEER_PORT); inet_pton(AF_INET6, argv[1], &peer.sin6_addr); - struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = TIMEOUT_MS * 1000; + struct timeval tv = {0, TIMEOUT_MS * 1000}; setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); - uint8_t seq = 0; - char input[DATA_LEN]; + uint8_t send_seq = 0; + uint8_t waiting_ack = 0; + packet_t last_pkt; while (1) { - printf("You: "); - fflush(stdout); - fgets(input, sizeof(input), stdin); + /* 尝试接收 */ + packet_t pkt; + struct sockaddr_in6 from; + socklen_t fromlen = sizeof(from); - packet_t pkt = {0}; - pkt.type = TYPE_DATA; - pkt.seq = seq; - pkt.length = strlen(input); - memcpy(pkt.data, input, pkt.length); + int n = recvfrom(sock, &pkt, sizeof(pkt), 0, + (struct sockaddr*)&from, &fromlen); - while (1) { - sendto(sock, &pkt, sizeof(pkt), 0, - (struct sockaddr*)&peer, sizeof(peer)); + if (n > 0) { + if (pkt.type == TYPE_DATA) { + printf("\nPeer: %s", pkt.data); - packet_t ack; - struct sockaddr_in6 from; - socklen_t fromlen = sizeof(from); + packet_t ack = {0}; + ack.type = TYPE_ACK; + ack.seq = pkt.seq; - int n = recvfrom(sock, &ack, sizeof(ack), 0, - (struct sockaddr*)&from, &fromlen); - - if (n > 0 && ack.type == TYPE_ACK && ack.seq == seq) { - break; + 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; } - - usleep(TIMEOUT_MS * 1000); } - seq ^= 1; - } + /* 如果不在等 ACK,则允许发送 */ + if (!waiting_ack) { + char buf[DATA_LEN]; + printf("You: "); + fflush(stdout); - close(sock); - return 0; + 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); + } + } }