Using fork() on Windows boxes is difficult; as with the sockets code, it really requires cygwin.
Below is the Makefile that I am currently using for the programs for this class. You should make one like it, replacing the program names with your own program names for the four programs.
CFLAGS=-g TARGETS=client-rdv server-wiki-rdv server-udp-rdv client-udp-rdv \ client-udp-wiki all: ${TARGETS} server-wiki-rdv: server-wiki-rdv.c client-rdv: client-rdv.c server-udp-rdv: server-udp-rdv.c client-udp-rdv: client-udp-rdv.c client-udp-wiki: client-udp-wiki.c clean: rm ${TARGETS}
int get_stream(char *host, char *service) { int error, fd; struct addrinfo req, *ai, *ai2, hints; char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; memset((void *)&req, 0, sizeof(struct addrinfo)); memset((void *)&hints, 0, sizeof(struct addrinfo)); hints.ai_socktype = SOCK_STREAM; hints.ai_family |= PF_UNSPEC; // hints.ai_flags |= AI_NUMERICSERV; if (error = getaddrinfo(host, service, &hints, &ai)) { fprintf(stderr, "getaddrinfo(%s, %s, ...): %s(%d)", gai_strerror(error), error); return -1; } for (ai2 = ai; ai; ai = ai->ai_next) { if (error = getnameinfo(ai->ai_addr, ai->ai_addrlen, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV)) { fprintf(stderr, "getnameinfo(%p, %d, %p, %d, %p, %d, %d): %s(%d)\n", ai->ai_addr, ai->ai_addrlen, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV, gai_strerror(error), error); continue; } fprintf(stdout, "Trying %s port %s...\n", hbuf, sbuf); if ((fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol)) < 0) { fprintf(stderr, "socket(%d, %d, %d): ", ai->ai_family, ai->ai_socktype, ai->ai_protocol); perror("get_stream"); continue; } if (connect(fd, ai->ai_addr, ai->ai_addrlen) < 0) { fprintf(stderr, "connect(%d, %p, %d): \n", fd, ai->ai_addr, ai->ai_addrlen); perror("get_stream"); close(fd); continue; } freeaddrinfo(ai2); return fd; } freeaddrinfo(ai2); fprintf(stderr, "No connections result.\n"); return -1; }
// Server code in C // adapted from http://en.wikipedia.org/wiki/Berkeley_sockets #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include <netinet/in.h> #include <arpa/inet.h> #include <stdio.h> #include <stdlib.h> #include <strings.h> #include <unistd.h> #include <signal.h> #define MAXMSGSIZE 500 /* arbitrary, biggest we will use */ int main() { struct addrinfo hint; struct sockaddr_storage bindaddr_storage; struct sockaddr_in6 *bindaddr6 = (struct sockaddr_in6 *)&bindaddr_storage; struct sockaddr_in *bindaddr = (struct sockaddr_in *)&bindaddr_storage; struct addrinfo *result; struct sockaddr_storage mysockname; int mysocknamesize; struct sockaddr_storage incoming; int incomingsize; struct sockaddr_storage peer; int peersize; char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; int retval; int i32SocketFD = socket(PF_INET6, SOCK_DGRAM, 0); char msg[] = "Successful message from server to client!\n"; if(-1 == i32SocketFD) { perror("can not create socket"); exit(-1); } bzero(&bindaddr_storage, sizeof(bindaddr_storage)); bindaddr6->sin6_family = AF_INET6; bindaddr6->sin6_addr = in6addr_any; /* struct assignment */ bindaddr6->sin6_port = htons(12345); if(-1 == bind(i32SocketFD,(struct sockaddr*) bindaddr6, sizeof(struct addrinfo))) { printf("error bind failed"); perror("main"); exit(-1); } // Report on where we're waiting for a connection mysocknamesize = sizeof(mysockname); if (retval = getsockname(i32SocketFD, (struct sockaddr *)&mysockname, &mysocknamesize) != 0) { printf("getsockname retval: %d (%s)\n",retval, gai_strerror(retval)); } else { if (retval = getnameinfo((struct sockaddr *)&mysockname, mysocknamesize,hbuf,sizeof(hbuf),sbuf,sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV) != 0) { printf("retval: %d (%s)\n",retval, gai_strerror(retval)); } else printf("My sockname host=%s, serv=%s\n", hbuf, sbuf); } /* set up to ignore child signals */ // this is to prevent child processes from becoming "zombies" // XXX n.b.: not all Unixes behave the same way! This works on Linux. signal(SIGCHLD,SIG_IGN); for(; ;) { pid_t pid; char msgin[MAXMSGSIZE]; int recvd; incomingsize = sizeof(incoming); printf("waiting for packet...\n"); fflush(stdout); if ((recvd = recvfrom(i32SocketFD, (void *)msgin, MAXMSGSIZE, 0, (struct sockaddr *)&incoming, (socklen_t *)&incomingsize)) == -1) { printf("error recvfrom failed"); perror("main"); exit(-1); } printf("received msg: |%s|\n",msgin); // Find out who we're talking to if (retval = getnameinfo((struct sockaddr *)&incoming,incomingsize, hbuf,sizeof(hbuf),sbuf,sizeof(sbuf),NI_NUMERICHOST|NI_NUMERICSERV) != 0) { printf("getnameinfo failed, retval: %d (%s)\n",retval, gai_strerror(retval)); } else { printf("remote host=%s, serv=%s\n", hbuf, sbuf); } // perform any calculations necessary to create the result to send back... // then send it back. printf("Sending the message |%s|\n",msg); sendto(i32SocketFD, msg, sizeof(msg), 0, (struct sockaddr *)&incoming,incomingsize); } exit(0); }
// UDP Client code in C // adapted from http://en.wikipedia.org/wiki/Berkeley_sockets #include <stdio.h> #include <errno.h> #include <string.h> #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <unistd.h>//for close() for socket int main(int argc, char *argv[]) { int sock; struct sockaddr_in sa; int bytes_sent, buffer_length; char buffer[200]; sprintf(buffer, "Hello World!"); buffer_length = strlen(buffer) + 1; sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); if(-1 == sock)//if socket failed to initialize, exit { printf("Error Creating Socket"); return 0; } sa.sin_family = AF_INET; sa.sin_addr.s_addr = htonl(0x7F000001); sa.sin_port = htons(12345); bytes_sent = sendto(sock, buffer, buffer_length, 0,(struct sockaddr*) &sa, sizeof(struct sockaddr_in) ); if(bytes_sent < 0) printf("Error sending packet: %s\n", strerror(errno) ); close(sock);//close the socket return 0; }