Commits

N.Y. Lin committed 5cd41d8

Add some example programs for fork() and tcp C/S.

  • Participants
  • Parent commits 6cfee99

Comments (0)

Files changed (3)

File net/tcp_simple/fork.c

+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+
+#define EXIT_FALURE -1
+
+int main( int argc, char* argv[] )
+{
+    pid_t pid;
+    printf("begin of main\n");
+    pid = fork();
+    if (pid==0)
+    {
+        int j;
+        for (j=0; j<10; ++j)
+        {
+            printf("child: %d\n", j);
+            sleep(1);
+        }
+        _exit(0);
+    }
+    else if (pid>0)
+    {
+        int j;
+        for (j=0; j<10; ++j)
+        {
+            printf("parent: %d\n", j);
+            sleep(1);
+        }
+        _exit(0);
+    }
+    else
+    {
+        fprintf ( stderr, "can't fork, error %d\n", errno );
+        exit(EXIT_FALURE);
+    }
+        
+    return 0;
+}
+

File net/tcp_simple/tcp_client.c

+/*Listing 2. Example Client Code*/
+
+/*
+ * Listing 2:
+ * An example client for "Hello, World!" server
+ * Ivan Griffin (ivan.griffin@ul.ie)
+ */
+
+#include <stdio.h>                /* perror() */
+#include <stdlib.h>               /* atoi() */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <unistd.h>               /* read() */
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+int main(int argc, char *argv[])
+{
+    int clientSocket,
+        remotePort,
+        status = 0;
+    struct hostent *hostPtr = NULL;
+    struct sockaddr_in serverName = { 0 };
+    char buffer[256] = "";
+    char *remoteHost = NULL;
+
+    if (3 != argc)
+    {
+        fprintf(stderr, "Usage: %s <serverHost> <serverPort>\n",
+                argv[0]);
+        exit(1);
+    }
+
+    remoteHost = argv[1];
+    remotePort = atoi(argv[2]);
+
+    clientSocket = socket(PF_INET, SOCK_STREAM,
+                          IPPROTO_TCP);
+    if (-1 == clientSocket)
+    {
+        perror("socket()");
+        exit(1);
+    }
+
+    /*
+     * need to resolve the remote server name or
+     * IP address */
+    hostPtr = gethostbyname(remoteHost);
+    if (NULL == hostPtr)
+    {
+        hostPtr = gethostbyaddr(remoteHost,
+                                strlen(remoteHost), AF_INET);
+        if (NULL == hostPtr)
+        {
+            perror("Error resolving server address");
+            exit(1);
+        }
+    }
+
+    serverName.sin_family = AF_INET;
+    serverName.sin_port = htons(remotePort);
+    (void) memcpy(&serverName.sin_addr,
+                  hostPtr->h_addr,
+                  hostPtr->h_length);
+
+    status = connect(clientSocket,
+                     (struct sockaddr*) &serverName,
+                     sizeof(serverName));
+    if (-1 == status)
+    {
+        perror("connect()");
+        exit(1);
+    }
+
+    /*
+     * Client application specific code goes here
+     *
+     * e.g. receive messages from server, respond,
+     * etc. */
+    while (0 < (status = read(clientSocket,
+                              buffer, sizeof(buffer) - 1)))
+    {
+        printf("%d: %s", status, buffer);
+    }
+
+    if (-1 == status)
+    {
+        perror("read()");
+    }
+
+    close(clientSocket);
+
+    return 0;
+}

File net/tcp_simple/tcp_server.c

