DS UNIX TCP/IP-Server in C

(Adapted) Winsock-Codes von Daniel Schwamm (31.03.1998)

UNIX-TCP/IP-Server in C


/*****************************************************************************
UNIX-TCP/IP-Server:

Hauptprozess richtet sockfd ein, der auf bestimmten Socket
lauscht. Wenn Client-Anfrage kommt, dann wird fork() aufgerufen.
Child arbeitet Client ab, während Parent wieder in Lauschzustand
geht (==> paralleler Server).

Zugehöriger Client: DS_WinClient.txt

Von: Daniel Schwamm (www.daniel-schwamm.de)
*****************************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stropts.h>

#define SERV_HOST_ADDR "194.1.1.1"
#define MAXCMD 3000

char RESULTTEXT[MAXCMD];
int SERV_TCP_PORT,sockfd,newsockfd;

DoLoginJob(char *RESULTTEXT){...};
DoHurz(char *RESULTTEXT){...};

/*****************************************************************************
Hole eine Kommandozeile vom Client
*****************************************************************************/
int GetCMD(int sockfd,char *cmd){
  
int n;

  if((
n=recv(sockfd,cmd,MAXCMD,0))<0){
    
sprintf(RESULTTXT,"%s#Konnte Kommando nicht empfangen#",CNSERR);
    return 
0;
  }
  
cmd[n]=0;

  return 
1;
}

/*****************************************************************************
Sende eine Kommandozeile an den Client
*****************************************************************************/
int SendCMD(int sockfd,char *cmd){
  
int n,l;

  
l=strlen(cmd);
  if((
n=send(sockfd,cmd,l,0))<0){
    
sprintf(RESULTTXT,"%s#Konnte Kommando <%s> nicht senden#",CNSERR,cmd);
    return 
0;
  }
  return 
1;
}

/*****************************************************************************
diverse aufräumarbeiten
*****************************************************************************/
void hndlsigurgs(){
  
shutdown(sockfd,2);
  exit(-
1);
}

/*****************************************************************************
diverse aufräumarbeiten
*****************************************************************************/
void hndlsigurgc(){
  
shutdown(newsockfd,2);
  exit(-
1);
}

/*****************************************************************************
Abarbeiten der Kinder-Prozesse. Hierzu werden zuerst die Client-Kommandos
empfangen und dann entspr. Unterprogramme aufgerufen.
*****************************************************************************/
void ChildProc(int sockfd){
  
signal(SIGURG,hndlsigurgc);
  
GetCMD(sockfd,CMD);
  if(
strlcmp(CMD,"LOGIN",5)==0){
    
DoLoginJob(RESULTTEXT);
    
SendCMD(sockfd,RESULTTXT);
  }
  else if(
strcmp(WRD,"HURZ")==0){
    
DoHurzJob(RESULTTEXT);
    
SendCMD(sockfd,RESULTTXT);
  }
  else{
    
sprintf(RESULTTXT,"%s#Unbekanntes Kommando <%s>#",CNSERR,CMD);
    
SendCMD(sockfd,RESULTTXT);
  }
}

/*****************************************************************************
Hauptprogramm: Einrichten des CNS-Servers. Der Server lauscht auf seinem
Socket, bis ein Client sich meldet. Mit fork() wird der Prozess kopiert.
Der Server geht wieder in den Lauschzustand ueber, waehrend der Child-Prozess
die Client-Anfrage abarbeitet.
*****************************************************************************/
void main(int argc,char *argv[]){
  
int clilen,childpid;
  
struct sockaddr_in cli_addr,serv_addr;
  
char fname[200];
  
int n,i,dum,optlen;
  
FILE *logout;
  
char ch;

  
SERV_TCP_PORT=4500;

  
/* Verhindere dreckige Zombis, indem Child-Results ignoriert werden */
  
signal(SIGCLD,SIG_IGN);
  
signal(SIGURG,hndlsigurgs);

  if((
sockfd=socket(AF_INET,SOCK_STREAM,0))<0){
    
printf("CNS-ERROR: Kann Streamsocket nicht oeffnen");
    exit(-
1);
  }
  
optlen=sizeof(dum);
  if(
    
setsockopt(
      
sockfd,
      
SOL_SOCKET,
      
SO_REUSEADDR,
      (
char*)&amp;dum,
      
optlen
    
)<0
  
){
    
printf("CNS-ERROR: Kann Optionen nicht oeffnen");
    exit(-
1);
  }

  
memset((char*)&amp;serv_addr,0,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(sockfd,(struct sockaddr*)&amp;serv_addr,sizeof(serv_addr))<0){
    
MsgLast("CNS-ERROR: Kann lokale Adresse nicht binden");
    exit(-
1);
  }

  
printf("OK: CarNet-Server erfolgreich gestartet. Warte auf Clients ...");
  
clientc=0;
  
listen(sockfd,5);
  for(;;){
    
clilen=sizeof(cli_addr);
    
newsockfd=accept(sockfd,(struct sockaddr*)&amp;cli_addr,&amp;clilen);
    
clientc++;
    if(
newsockfd<0){
      
MsgLast("CNS-ERROR: ACCEPT-Fehler");
      exit(-
1);
    }
    if((
childpid=fork())<0){
      
MsgLast("CNS-ERROR: FORK-Fehler");
      exit(-
1);
    }
    else if(
childpid==0){
      
close(sockfd);
      
ChildProc(newsockfd);
      
shutdown(newsockfd,2);
      exit(
0);
    }
    
close(newsockfd);
  }
}