Sockets BSD/Windows

Exemples de code


Exemples

Les travaux de W.Richard Stevens datent de 1990. Je les ai mis à jour en mettant chaque application dans un seul fichier source, ce qui rend plus difficile la maintenance, mais facilite la compréhension de chaque application.

HTTP Client

/*
  Client HTTP qui se connecte à un serveur juste pour voir son en-tête.
  Auteur: Bertrand Massot

  Exemple de session:
   [Connection à 127.0.0.1] Socket fermé.
   HTTP/1.1 200 OK
   Date: Wed, 06 Dec 2006 04:53:46 GMT
   Server: Apache/1.3.33 (Debian GNU/Linux) PHP/4.3.10-16
   Last-Modified: Sat, 14 Oct 2006 10:00:44 GMT
   ETag: "afa82-148a-4530b54c"
   Accept-Ranges: bytes
   Content-Length: 5258
   Content-Type: text/html; charset=iso-8859-1
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>

int main(int argc, char *argv[])
{
  int sk = -1;
  struct sockaddr_in ServAddr;
  struct hostent *serveurEnt;
  unsigned long hostAddr;
  int i=1, n=0;
  char *serveur = "127.0.0.1";		// www.truc.com ou IP
  char req[255];	// Requête HTTP
  char buf[2048];	// Paquet reçu

  printf("[Connection à %s] ", serveur);
  bzero(&ServAddr,sizeof(ServAddr));
  hostAddr = inet_addr(serveur); // convertit IP en entier long

  if ( (long)hostAddr != (long)-1)
    bcopy(&hostAddr, &ServAddr.sin_addr, sizeof(hostAddr));
  else  // un nom a été donné, pas une IP
  {
    serveurEnt = gethostbyname(serveur);
    if (serveurEnt==NULL)
    {
     perror ("gethostbyname()");
     return -1;
    }
    bcopy(serveurEnt->h_addr,&ServAddr.sin_addr, serveurEnt->h_length);
  }
  ServAddr.sin_port = htons(80); // Port 80 pour HTTP
  ServAddr.sin_family = AF_INET;
  if ( (sk = socket(AF_INET,SOCK_STREAM,0)) < 0)
  {
   perror("socket()");
   return -1;
  }

  if (connect(sk,(struct sockaddr *)&ServAddr, sizeof(ServAddr)) < 0)
  {
   perror("connect()");
   return -1;
  }

  sprintf (req, "GET / HTTP/1.1\r\n"
                "Host:%s\r\n\r\n", serveur);

  if ( (i = send(sk, req, strlen(req), 0)) == -1)
  {
   perror ("send()");
   return -1;
  }
  if ((i = recv(sk, buf, sizeof(buf), 0)) == -1 )
  {
   perror ("recv()");
   return -1;
  }

  if (close(sk)==-1)
  {
   perror ("close()");
   return -1;
  }
  printf("Socket fermé.\n");

  for (n=0; n<i; n++) // isole le header du 1er paquet
  {
    if (buf[n]=='\r' && buf[n+1]=='\n'&& buf[n+2]=='\r'&& buf[n+3]=='\n')
    {
      buf[n]=0;
      printf("%s\n", buf);
      break;
    }
  }

  return 0;
}

HTTP Server

/*
  Serveur qui écoute sur le port 80.
  Auteur: Bertrand Massot

  Lancer en tant que root, puis lancer un navigateur et saisir
  l' adresse http://127.0.0.1
  Le serveur va alors:
	* afficher la requête du navigateur,
	* envoyer une réponse HTTP sommaire
	* puis fermer la connection et le programme serveur.

  La requête de Firefox:
  GET / HTTP/1.1
  Host: 127.0.0.1
  User-Agent: Mozilla/5.0 Firefox/1.5.0.8
  Accept: text/xml;q=0.5
  Accept-Language: fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3
  Accept-Encoding: gzip,deflate
  Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
  Keep-Alive: 300
  Connection: keep-alive
*/
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
  int skEcoute, skClient, clilen, nbytes;
  struct sockaddr_in cli_addr, serv_addr;
  char paquet[1024];

  if ((skEcoute = socket(AF_INET,SOCK_STREAM,0))<0)
  {
    perror("socket()");
    return -1;
  }

  bzero((char*) &serv_addr,sizeof(serv_addr));
  serv_addr.sin_family		= AF_INET;
  serv_addr.sin_addr.s_addr	= htonl(INADDR_ANY);
  serv_addr.sin_port		= htons(80);

  if (bind(skEcoute,(struct sockaddr *)&serv_addr, sizeof(serv_addr))<0)
  {
    perror("bind");
    return -1;
  }

  if (listen(skEcoute,5) == -1)
  {
    perror("listen()");
    return -1;
  }

  printf("Server started on port 80...\n\n");

  clilen = sizeof(cli_addr);
  if ((skClient = accept(skEcoute, (struct sockaddr *)&cli_addr, &clilen)) < 0)
  {
    perror("accept()");
    return -1;
  }

  if ((nbytes = recv(skClient,paquet,1024,0)) == -1)
  {
    perror("recv");
    return -1;
  }
  paquet[nbytes]=0;
  printf(paquet);

  // Envoie une réponse sommaire
  nbytes= sprintf(paquet, "HTTP/1.1 200 OK\n"
                          "Content-Length:29\n"
                          "Content-type:text/html\r\n"
                          "\r\n"
                          "&lt;H1&gt;Fin de la connection&lt;/H1&gt;");
  nbytes = send(skClient, paquet, nbytes, 0);

  close(skClient);
  close(skEcoute);

  return 0;
}