+/*Listing 1. Example Server Code*/
+
+/*
+ * Listing 1:
+ * Simple "Hello, World!" server
+ * Ivan Griffin (ivan.griffin@ul.ie)
+ */
+
+#include <stdio.h>   /* */
+#include <stdlib.h>  /* exit() */
+#include <string.h>  /* memset(), memcpy() */
+#include <sys/utsname.h>   /* uname() */
+#include <sys/types.h>
+#include <sys/socket.h>   /* socket(), bind(),
+                             listen(), accept() */
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <unistd.h>  /* fork(), write(), close() */
+
+/*
+ * prototypes
+ */
+int _GetHostName(char *buffer, int length);
+
+/*
+ * constants
+ */
+const char MESSAGE[] = "Hello, World!\n";
+const int BACK_LOG = 5;
+
+int main(int argc, char *argv[])
+{
+    int serverSocket = 0,
+        on = 0,
+        port = 0,
+        status = 0,
+        childPid = 0;
+    struct hostent *hostPtr = NULL;
+    char hostname[80] = "";
+    struct sockaddr_in serverName = { 0 };
+
+    if (2 != argc)
+    {
+        fprintf(stderr, "Usage: %s <port>\n",
+                argv[0]);
+        exit(1);
+    }
+    port = atoi(argv[1]);
+
+    serverSocket = socket(PF_INET, SOCK_STREAM,
+                          IPPROTO_TCP);
+    if (-1 == serverSocket)
+    {
+        perror("socket()");
+        exit(1);
+    }
+
+    /*
+     * turn off bind address checking, and allow
+     * port numbers to be reused - otherwise
+     * the TIME_WAIT phenomenon will prevent
+     * binding to these address.port combinations
+     * for (2 * MSL) seconds.
+     */
+
+    on = 1;
+
+    status = setsockopt(serverSocket, SOL_SOCKET,
+                        SO_REUSEADDR,
+                        (const char *) &on, sizeof(on));
+
+    if (-1 == status)
+    {
+        perror("setsockopt(...,SO_REUSEADDR,...)");
+    }
+
+    /*
+     * when connection is closed, there is a need
+     * to linger to ensure all data is
+     * transmitted, so turn this on also
+     */
+    {
+        struct linger linger = { 0 };
+
+        linger.l_onoff = 1;
+        linger.l_linger = 30;
+        status = setsockopt(serverSocket,
+                            SOL_SOCKET, SO_LINGER,
+                            (const char *) &linger,
+                            sizeof(linger));
+
+        if (-1 == status)
+        {
+            perror("setsockopt(...,SO_LINGER,...)");
+        }
+    }
+
+    /*
+     * find out who I am
+     */
+
+    status = _GetHostName(hostname,
+                          sizeof(hostname));
+    if (-1 == status)
+    {
+        perror("_GetHostName()");
+        exit(1);
+    }
+
+    hostPtr = gethostbyname(hostname);
+    if (NULL == hostPtr)
+    {
+        perror("gethostbyname()");
+        exit(1);
+    }
+
+    (void) memset(&serverName, 0,
+                  sizeof(serverName));
+    (void) memcpy(&serverName.sin_addr,
+                  hostPtr->h_addr,
+                  hostPtr->h_length);
+    printf ( "%s\n", hostname );
+    
+
+    /*
+     * to allow server be contactable on any of
+     * its IP addresses, uncomment the following
+     * line of code:
+     * serverName.sin_addr.s_addr=htonl(INADDR_ANY);
+     */
+
+    serverName.sin_family = AF_INET;
+    /* network-order */
+    serverName.sin_port = htons(port);
+
+    status = bind(serverSocket,
+                  (struct sockaddr *) &serverName,
+                  sizeof(serverName));
+    if (-1 == status)
+    {
+        perror("bind()");
+        exit(1);
+    }
+
+    status = listen(serverSocket, BACK_LOG);
+    if (-1 == status)
+    {
+        perror("listen()");
+        exit(1);
+    }
+
+    for (;;)
+    {
+        struct sockaddr_in clientName = { 0 };
+        int slaveSocket, clientLength =
+            sizeof(clientName);
+
+        (void) memset(&clientName, 0,
+                      sizeof(clientName));
+
+        slaveSocket = accept(serverSocket,
+                             (struct sockaddr *) &clientName,
+                             &clientLength);
+        if (-1 == slaveSocket)
+        {
+            perror("accept()");
+            exit(1);
+        }
+
+        childPid = fork();
+
+        switch (childPid)
+        {
+        case -1: /* ERROR */
+            perror("fork()");
+            exit(1);
+
+        case 0: /* child process */
+
+            close(serverSocket);
+
+            if (-1 == getpeername(slaveSocket,
+                                  (struct sockaddr *) &clientName,
+                                  &clientLength))
+            {
+                perror("getpeername()");
+            }
+            else
+            {
+                printf("Connection request from %s\n",
+                       inet_ntoa(clientName.sin_addr));
+            }
+
+            /*
+             * Server application specific code
+             * goes here, e.g. perform some
+             * action, respond to client etc.
+             */
+            write(slaveSocket, MESSAGE,
+                  strlen(MESSAGE));
+            close(slaveSocket);
+            exit(0);
+
+        default: /* parent process */
+            close(slaveSocket);
+            printf("slave socket closed\n");
+        }
+    }
+
+    return 0;
+}
+
+/*
+ * Local replacement of gethostname() to aid
+ * portability */
+int _GetHostName(char *buffer, int length)
+{
+    struct utsname sysname = { 0 };
+    int status = 0;
+
+    status = uname(&sysname);
+    if (-1 != status)
+    {
+        strncpy(buffer, sysname.nodename, length);
+    }
+
+    return (status);
+}