/* alternating bit receiver for internet datagram demo */ /* modification 9/20/93 with Louis Sanchez's bug fix */ #include #include #include #include #include #include #include #include #include #define DATA 1 #define ACK 2 struct Msg { struct sockaddr_in dst; struct sockaddr_in src; char msgtype; char buf[80]; char alternating_bit; }; void help_msg() { printf("format: abreceiver -[d] c2host c2portno\n"); printf(" option: d set debug mode\n"); } void printsockaddr(struct sockaddr_in *arg) { struct hostent *hp; printf(" sockaddr_in: "); printf("Domain=%d, ", arg->sin_family); hp=gethostbyaddr((char *)&(arg->sin_addr), sizeof(arg->sin_addr), AF_INET); printf("Hostname=%s, ", hp->h_name); printf("Port=%d, ", ntohs(arg->sin_port)); printf("Address=%s,\n", inet_ntoa(arg->sin_addr)); } main(int argc, char *argv[]) { int sock; struct sockaddr_in from; struct sockaddr_in to; struct sockaddr_in C2addr; struct hostent *hp; int n; int state=1; struct Msg m; char AltBit; int c; extern char *optarg; extern int optind; int option_exist = 0; int counter = 0; int length; int debug = 1; char *C2Host; /* channel C2's host name */ int C2PortNo; /* process command line args */ while ((c=getopt(argc,argv,"d")) != EOF) { option_exist = 1; switch(c) { case 'd': debug = 1; printf("set debug mode on\n"); break; case '?': help_msg(); exit (1); default: fprintf (stderr, "unrecognized arg >%s<\n", optarg); help_msg(); exit (1); } } C2Host = argv[optind++]; C2PortNo = atoi(argv[optind++]); printf("C2hostname=%s, C2PortNo=%d\n", C2Host, C2PortNo); /* create socket from which to read */ sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock < 0) { perror("opening datagram socket"); exit(1); } /* create name structure with wildcard using INADDR_ANY */ from.sin_family = AF_INET; from.sin_addr.s_addr = INADDR_ANY; from.sin_port = 0; /* port no. < 1024 IPPORT_RESERVED is for privillege process */ /* here just initialized it, it will be assigned value after call */ /* getsockname() */ if (bind(sock, (struct sockaddr_in *)&from, sizeof(struct sockaddr_in))) { perror("binding name to datagram socket"); exit(1); } length = sizeof(from); if (getsockname(sock, (struct sockaddr_in *)&from, (socklen_t *)&length)) { perror("getting socket name"); exit(1); } /* Find assigned port value and print out. */ printf("socket has port #%d\n", ntohs(from.sin_port)); hp = gethostbyname(C2Host); if (hp == 0) { fprintf(stderr, "%s: unknown host", C2Host); exit(2); } bcopy(hp->h_addr, &C2addr.sin_addr, hp->h_length); /* in system V unix use memcpy */ /* memcpy(&C2addr.sin_addr, hp->h_addr, hp->h_length); */ C2addr.sin_family = AF_INET; C2addr.sin_port = htons(C2PortNo); AltBit = 0; //## while (1) { printf("\nState%d: ", state); switch(state) { case 1: if(recv(sock, &m, sizeof(m), 0) < 0) perror("receiving datagram message"); printf("Received +D%d msg=%s", m.alternating_bit, m.buf); if (AltBit != m.alternating_bit) { printf(" It is dupliate or error!"); state = 8; } else state = 2; break; case 2: printf("Deliver data=%s\n", m.buf); state= 3; break; case 3: bcopy(&m.src, &to, sizeof(to)); bcopy(&m.dst, &m.src, sizeof(to)); bcopy(&to, &m.dst, sizeof(to)); m.msgtype = ACK; printf("Sending A0"); if (sendto(sock, &m, sizeof(m), 0, (struct sockaddr_in *)&C2addr, sizeof(C2addr)) < 0) perror("send ACK message"); AltBit = !AltBit; //## state = 4; break; case 4: if(recv(sock, &m, sizeof(m), 0) < 0) perror("receiving datagram message"); printf("Received +D%d msg=%s", m.alternating_bit, m.buf); if (AltBit != m.alternating_bit) { printf(" It is dupliate or error!"); state = 7; } else state = 5; break; case 5: printf("Deliver data=%s\n", m.buf); state= 6; break; case 6: bcopy(&m.src, &to, sizeof(to)); bcopy(&m.dst, &m.src, sizeof(to)); bcopy(&to, &m.dst, sizeof(to)); m.msgtype = ACK; printf("Sending -A1"); if (sendto(sock, &m, sizeof(m), 0, (struct sockaddr_in *)&C2addr, sizeof(C2addr)) < 0) perror("send ACK message"); AltBit = !AltBit; //## state = 1; break; case 7: bcopy(&m.src, &to, sizeof(to)); bcopy(&m.dst, &m.src, sizeof(to)); bcopy(&to, &m.dst, sizeof(to)); m.msgtype = ACK; m.alternating_bit = 0; //## printf("Resending -A0"); if (sendto(sock, &m, sizeof(m), 0, (struct sockaddr_in *)&C2addr, sizeof(C2addr)) < 0) perror("send ACK message"); state = 4; break; case 8: bcopy(&m.src, &to, sizeof(to)); bcopy(&m.dst, &m.src, sizeof(to)); bcopy(&to, &m.dst, sizeof(to)); m.msgtype = ACK; m.alternating_bit = 1; //## printf("Resending -A1"); if (sendto(sock, &m, sizeof(m), 0, (struct sockaddr_in *)&C2addr, sizeof(C2addr)) < 0) perror("send ACK message"); state = 1; break; } // switch(state) } // while close(sock); }