Unix-sockets-socket-server-example

提供:Dev Guides
移動先:案内検索

Unixソケット-サーバーの例

プロセスをTCPサーバーにするには、以下の手順に従う必要があります-

  • _socket()_システムコールでソケットを作成します。
  • _bind()_システムコールを使用して、ソケットをアドレスにバインドします。 インターネット上のサーバーソケットの場合、アドレスはホストマシンのポート番号で構成されます。
  • _listen()_システムコールで接続をリッスンします。
  • _accept()_システムコールで接続を受け入れます。 通常、この呼び出しは、クライアントがサーバーに接続するまでブロックします。 *_read()_および_write()_システムコールを使用してデータを送受信します。

次に、これらの手順をソースコードの形式で説明します。 このコードをファイル_server.c_に入れて、_gcc_コンパイラーでコンパイルします。

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

#include <netdb.h>
#include <netinet/in.h>

#include <string.h>

int main( int argc, char* argv[] ) {
   int sockfd, newsockfd, portno, clilen;
   char buffer[256];
   struct sockaddr_in serv_addr, cli_addr;
   int  n;

  /*First call to socket() function*/
   sockfd = socket(AF_INET, SOCK_STREAM, 0);

   if (sockfd < 0) {
      perror("ERROR opening socket");
      exit(1);
   }

  /*Initialize socket structure*/
   bzero((char *) &serv_addr, sizeof(serv_addr));
   portno = 5001;

   serv_addr.sin_family = AF_INET;
   serv_addr.sin_addr.s_addr = INADDR_ANY;
   serv_addr.sin_port = htons(portno);

  /* Now bind the host address using bind() call.*/
   if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
      perror("ERROR on binding");
      exit(1);
   }

  /*Now start listening for the clients, here process will
     * go in sleep mode and will wait for the incoming connection
   */

   listen(sockfd,5);
   clilen = sizeof(cli_addr);

  /*Accept actual connection from the client*/
   newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen);

   if (newsockfd < 0) {
      perror("ERROR on accept");
      exit(1);
   }

  /*If connection is established then start communicating*/
   bzero(buffer,256);
   n = read( newsockfd,buffer,255 );

   if (n < 0) {
      perror("ERROR reading from socket");
      exit(1);
   }

   printf("Here is the message: %s\n",buffer);

  /*Write a response to the client*/
   n = write(newsockfd,"I got your message",18);

   if (n < 0) {
      perror("ERROR writing to socket");
      exit(1);
   }

   return 0;
}

複数の接続を処理する

サーバーが複数の同時接続を処理できるように、上記のコードで次の変更を行います-

  • _accept_ステートメントと次のコードを無限ループに入れます。
  • 接続が確立されたら、_fork()_を呼び出して新しいプロセスを作成します。
  • 子プロセスは、_sockfd_を閉じ、_doprocessing_関数を呼び出して、新しいソケットファイル記述子を引数として渡します。 _doprocessing()_が返すように、2つのプロセスが会話を完了すると、このプロセスは単に終了します。 *親プロセスは_newsockfd_を閉じます。 このコードはすべて無限ループにあるため、acceptステートメントに戻り、次の接続を待機します。
#include <stdio.h>
#include <stdlib.h>

#include <netdb.h>
#include <netinet/in.h>

#include <string.h>

void doprocessing (int sock);

int main( int argc, char* argv[] ) {
   int sockfd, newsockfd, portno, clilen;
   char buffer[256];
   struct sockaddr_in serv_addr, cli_addr;
   int n, pid;

  /*First call to socket() function*/
   sockfd = socket(AF_INET, SOCK_STREAM, 0);

   if (sockfd < 0) {
      perror("ERROR opening socket");
      exit(1);
   }

  /*Initialize socket structure*/
   bzero((char *) &serv_addr, sizeof(serv_addr));
   portno = 5001;

   serv_addr.sin_family = AF_INET;
   serv_addr.sin_addr.s_addr = INADDR_ANY;
   serv_addr.sin_port = htons(portno);

  /* Now bind the host address using bind() call.*/
   if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
      perror("ERROR on binding");
      exit(1);
   }

  /*Now start listening for the clients, here
     * process will go in sleep mode and will wait
 *for the incoming connection
  */

   listen(sockfd,5);
   clilen = sizeof(cli_addr);

   while (1) {
      newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);

      if (newsockfd < 0) {
         perror("ERROR on accept");
         exit(1);
      }

     /*Create child process*/
      pid = fork();

      if (pid < 0) {
         perror("ERROR on fork");
         exit(1);
      }

      if (pid == 0) {
        /*This is the client process*/
         close(sockfd);
         doprocessing(newsockfd);
         exit(0);
      }
      else {
         close(newsockfd);
      }

   }/*end of while*/
}

次のコードシーケンスは、_doprocessing_関数の簡単な実装を示しています。

void doprocessing (int sock) {
   int n;
   char buffer[256];
   bzero(buffer,256);
   n = read(sock,buffer,255);

   if (n < 0) {
      perror("ERROR reading from socket");
      exit(1);
   }

   printf("Here is the message: %s\n",buffer);
   n = write(sock,"I got your message",18);

   if (n < 0) {
      perror("ERROR writing to socket");
      exit(1);
   }

}