c언어 소켓 통신 예제 (멀티 스레드, 멀티 프로세스)

프로그래밍/C, C++|2021. 3. 2. 15:24
반응형

멀티 스레드와 멀티 프로세스의 차이점을 설명한 글입니다.

요약하자면, 가장 큰 차이는 멀티스레드 방식은 공유 메모리를 갖고, 멀티프로세스 방식은 별도 메모리를 갖는듯..

내용을 확인 하신 후 상황에 맞는 소켓을 작성 하시기 바랍니다.

https://you9010.tistory.com/136

 

예제는 해외 사이트에서 가져왔으나, client 수 제한이 없거나 좀비프로세스 발생을 원치 않는다면 아래 URL 에서도 깔끔한 소스를 보실 수 있습니다.

https://velog.io/@jyongk/Multi-Process-Server-Multi-Thread-Server

 

 

멀티 스레드 방식

socket_server.c

 

#include <stdio.h>

#include <stdlib.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <string.h>

#include <arpa/inet.h>

#include <fcntl.h> // for open

#include <unistd.h> // for close

#include <pthread.h>

 

char client_message[2000];

char buffer[1024];

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

 

void * socketThread(void *arg)

{

  int newSocket = *((int *)arg);

  recv(newSocket , client_message , 2000 , 0);

 

  // Send message to the client socket 

  pthread_mutex_lock(&lock);

  char *message = malloc(sizeof(client_message)+20);

  strcpy(message,"Hello Client : ");

  strcat(message,client_message);

  strcat(message,"\n");

  strcpy(buffer,message);

  free(message);

  pthread_mutex_unlock(&lock);

  sleep(1);

  send(newSocket,buffer,13,0);

  printf("Exit socketThread \n");

  close(newSocket);

  pthread_exit(NULL);

}

 

int main(){

  int serverSocket, newSocket;

  struct sockaddr_in serverAddr;

  struct sockaddr_storage serverStorage;

  socklen_t addr_size;

 

  //Create the socket. 

  serverSocket = socket(PF_INET, SOCK_STREAM, 0);

 

  // Configure settings of the server address struct

  // Address family = Internet 

  serverAddr.sin_family = AF_INET;

 

  //Set port number, using htons function to use proper byte order 

  serverAddr.sin_port = htons(7799);

 

  //Set IP address to localhost 

  serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");

 

 

  //Set all bits of the padding field to 0 

  memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);

 

  //Bind the address struct to the socket 

  bind(serverSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr));

 

  //Listen on the socket, with 40 max connection requests queued 

  if(listen(serverSocket,50)==0)

    printf("Listening\n");

  else

    printf("Error\n");

    pthread_t tid[60];

    int i = 0;

    while(1)

    {

        //Accept call creates a new socket for the incoming connection

        addr_size = sizeof serverStorage;

        newSocket = accept(serverSocket, (struct sockaddr *) &serverStorage, &addr_size);

 

        //for each client request creates a thread and assign the client request to it to process

       //so the main thread can entertain next request

        if( pthread_create(&tid[i++], NULL, socketThread, &newSocket) != 0 )

           printf("Failed to create thread\n");

 

        if( i >= 50)

        {

          i = 0;

          while(i < 50)

          {

            pthread_join(tid[i++],NULL);

          }

          i = 0;

        }

    }

  return 0;

}

 

멀티프로세스 방식

socket_server.c

 

#include <stdio.h>

#include <stdlib.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <string.h>

#include <arpa/inet.h>

#include <fcntl.h> // for open

#include <unistd.h> // for close

#include <sys/types.h>

#include <pthread.h>

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

 

void  socketThread(int clientSocket)

{

 

  char client_message[2000];

  char buffer[1024];

 

  int newSocket = clientSocket;

 

  recv(newSocket , client_message , 2000 , 0);

 

  // Send message to the client socket

  pthread_mutex_lock(&lock);

  char *message = malloc(sizeof(client_message)+20);

  strcpy(message,"Hello Client : ");

  strcat(message,client_message);

  strcat(message,"\n");

  strcpy(buffer,message);

  free(message);

  pthread_mutex_unlock(&lock);

  sleep(1);

  send(newSocket,buffer,13,0);

  printf("Exit socketThread \n");

  close(newSocket);

  }

 

 

 