SERVER ECHO TCP INET (Fork)

Concurrent server using TCP protocol
/*
  Serveur d' echo TCP INET avec fork()
  Auteur: W.Richard Stevens, Bertrand Massot

 Ce serveur d'echo écoute en boucle infinie. Un client se connecte sur un fork().
 Quand le serveur reçoit un message, il le renvoie au client.
 Pour transformer ce serveur echo en chat, modifier str-echo.c
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

#define SERV_TCP_PORT   4404
#define MAXBUF 512

void Sortir(char *p)
{
  perror(p);
  exit(1);
}

void echo(int sk)
{
   int n;
   char buf[MAXBUF];

   for (;;)
   {
     n = recv(sk, buf, MAXBUF, 0);
     if (n == 0)
     {
       printf("Client left.\n");
       return;
     }
     else if (n < 0)
       Sortir("recv()");

     printf("> %s", buf);
     if (send(sk, buf, n, 0) != n)	// renvoie au client
       Sortir("send()");
   }
}


int main(int argc, char **argv)
{
  int sk, newsk, clilen, childpid;
  struct sockaddr_in cli_addr, serv_addr;

  if ( (sk = socket(AF_INET, SOCK_STREAM, 0)) == -1)
		perror("socket()");

  bzero((char *) &serv_addr, sizeof(serv_addr));
  serv_addr.sin_family		= AF_INET;
  serv_addr.sin_addr.s_addr	= htonl(INADDR_ANY);
  serv_addr.sin_port		= htons(SERV_TCP_PORT);

  if (bind(sk, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
		perror("bind()");
	
  listen(sk, 5);

  printf("Serveur %s en écoute sur le port %d ...\n", argv[0], SERV_TCP_PORT);
  for (;;)
  {
    clilen = sizeof(cli_addr);
    newsk = accept(sk, (struct sockaddr *) &cli_addr, &clilen);
    if (newsk < 0)
	Sortir("accept()");
    if ( (childpid = fork()) < 0)
	perror("fork()");
    else if (childpid == 0)	/* processus fils */
    {
      printf("NEW CLIENT\n");
      close(sk);		/* ferme socket d'écoute */
      echo(newsk);		/* traite le client */
    }
    close(newsk);		/* processus parent */
  }

  return 0;
}

CLIENT ECHO TCP INET

/*
  Client echo TCP INET
  Auteur: W.Richard Stevens, Bertrand Massot

  Tout ce qui est saisi est reçu en écho.
  Si le serveur tombe, le client stoppe.
  Connecter plusieurs clients.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

#define SERV_TCP_PORT   4404
#define SERV_HOST_ADDR	"127.0.0.1"
#define MAXBUF 512

void Sortir(char *p)
{
  perror(p);
  exit(1);
}

void str_cli(FILE *fp, int sk)
{
  int n;
  char sendline[MAXBUF], recvline[MAXBUF + 1];

  while (fgets(sendline, MAXBUF, fp) != NULL)
  {
    n = strlen(sendline);
    if (strcmp(sendline,"exit")==0) return;

    if (send(sk, sendline, n,0) != n)
      Sortir("send()");

    n = recv(sk, recvline, MAXBUF,0); 
    if (n < 0) Sortir("recv()");
    recvline[n] = 0;
    printf(">> %s", recvline);
  }

  if (ferror(fp)) Sortir("Error reading file");
}


int main(int argc, char **argv)
{
  int sk;
  struct sockaddr_in serv_addr;

  bzero((char *) &serv_addr, sizeof(serv_addr));
  serv_addr.sin_family		= AF_INET;
  serv_addr.sin_addr.s_addr	= inet_addr(SERV_HOST_ADDR);
  serv_addr.sin_port		= htons(SERV_TCP_PORT);

  if ( (sk = socket(AF_INET, SOCK_STREAM, 0)) < 0)
		Sortir("socket()");

  printf("Connecting to %s:%d ... ", SERV_HOST_ADDR, SERV_TCP_PORT);
  if (connect(sk, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
		Sortir("connect()");
  printf("Connected.\n");

  str_cli(stdin, sk);

  close(sk);
  return 0;
}

SERVER TCP UNIX (fork)

Example of server using UNIX domain stream protocol Le serveur n' écoute pas sur un port, mais un descripteur de fichier.
/*
 * Reproduced from Unix Network Programming
		W.Richard Stevens
		Prentice Hall Software Series 1990
		Last revision Bertrand Massot 2006

 * Example of server using UNIX domain stream protocol
*/

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>

#define	UNIXSTR_PATH	"/tmp/s.unixstr"
#define UNIXDG_PATH	"/tmp/s.unixdg"
#define UNIXDG_TMP	"/tmp/dg.XXXXXX"
#define MAXLINE 512

/* Error handling */
void err_dump(char *p)
{
  perror(p);
  exit(1);
}

/* Read a line from a descriptor. Read the line one byte at a time,
 * looking for the newline. We store the newline in the buffer,
 * then follow it with a null (the same as fgets(3)).
 * We return the number of characters up to, but not including,
 * the null (the same as strlen(3)). */
