diff --git a/windows_chat.c b/windows_chat.c new file mode 100644 index 0000000..3967cfc --- /dev/null +++ b/windows_chat.c @@ -0,0 +1,102 @@ +#include +#include +#include +#include + +#include "common.h" + +#pragma comment(lib, "ws2_32.lib") + +void send_with_stopwait(SOCKET sock, + struct sockaddr_in6 *peer, + struct packet *pkt) +{ + int len = sizeof(*peer); + + while (1) { + sendto(sock, (char *)pkt, sizeof(*pkt), 0, + (struct sockaddr *)peer, len); + + fd_set fds; + FD_ZERO(&fds); + FD_SET(sock, &fds); + + TIMEVAL tv; + tv.tv_sec = TIMEOUT_SEC; + tv.tv_usec = 0; + + int ret = select(0, &fds, NULL, NULL, &tv); + if (ret > 0) { + struct packet ack; + recvfrom(sock, (char *)&ack, sizeof(ack), 0, NULL, NULL); + if (ack.type == TYPE_ACK && ack.seq == pkt->seq) { + return; + } + } + printf("[timeout] retransmit\n"); + } +} + +int main(int argc, char *argv[]) +{ + if (argc != 2) { + printf("用法: %s <对方IPv6地址>\n", argv[0]); + return 1; + } + + WSADATA wsa; + WSAStartup(MAKEWORD(2, 2), &wsa); + + SOCKET sock = socket(AF_INET6, SOCK_DGRAM, 0); + + struct sockaddr_in6 local = {0}; + 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 = {0}; + 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("Windows UDP IPv6 Stop-Wait Chat\n"); + + while (1) { + fd_set fds; + FD_ZERO(&fds); + FD_SET(sock, &fds); + TIMEVAL tv = {0, 100000}; + + if (select(0, &fds, NULL, NULL, &tv) > 0) { + recvfrom(sock, (char *)&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, (char *)&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; + } + + closesocket(sock); + WSACleanup(); + return 0; +}