int main(){

  int serverSocket, newSocket;

  struct sockaddr_in serverAddr;

  struct sockaddr_storage serverStorage;

  socklen_t addr_size;

  pid_t pid[50];

  //Create the socket.

  serverSocket = socket(PF_INET, SOCK_STREAM, 0);

 

  // Configure settings of the server address struct

  // Address family = Internet

  serverAddr.sin_family = AF_INET;

 

  //Set port number, using htons function to use proper byte order

  serverAddr.sin_port = htons(7799);

 

  //Set IP address to localhost

  serverAddr.sin_addr.s_addr = inet_addr("0.0.0.0");

  //Set all bits of the padding field to 0

  memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);

 

  //Bind the address struct to the socket

  bind(serverSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr));

 

  //Listen on the socket, with 50 max connection requests queued

  if(listen(serverSocket,50)==0)

    printf("Listening\n");

  else

    printf("Error\n");

    int i = 0;

while(1)

    {

        /* Accept call creates a new socket for the incoming connection */

        addr_size = sizeof serverStorage;

        newSocket = accept(serverSocket, (struct sockaddr *) &serverStorage, &addr_size);

        int pid_c = 0;

 

      if ((pid_c = fork())==0)

        {

          socketThread(newSocket);

        }

        else

        {

          pid[i++] = pid_c;

          if( i >= 49)

           {

             i = 0;

             while(i < 50)

                waitpid(pid[i++], NULL, 0);

             i = 0;

           }

        }

    }

  return 0;

}


클라이언트 소켓 파일

socket_client.c

 

#include <stdio.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <string.h>

#include <arpa/inet.h>

#include <stdlib.h>

#include <fcntl.h> // for open

#include <unistd.h> // for close

#include<pthread.h>

 

void * cientThread(void *arg)

{

  printf("In thread\n");

  char message[1000];

  char buffer[1024];

  int clientSocket;

  struct sockaddr_in serverAddr;

  socklen_t addr_size;

 

  // Create the socket. 

  clientSocket = socket(PF_INET, SOCK_STREAM, 0);

 

  //Configure settings of the server address

 // Address family is Internet 

  serverAddr.sin_family = AF_INET;

 

  //Set port number, using htons function 

  serverAddr.sin_port = htons(7799);

 

 //Set IP address to localhost

  serverAddr.sin_addr.s_addr = inet_addr("localhost");

  memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);

 

    //Connect the socket to the server using the address

    addr_size = sizeof serverAddr;

    connect(clientSocket, (struct sockaddr *) &serverAddr, addr_size);

    strcpy(message,"Hello");

 

   if( send(clientSocket , message , strlen(message) , 0) < 0)

    {

            printf("Send failed\n");

    }

 

    //Read the message from the server into the buffer

    if(recv(clientSocket, buffer, 1024, 0) < 0)

    {

       printf("Receive failed\n");

    }

    //Print the received message

    printf("Data received: %s\n",buffer);

    close(clientSocket);

    pthread_exit(NULL);

}

int main(){

  int i = 0;

  pthread_t tid[51];

  while(i< 50)

  {

    if( pthread_create(&tid[i], NULL, cientThread, NULL) != 0 )

           printf("Failed to create thread\n");

    i++;

  }

  sleep(20);

  i = 0;

  while(i< 50)

  {

     pthread_join(tid[i++],NULL);

     printf("%d:\n",i);

  }

  return 0;

} 

 

 

 

[출처] https://dzone.com/articles/parallel-tcpip-socket-server-with-multi-threading

[수정] 출처의 예제에 오타가 있어서 바로 실행하면 에러가 발생합니다. 소스를 보완하여 작성하였습니다.

반응형

댓글()