int readline(int fd, char *ptr, int maxlen)
{
  int n, rc;
  char c;

  for (n = 1; n < maxlen; n++)
  {
    rc = recv(fd,&c,1,0);
    if (rc == 1)
    {
      *ptr++ = c;
      if (c == '\n') break;
    }
    else if (rc == 0)
    {
      if (n == 1) return(0);	/* EOF, no data read */
      else break;		/* EOF, some data was read */
    }
    else return -1;	/* error */
  }
  *ptr = 0;

  return n;
}

/* Write "n" bytes to a descriptor.
 * Use in place of write() when fd is a stream socket. */
int writen(int fd, char *ptr, int nbytes)
{
  int nleft, nwritten;

  nleft = nbytes;
  while (nleft > 0)
  {
    nwritten = send (fd, ptr, nbytes, 0);
    if (nwritten <= 0) return nwritten;

    nleft -= nwritten;
    ptr += nwritten;
  }

  return nbytes - nleft;
}

/* Read a stream socket one line at a time,
 * and write each line back to the sender.
 * Return when the connection is terminated. */
void str_echo(int sockfd)
{
   int n;
   char line[MAXLINE];

   for (;;)
   {
     n = readline(sockfd, line, MAXLINE);
     if (n == 0)
     {
       printf("Client left.\n");
       return;	/* connection terminated */
     }
     else if (n < 0)
       err_dump("str_echo: readline error");

     printf("[%d]> %s", sockfd, line);	/* write locally */
     if (writen(sockfd, line, n) != n)		/* and send back */
       err_dump("str_echo: writen error");
   }
}

