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;
}