/* Entry Point */
int main(int argc, char **argv)
{
  int  sockfd, newsockfd, clilen, childpid, servlen;
  struct sockaddr_un cli_addr, serv_addr;

  /* Open a socket (a UNIX domain stream socket). */
  if ( (sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
		err_dump("server: can't open stream socket");
	
  /* Bind our local address so that the client can send to us. */
  bzero((char *) &serv_addr, sizeof(serv_addr));
  serv_addr.sun_family = AF_UNIX;
  strcpy(serv_addr.sun_path, UNIXSTR_PATH);
  servlen = strlen(serv_addr.sun_path) + sizeof(serv_addr.sun_family);

  if (bind(sockfd, (struct sockaddr *) &serv_addr, servlen) < 0)
		err_dump("server: can't bind local address");

  listen(sockfd, 5);
  printf("Server listenning ...\n");
  for (;;)
  {
    /* Wait for a connection from a client process.
     * This is an example of a concurrent server. */
    clilen = sizeof(cli_addr);
    newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
    if (newsockfd < 0)
      err_dump("server: accept error");
		
    if ((childpid = fork()) < 0)
      err_dump("server: fork error");

    else if (childpid == 0)	/* child process */
    {
      close(sockfd);		/* close original socket */
      str_echo(newsockfd);	/* process the request */
      exit (0);
    }
    close(newsockfd);		/* parent process */
  }

  return 0;
}

CLIENT TCP UNIX

Tout ce qui est saisi est reçu en écho. Si le serveur tombe, le client stoppe.
/* 
 * Example of client using UNIX domain stream protocol
 * Reproduced from Unix Network Programming
		W.Richard Stevens
		Prentice Hall Software Series 1990
		Last revision Bertrand Massot 2006
*/

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>

#define	UNIXSTR_PATH	"/tmp/s.unixstr"
#define UNIXDG_PATH	"/tmp/s.unixdg"
#define UNIXDG_TMP	"/tmp/dg.XXXXXX"
#define MAXLINE 512

/* Error handling */
void err_dump(char *p)
{
  perror(p);
  exit(1);
}

/* Read a line from a descriptor. Read the line one byte at a time,
 * looking for the newline. We store the newline in the buffer,
 * then follow it with a null (the same as fgets(3)).
 * We return the number of characters up to, but not including,
 * the null (the same as strlen(3)). */
int readline(int fd, char *ptr, int maxlen)
{
  int n, rc;
  char c;

  for (n = 1; n < maxlen; n++)
  {
    rc = recv(fd,&c,1,0);
    if (rc == 1)
    {
      *ptr++ = c;
      if (c == '\n') break;
    }
    else if (rc == 0)
    {
      if (n == 1) return(0);	/* EOF, no data read */
      else break;		/* EOF, some data was read */
    }
    else return -1;	/* error */
  }
  *ptr = 0;

  return n;
}

/* Write "n" bytes to a descriptor.
 * Use in place of write() when fd is a stream socket. */
int writen(int fd, char *ptr, int nbytes)
{
  int nleft, nwritten;

  nleft = nbytes;
  while (nleft > 0)
  {
    nwritten = send (fd, ptr, nbytes, 0);
    if (nwritten <= 0) return nwritten;

    nleft -= nwritten;
    ptr += nwritten;
  }

  return nbytes - nleft;
}

/* Read the contents of the FILE *fp, write each line to the 
 * stream socket (to the server process), then read a line back from
 * the socket and write it to the standard output.
 * Return to caller when an EOF is encountered on the input file. */
void str_cli(FILE *fp, int sockfd)
{
  int n;
  char sendline[MAXLINE], recvline[MAXLINE + 1];

  while (fgets(sendline, MAXLINE, fp) != NULL)
  {
    n = strlen(sendline);
    if (strcmp(sendline,"exit")==0) return;

    if (writen(sockfd, sendline, n) != n)
      err_dump("str_cli: writen error on socket");

    /* Now read a line from the socket and write it to
     * our standard output. */
    n = readline(sockfd, recvline, MAXLINE); 
    if (n < 0) err_dump("str_cli: readline error");
    recvline[n] = 0;		/* null terminate */
    //fputs(recvline, stdout);
    printf(">> %s", recvline);
  }

  if (ferror(fp)) err_dump("str_cli: error reading file");
}

/* Entry Point */
int main(int argc, char **argv)
{
  int sockfd, servlen;
  struct sockaddr_un serv_addr;

  /* Fill in the structure "serv_addr" with the address of the
   * server that we want to send to. */
  bzero((char *) &serv_addr, sizeof(serv_addr));
  serv_addr.sun_family = AF_UNIX;
  strcpy(serv_addr.sun_path, UNIXSTR_PATH);
  servlen = strlen(serv_addr.sun_path) + sizeof(serv_addr.sun_family);

  /*  Open a socket (an UNIX domain stream socket) */
  if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
    err_dump("client: can't open stream socket");

  /* Connect to the server */
  printf("Connecting to server\n");
  if (connect(sockfd, (struct sockaddr *) &serv_addr, servlen) < 0)
		err_dump("client: can't connect to server");
  printf("Connected\n");

  str_cli(stdin, sockfd);	/* do it all */

  close(sockfd);

  return 0;
}

SERVER TCP INET (select)

Concurrent server using Synchronous multiplexing
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>

#ifdef WIN32
 #include <winsock2.h>
 #define bzero(b,len) memset(b, 0, len)
#else
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #define closesocket(s) close(s)
 #define SOCKET int
#endif

#define PORT 4404
#define MAX_USERS 32

void log_(char *msg)
{
  struct tm *p;
  time_t ti;

  ti=time(NULL);
  p = localtime(&ti);
  printf("%02d:%02d:%02d %s\n",p->tm_hour,p->tm_min,p->tm_sec, msg);
}


void Sortir(char *msg)
{
  perror(msg);
  #ifdef WIN32
    WSACleanup();
  #endif
  exit(1);
}


int main(void)
{
  fd_set master;                 // master file descriptor list
  fd_set read_fds;               // temp file descriptor list for select()
  struct sockaddr_in myaddr;     // server address
  struct sockaddr_in remoteaddr; // client address
  FD_ZERO(&master);              // clear the master and temp sets
  FD_ZERO(&read_fds);
  unsigned short MAXDESCRIPTOR;	// maximum file descriptor number
  char buf[288];		// strIN. 288 max, voir II du protocole
  int nbytes,i,j,yes=1;		// for setsockopt() SO_REUSEADDR, below
  char c[256];
  SOCKET skEcoute, sk = -1;

  #ifdef WIN32
   int addrlen;
   WSADATA wsa;

   if (WSAStartup(0x202, &wsa) != 0)
   {
    perror("WSAStartup");
    return 1;
   }

   if ((skEcoute = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
   {
    log_(WSAGetLastError());
    Sortir("socket()");
   }

   if (setsockopt(skEcoute,SOL_SOCKET,SO_REUSEADDR,(char *)(&yes),sizeof(int))
		== SOCKET_ERROR) Sortir("setsockopt()");
  #else
   socklen_t addrlen;
   if ((skEcoute = socket(AF_INET, SOCK_STREAM, 0)) == -1)
     Sortir("socket()");
   if (setsockopt(skEcoute, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
     Sortir("setsockopt()");
  #endif

  bzero((char *) &myaddr, sizeof(myaddr));
  myaddr.sin_family      = AF_INET;
  myaddr.sin_addr.s_addr = INADDR_ANY;
  myaddr.sin_port        = htons(PORT);

  if (bind(skEcoute, (struct sockaddr *)&myaddr, sizeof(myaddr)) == -1)
    Sortir("bind()");
  if (listen(skEcoute, 10) == -1) Sortir("listen()");

  // Ajoute skEcoute au master set
  FD_SET(skEcoute, &master);
  // Garde une trace du plus grand descripteur: c'est moi pour l' instant
  MAXDESCRIPTOR = skEcoute;

  log_("Server started");
  while(1)
  {
    read_fds = master; // copie le master
    if (select(MAXDESCRIPTOR+1, &read_fds, NULL, NULL, NULL) == -1)
     Sortir("select()");

    for(i=0; i<=MAXDESCRIPTOR; i++) // Parcourt les connections
    {
      if (FD_ISSET(i, &read_fds)) // des données sont prêtes?
      {
        if (i == skEcoute) // c'est mon socket: Nouvelle connection
        {
          addrlen = sizeof(remoteaddr);
          if ((sk = accept(skEcoute, (struct sockaddr *)&remoteaddr,&addrlen)) == -1)
             perror("accept");
          else
          {
            #ifdef WIN32
            if (master.fd_count >= MAX_USERS)
            #else
            if (sk >= MAX_USERS)
            #endif
              log_("# Connection refusee: MAX_USERS est atteint");
            else
            {
              MAXDESCRIPTOR++;
              FD_SET(sk, &master); // add to master set
              if (sk > MAXDESCRIPTOR) MAXDESCRIPTOR = sk; // keep track of the maximum
              sprintf (c,"< New client: %s (sock %i)",
		inet_ntoa(remoteaddr.sin_addr), sk);
              log_(c);
            }
          }
        }
        else // Des données arrivent
        {
          memset(buf, 0, sizeof(buf)); 
          if ((nbytes = recv(i, buf, sizeof(buf), 0)) <= 0)
          {
            closesocket(i); // bye!
            FD_CLR(i, &master); // retire du master
            sprintf (c,"- client left (sock %d)", i);
            log_(c);
          }
          else // lire données
          {
            buf[nbytes]=0;
            log_(buf);
            // redispatche à tous
            for(j = 3; j <= MAXDESCRIPTOR; j++) { 
               if (FD_ISSET(j, &master)) { 
                 if (j != skEcoute)
                    if (send(j, buf, nbytes, 0) == -1) perror("send");
                 }
               }
            }
          } //client a quitté ou envoyé data
        } // if skEcoute or client
      } //boucle sockets
   } // boucle infinie

   return 0;
}

Multi-thread

Un header commun est partagé par le client et le serveur. Le serveur utilise les threads et produit les callbacks.
// sock_lib.h

/*standard C input-output header*/
#include<stdio.h>
/*POSIX Threads Header*/
#include<pthread.h>
/*required for socket specific functions and constants*/
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
/*required by strerror*/
#include<string.h>
/*needed by _exit*/
#include<unistd.h>
/*exit status constants*/
#define         SUCCESS         0
#define         SOCKET_ERR      1
#define         BIND_ERR        2
#define         LISTEN_ERR      3
#define         ACCEPT_ERR      4
#define         TH_CREATE_ERR   5
#define         RECV_ERR        6
#define         SEND_ERR        7       
#define         CLOSE_SOCK_ERR  8
#define         GETHOSTN_ERR    9
#define         CONNECT_ERR     10
/*other constants*/
#define        BUF_SIZE    512
#define        PORT        8000

void print_error( const int exit_status, const int err )
{
    char* msg = strerror( err );
    printf( "%s", msg );

    _exit( exit_status );
}
// server.c
#include<errno.h>
#skinclude <ctype.h>
#skinclude "sock_lib.h"

/*listens for a connection on the designated port*/
void wait_client( const int );
/*spawns a separate thread to service each client*/
void start_pthread( int );
/*call-back function used to communicate with the client*/
void* onData_Arrival( void* );


int main( int argc, char* argv[] )
{
    int sk;

    if( ( sk = socket( AF_INET, SOCK_STREAM, 0 ) ) == -1)
        print_error( SOCKET_ERR, errno );

    /*go listen for connection(s)*/
    wait_client( sk );

    /*will never happen*/
    return SUCCESS;
}

void wait_client( const int sk )
{
    struct sockaddr_in sAddr;

    bzero(&sAddr, sizeof(sAddr));
    sAddr.sin_family = AF_INET;		/*use IPv4 Internet protocols*/
    sAddr.sin_port = htons(PORT);
    sAddr.sin_addr.s_addr = INADDR_ANY; /*allow connections from any address*/

    /*associate socket to specified port in sAddr*/
    if( bind( sk, (struct sockaddr*)&sAddr, sizeof(sAddr) ) == -1 )
        print_error( BIND_ERR, errno );    

    /*listen making a queue of 20 client request if necessary*/
    if( ( listen( sk, 20 ) ) == -1 )
        print_error( LISTEN_ERR, errno );

    printf( "Listening...\n" );
    start_pthread( sk );
}



void start_pthread( int sk )
{
    struct sockaddr_in th_sock_addr;
    int sk;
    int th_addr_size;
    pthread_t client_th;    
    
    while(1)
    {
      /*accept an incoming connection*/
      if( ( sk = accept( sk, (struct sockaddr*)&th_sock_addr,
	&th_addr_size ) ) == -1 )
         print_error( ACCEPT_ERR, errno );
        
      /*spawn separate thread to service client*/
      if( pthread_create( &client_th, NULL, onData_Arrival, &sk ) )
      //if (pthread_create(&thread_id, NULL,(void *(*)())addition, NULL) == -1)
            print_error( TH_CREATE_ERR, errno );
        
      printf( "Receiving message...\n" );
        
      /*wait for thread to finish*/
      pthread_join( client_th, NULL );
    }
}

void* onData_Arrival( void* arg_list)
{
    /*convert to appropriate type the thread arguments*/
    int* sk = ( int* )arg_list;
    
    char buffer[BUF_SIZE];
    int buffer_len, i;
    
    /*receive client data*/
    if( recv( *sk, buffer, BUF_SIZE, 0 ) == -1 )
        print_error( RECV_ERR, errno );
    
    printf( "Message received from client side: %s\n", buffer );
    
    /*data processing goes here!*/
    buffer_len = strlen(buffer);
    for ( i=0; i < buffer_len; i++) 
        buffer[i] = toupper(buffer[i]);
    
    /*send back the results to client*/
    if( send( *sk, buffer, buffer_len, 0 ) == -1 )
        print_error( SEND_ERR, errno );
    
    printf( "Transmition finished!\n" );
    
    /*close socket*/
    if( close (*sk) == -1 )
        print_error( CLOSE_SOCK_ERR, errno );
}
// client.c
// http://code.box.sk/newsread.php?newsid=1014
/*hopefully never used*/
#include<errno.h>

/*required by gethostbyname*/
#include<netdb.h>

/*local common server-client constants and functions*/
#include"sock_lib.h"

int main( int argc, char* argv[] )
{
    int sk;
    /*"$man 7 ip" for the struct definition*/
    struct sockaddr_in sAddr;
    /*"$man gethostbyname" for the function and struct definition*/
    struct hostent *server_hostname;
    /*set address to connect to, to the local loopback*/
    char buffer[BUF_SIZE] = "127.0.0.1";

    /*getting hostname for the ip address stored in buffer*/
    if( ( server_hostname = gethostbyname( buffer ) ) == NULL )
        // gethostbyname uses a special h_errno for error number
        print_error( GETHOSTN_ERR, h_errno );

    /*clear the struct bytes*/
    bzero( &sAddr, sizeof( sAddr ) );
    
    sAddr.sin_family		= AF_INET;
    sAddr.sin_addr.s_addr	= ((struct in_addr*)
	(server_hostname->h_addr_list[0]))->s_addr;
    sAddr.sin_por		= htons( PORT );
    
    /*get sk specifyng using the stream type socket*/
    if( ( sk = socket( AF_INET, SOCK_STREAM, 0 ) ) == -1 )
        print_error( SOCKET_ERR, errno );
    
    /*connect to server*/
    if( connect( sk, (void*)&sAddr, sizeof(sAddr) ) == -1 )
        print_error( CONNECT_ERR, errno );
    
    /*send input data to server*/
    if( send( sk, "test data", strlen( "test data" ) + 1, 0 ) == -1 )
        print_error( SEND_ERR, errno );
    
    /*receive response data*/
    if( recv(sk, buffer, BUF_SIZE, 0) == -1 )
        print_error( RECV_ERR, errno );
    
    /*close socket*/
    if( close( sk ) == -1 )
        print_error( CLOSE_SOCK_ERR, errno );
    
    /*output data*/
    printf( "Returned buffer is: %s\n", buffer );
}

SERVER UDP INET

Example of server using UNIX domain stream protocol Le serveur n' écoute pas sur un port, mais un descripteur de fichier.
/*
 * Reproduced from Unix Network Programming
		W.Richard Stevens
		Prentice Hall Software Series 1990
		Last revision Bertrand Massot 2006

 * Example of server using UDP protocol
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

#define	SERV_UDP_PORT	7000
#define	MAXMESG 2048

/* Handle error and exit */
void err_dump(char *p)
{
  perror(p);
  exit(1);
}

/* Read a datagram from a conncetionless socket and write it back to
 * the sender.
 * We never return, as we never know when a datagram client is done. */
int dg_echo(int sockfd, struct sockaddr *pcli_addr, int maxclilen)
{
  int n, clilen;
  char mesg[MAXMESG];

  for (;;)
  {
    clilen = maxclilen;
    n = recvfrom(sockfd, mesg, MAXMESG, 0, pcli_addr, &clilen);
    if (n < 0)
      err_dump("dg_echo: recvfrom error");

    if (sendto(sockfd, mesg, n, 0, pcli_addr, clilen) != n)
      err_dump("dg_echo: sendto error");
  }
}

/* Entry Point */
int main(int argc, char **argv)
{
  int sockfd;
  struct sockaddr_in serv_addr, cli_addr;

  /*  Open a UDP socket (an Internet datagram socket) */
	
  if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
	err_dump("server: can't open datagram socket");

  /* Bind our local address so that the client can send to us */
	
  bzero((char *) &serv_addr, sizeof(serv_addr));
  serv_addr.sin_family		= AF_INET;
  serv_addr.sin_addr.s_addr	= htonl(INADDR_ANY);
  serv_addr.sin_port		= htons(SERV_UDP_PORT);

  if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
		err_dump("server: can't bind local address");

  dg_echo(sockfd, (struct sockaddr *) &cli_addr, sizeof(cli_addr));

  /* NOTREACHED */
  return 0;
}

CLIENT UDP INET

/*
 * Example of client using UDP protocol
 * Reproduced from Unix Network Programming
		W.Richard Stevens
		Prentice Hall Software Series 1990
		Last revision Bertrand Massot 2006
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

#define	SERV_UDP_PORT	7000
#define SERV_HOST_ADDR	"127.0.0.1"	/* host addr for server */
#define	MAXLINE 512

/* Handle error and exit */
void err_dump(char *p)
{
  perror(p);
  exit(1);
}

/* Read the contents of the FILE *fp, write each line to the
 * datagram socket, then read a line back from the datagram
 * socket and write it to the standard output.
 * Return to caller when an EOF is encountered on the input file. */
void dg_cli(FILE *fp, int sockfd, struct sockaddr *pserv_addr, int servlen)
{
  int n, fromlen;
  struct sockaddr_in from;
  char sendline[MAXLINE], recvline[MAXLINE +1];

  while (fgets(sendline, MAXLINE, fp) != NULL)
  {
    n = strlen(sendline);
    if (sendto(sockfd, sendline, n, 0, pserv_addr, servlen) != n)
	err_dump("dg_cli: sendto error on socket");
    /*  Now read a message from the socket and write it to  our standard output. */
    fromlen = sizeof(from);
    n = recvfrom(sockfd, recvline, MAXLINE,0, (struct sockaddr *)&from , &fromlen);
    if (n < 0)
	err_dump("dg_cli: recvfrom error");
    recvline[n] = 0;	/* null terminate */
    fputs(recvline, stdout);
   }
   if (ferror(fp))
	err_dump("dg_cli: error reading file");
}

/* Entry Point */
int main(int argc, char **argv)
{
  int sockfd;
  struct sockaddr_in cli_addr, serv_addr;

  /* Fill in the structure "serv_addr" with the address of the
   * server that we want to send to. */	
  bzero((char *) &serv_addr, sizeof(serv_addr));
  serv_addr.sin_family		= AF_INET;
  serv_addr.sin_addr.s_addr	= inet_addr(SERV_HOST_ADDR);
  serv_addr.sin_port		= htons(SERV_UDP_PORT);

  /* Open a UDP socket (an Internet datagram socket). */
  if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
	err_dump("client: can't open datagram socket");

  /* Bind any local address for us */
  bzero((char *) &cli_addr, sizeof(cli_addr));	/* zero out */
  cli_addr.sin_family		= AF_INET;
  cli_addr.sin_addr.s_addr	= htonl(INADDR_ANY);
  cli_addr.sin_port		= htons(0);
  if (bind(sockfd, (struct sockaddr *) &cli_addr, sizeof(cli_addr)) < 0)
	err_dump("client:can't bind local address");

  dg_cli(stdin, sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
  close(sockfd);

  return 0;
}

SERVER UDP INET (Transfert de Fichier)

//include <winsock.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>

#define PORT 8000

int main()
{
  //WSADATA ws;
  //WSAStartup(0x0101,&ws);
  //SOCKET sk;
  struct sockaddr_in peer;
  char buf[1024];
  int sk, peerlen, i=0, paquets=0; double total=0;
  unsigned short transfer = 0;
  FILE *pF =NULL;
  char *fic=NULL;

  peer.sin_family = AF_INET;
  peer.sin_port = htons(PORT);
  peer.sin_addr.s_addr = htonl(INADDR_ANY);
  sk = socket(AF_INET, SOCK_DGRAM, 0);
  bind(sk,(struct sockaddr *)&peer,sizeof(peer));
  peerlen = sizeof(peer);

  while(1)
  {
    i = recvfrom(sk, buf, sizeof(buf), 0, (struct sockaddr*)&peer, &peerlen);
    if (i!=-1)
    {
     buf[i]='\0';
     if (buf[0]=='F' && buf[1]=='I' && buf[2]=='L' && buf[3]=='E' && buf[4]==':')
     {
      fic = malloc(i-4); strncpy(fic, buf+5, i-5);
      printf("Réception de %s ... ", fic);
      //pF = fopen(fic, "w");
      pF = fopen("img2.png", "w");
      paquets = total = 0;
      transfer=1;
     }
     else if (buf[0]=='E' && buf[1]=='N' && buf[2]=='D')
     {
      printf("%.0f octets reçus en %d paquets.\n", total, paquets);
      fclose(pF);
      transfer=0;
      free(fic); fic=NULL;
     }
     else if (transfer)
     {
      //printf("Réception paquet %d: %d octets\n", paquets, i);
      fwrite (buf, 1, i , pF);
      total += i;
      paquets++;
     }
    }
  }

  return 0;
}

CLIENT UDP INET (Transfert de Fichier)

// ./envoi IP port nom_fichier
//include <winsock.h>
#include <unistd.h>	// pour close
#include <arpa/inet.h>  // pour sockaddr_in
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

void envoyer_image(char *fichier);

int main(int argc, char **argv)
{
  //WSADATA ws;
  //WSAStartup(0x0101,&ws);
  //SOCKET sk;
  int sk;
  struct sockaddr_in peer;

  FILE *pF =NULL;
  char buf[1024];
  unsigned long taille=0;
  int i=1, paq=0, l=0;
  char *fic=NULL;

  if (!argv[1])
  {
    printf("usage: ./%s FILEPATH\n", argv[0]);
    return 1;
  }

  // se connecte
  peer.sin_family = AF_INET;
  peer.sin_port = htons(8000);
  peer.sin_addr.s_addr = inet_addr("127.0.0.1");
  sk = socket(AF_INET, SOCK_DGRAM, 0);

  // Ouvre fichier et envoie
  if (!(pF = fopen(argv[1], "rb")))
     { printf("%s : Fichier introuvable\n", argv[1]); exit(1); }
  fseek(pF, 0, SEEK_END);
  taille = ftell(pF);
  printf("Envoi de %s (%ld octets) ... ", argv[1], taille);
  l = strlen(argv[1]);
  fic = malloc(l+6);
  sprintf(fic,"FILE:%s", argv[1]);
  sendto(sk, fic, l+5, 0, (struct sockaddr *)&peer, sizeof(peer));
  rewind(pF);

  while(i)
  {
    i = fread (buf, 1, 1024, pF);
    if (i)
    {
      buf[i]='\0';
      sendto(sk, buf, i, 0, (struct sockaddr *)&peer, sizeof(peer));
      paq++;
      //printf("paquet %d : %d octets.\n", paq, i);
    }
  }
  fclose(pF);
  printf("%d paquets envoyés.\n", paq);
  sendto(sk, "END", 3, 0, (struct sockaddr *)&peer, sizeof(peer));

  close(sk);
  return 0;
}

SERVER UDP UNIX

/*
 * Reproduced from Unix Network Programming
		W.Richard Stevens
		Prentice Hall Software Series 1990
		Last revision Bertrand Massot 2006

 * Example of server using UNIX domain datagram protocol.
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/un.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>

#define	UNIXSTR_PATH	"/tmp/s.unixstr"
#define UNIXDG_PATH	"/tmp/s.unixdg"
#define UNIXDG_TMP	"/tmp/dg.XXXXXX"
#define	MAXMESG 2048

/* Handle error and exit */
void err_dump(char *p)
{
  perror(p);
  exit(1);
}

/* Read a datagram from a conncetionless socket and write it back to
 * the sender.
 * We never return, as we never know when a datagram client is done. */
void dg_echo(int sockfd, struct sockaddr *pcli_addr, int maxclilen)
{
  int n, clilen;
  char mesg[MAXMESG];

  for (;;)
  {
    clilen = maxclilen;
    n = recvfrom(sockfd, mesg, MAXMESG, 0, pcli_addr, &clilen);
    if (n < 0)
	err_dump("dg_echo: recvfrom error");

    if (sendto(sockfd, mesg, n, 0, pcli_addr, clilen) != n)
	err_dump("dg_echo: sendto error");
  }
}

/* Entry Point */
int main(int argc, char **argv)
{
  int sockfd, servlen;
  struct sockaddr_un serv_addr, cli_addr;

  /* Open a socket (a UNIX domain datagram socket). */

  if ( (sockfd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0)
	err_dump("server: can't open datagram socket");
  printf("sockfd = %d\n",sockfd);

  /* Bind our local address so that the client can send to us. */
  unlink(UNIXDG_PATH);	/* in case it was left from last time */
  bzero((char *) &serv_addr, sizeof(serv_addr));
  serv_addr.sun_family = AF_UNIX;
  strcpy(serv_addr.sun_path, UNIXDG_PATH);
  servlen = sizeof(serv_addr.sun_family) + strlen(serv_addr.sun_path);

  if (bind(sockfd, (struct sockaddr *) &serv_addr, servlen) < 0)
	err_dump("server: can't bind local address");
	
  dg_echo(sockfd, (struct sockaddr *) &cli_addr, sizeof(cli_addr));

  /* NOTREACHED */
  return 0;
}

CLIENT UDP UNIX

/*
 * Example of client using UNIX domain datagram protocol.
 * Reproduced from Unix Network Programming
		W.Richard Stevens
		Prentice Hall Software Series 1990
 */

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>

#define	UNIXSTR_PATH	"/tmp/s.unixstr"
#define UNIXDG_PATH	"/tmp/s.unixdg"
#define UNIXDG_TMP	"/tmp/dg.XXXXXX"
#define MAXLINE 1024

/* Handle error and exit */
void err_dump(char *p)
{
  perror(p);
  exit(1);
}

/* Read the contents of the FILE *fp, write each line to the
 * datagram socket, then read a line back from the datagram
 * socket and write it to the standard output.
 * Return to caller when an EOF is encountered on the input file. */
void dg_cli(FILE *fp, int sockfd, struct sockaddr *pserv_addr, int servlen)
{
  int n, fromlen;
  struct sockaddr_un from;
  char sendline[MAXLINE], recvline[MAXLINE +1];

  while (fgets(sendline, MAXLINE, fp) != NULL)
  {
    n = strlen(sendline);
    if (sendto(sockfd, sendline, n, 0, pserv_addr, servlen) != n)
	err_dump("dg_cli: sendto error on socket");
    /*  Now read a message from the socket and write it to  our standard output. */
    fromlen = sizeof(from);
    n = recvfrom(sockfd, recvline, MAXLINE,0, (struct sockaddr *)&from , &fromlen);
    if (n < 0)
	err_dump("dg_cli: recvfrom error");
    recvline[n] = 0;	/* null terminate */
    fputs(recvline, stdout);
   }
   if (ferror(fp))
	err_dump("dg_cli: error reading file");
}

/* Entry Point */
int main(int argc, char **argv)
{
  int sockfd, clilen, servlen;
  char *mktemp();
  struct sockaddr_un cli_addr, serv_addr;

  /* Fill in the structure "serv_addr" with the address of the
   * server that we want to send to. */
  bzero((char *) &serv_addr, sizeof(serv_addr));
  serv_addr.sun_family = AF_UNIX;
  strcpy(serv_addr.sun_path, UNIXDG_PATH);
  servlen = sizeof(serv_addr.sun_family) + strlen(serv_addr.sun_path);

  /* Open a socket (a UNIX domain datagram socket). */
  if ( (sockfd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0)
	err_dump("client: can't open datagram socket");

  /* Bind a local address for us.
   * In the UNIX domain we have to choose our own name (that
   * should be unique). We'll use mktemp() to create a unique
   * pathname, based our process id.  */
  bzero((char *) &cli_addr, sizeof(cli_addr));	/* zero out */
  cli_addr.sun_family = AF_UNIX;
  strcpy(cli_addr.sun_path, UNIXDG_TMP);
  mkstemp(cli_addr.sun_path);
  clilen = sizeof(cli_addr.sun_family) + strlen(cli_addr.sun_path);

  if (bind(sockfd, (struct sockaddr *) &cli_addr, clilen) < 0)
	err_dump("client: can't bind local address");

  dg_cli(stdin, sockfd, (struct sockaddr *) &serv_addr, servlen);

  close(sockfd);
  unlink(cli_addr.sun_path);

  return 0;
}
25/12/06 - 2018 Masta