[Tip] semop() 세마포어 값을 변경

 

--------------------------------------------------------------------------------------------------------------------------

설명

--------------------------------------------------------------------------------------------------------------------------

semop() 함수는 세마포어의 값을 변경합니다. 세마포어를 사용하기 위해서는 

먼저 세마포어 값을 1 감소시키고, 사용 후에는 1 증가시키는데, 이렇게 세마포어값을 증감하는 것을 요청하는 함수입니다.

 

--------------------------------------------------------------------------------------------------------------------------

헤더

--------------------------------------------------------------------------------------------------------------------------

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/sem.h>

 

--------------------------------------------------------------------------------------------------------------------------

형태

--------------------------------------------------------------------------------------------------------------------------

int semop ( int semid, struct sembuf *sops, unsigned nsops )

 

--------------------------------------------------------------------------------------------------------------------------

인수

--------------------------------------------------------------------------------------------------------------------------

int semid 시스템에서 세머포어를 식별하는 집합 번호

struct sembuf *sops

세마포어 값을 계사하기위한 설정 값

struct sembuf {

    short sem_num;   세마포어 번호

    short sem_op;     세마포어 증감값

    short sem_flg;     옵션

}

 

sem_flg sem_flg 내용

IPC_NOWAIT

호출 즉시 실행하지 못했을 경우 기다리지 않고 실패로 바로 복귀합니다.

 

SEM_UNDO 프로세스가 종료되면 시스템에서 세마포어 설저을 원래 상태로 되돌립니다. 그러므로 보통 이 옵션을 사용합니다.

unsigned nsops

변경하려는 세마포어 개수로 변경하려는 세마포어 개수가 여러 개일 때 사용합니다.

예를 들어 변경하려는 세마포어 개수가 한 개라면

 

struct sembuf sbuf = { 0, -1, 0};

semop( semmop, &sbuf, 1);

 

이렇게 값이 1이 되지만 한번에 2개 이상의 세마포어를 변경한다면,

 

struct sembuf pbuf[2]   = {

      { 0,  1, 0} ,   // 첫번째 세마포어 값을 1 증가

      { 1, -1, 0}     // 두번째 세마포어 값을 1 감소

    }

semop( semmop, pbuf, 2);

 

--------------------------------------------------------------------------------------------------------------------------

반환

--------------------------------------------------------------------------------------------------------------------------

0 성공

-1 실패

 

--------------------------------------------------------------------------------------------------------------------------

예제

--------------------------------------------------------------------------------------------------------------------------

예제에서는 두개의 쓰레드를 만들어 첫번째 쓰레드는 카운터 값을 증가 시키고 두번째 쓰레드는 카운터를 화면에 출력합니다. 

카운터가 5 이상의 값이 되면 두 개의 쓰레드는 모두 종료하고 프로그램이 종료되면서 세마포어를 삭제합니다.

여기서 세마포어는 각각의 쓰레드가 독립적으로 실행될수 있음을 보장하는 역할을 수행한다.

 

#include <pthread.h>

#include <stdlib.h>

#include <unistd.h>

#include <stdio.h>

#include <sys/ipc.h>

#include <sys/sem.h>

 

int         cnt   = 0;

static int  semid;

 

void p()

{

   struct sembuf pbuf;

 

   pbuf.sem_num   = 0;

   pbuf.sem_op    = -1;

   pbuf.sem_flg   = SEM_UNDO;

 

   if ( -1 == semop(semid, &pbuf, 1))

      printf( "p()-semop() 실행 오류\n");

}

 

void v()

{

   struct sembuf vbuf;

 

   vbuf.sem_num   = 0;

   vbuf.sem_op    = 1;

   vbuf.sem_flg   = SEM_UNDO;

 

   if ( -1 == semop( semid, &vbuf, 1))

      printf( "v()-semop() 실행 오류\n");

}

 

void *fun_thread1(void *arg)

{

   while( 1)

   {

      p();

      printf( "thread1 실행\n");

      if ( 5 < cnt)

      {

         printf( "thread1 완전 종료\n");

         v();

         break;

      }

      else

      {

         cnt++;

         usleep( 100);

         printf( "thread1 완료\n");

      }

      v();

   }

   return NULL;

}

 

void *fun_thread2(void *arg)

{

   while( 1)

   {

      p();

      printf( "thread2 실행\n");

      if ( 5 < cnt)

      {

         printf( "thread2 완전 종료\n");

         v();

         break;

      }

      else

      {

         printf( "카운터= %d\n", cnt);

         usleep( 100);

         printf( "thread2 완료\n");

      }

      v();

   }

 

   return NULL;

}

 

int main(int argc, char *argv[])

{

   pthread_t thread1;

   pthread_t thread2;

   union semun{

      int                  val;

      struct   semid_ds   *buf;

      unsigned short int  *arrary;

   }  arg;

 

   if ( -1 == (semid = semget( IPC_PRIVATE, 1, IPC_CREAT | 0666)))

   {

      printf( "semget() 실행 오류\n");

      return -1;

   }

 

   arg.val  =  1;                // 세마포어 값을 1로 설정

   if ( -1 == semctl(semid, 0, SETVAL, arg))

   {

      printf( "semctl()-SETVAL 실행 오류\n");

      return -1;

   }

 

   pthread_create(&thread1, NULL, fun_thread1, NULL);

   pthread_create(&thread2, NULL, fun_thread2, NULL);

   pthread_join( thread1, NULL);

   pthread_join( thread2, NULL);

 

   if ( -1 == semctl(semid, 0, IPC_RMID, arg))

   {

      printf( "semctl()-IPC_RMID 실행 오류\n");

      return -1;

   }

   printf( "프로그램 종료\n");

   return 0;

}

 

]$ gcc main.c -lpthread       // 소스에 쓰레드를 이용하므로 옵션에 -lpthread를 추가

]$ ./a.out

thread1 실행

thread1 완료

thread2 실행

카운터= 1

thread2 완료

thread1 실행

thread1 완료

thread2 실행

카운터= 2

thread2 완료

thread1 실행

thread1 완료

thread2 실행

카운터= 3

thread2 완료

thread1 실행

thread1 완료

thread2 실행

카운터= 4

thread2 완료

thread1 실행

thread1 완료

thread2 실행

카운터= 5

thread2 완료

thread1 실행

thread1 완료

thread2 실행

thread2 완전 종료

thread1 실행

thread1 완전 종료

프로그램 종료

]$

#include <windows.h>

#include <stdio.h>

 

#if(0)

gcc -Wall -DTEST_PRINTF -c win12.c

gcc -o win12 win12.o -lm -lws2_32 -lgdi32

#endif

 

void gotoxy(int x, int y)      // 좌표 보내기 gotoxy

{

    COORD Cur;

    Cur.X=x;

    Cur.Y=y;

    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),Cur);

}

void cursor(int n) // 커서 보이기 & 숨기기

{

    HANDLE hConsole;

    CONSOLE_CURSOR_INFO ConsoleCursor;

 

    hConsole = GetStdHandle(STD_OUTPUT_HANDLE);

 

    ConsoleCursor.bVisible = n;

    ConsoleCursor.dwSize = 1;

 

    SetConsoleCursorInfo(hConsole , &ConsoleCursor);

}

int main(void)

{

    POINT pt; // 마우스 포인터

    int x[50000]; // 매크로 x좌표

    int y[50000]; // 매크로 y좌표

    int sub_x[50000], sub_y[50000]; // 보조 xy

    int check_mouse = 2; // 마우스 관련 변수

    int i = 0; // 매크로 녹화시 이용

    int n = 0; // 메크로 진행시 이용

 

 

    system("mode con: cols=31 lines=13"); // 화면 고정

    cursor(0); // 커서 숨기기

 

    gotoxy(0,0);

    puts("┏━━━━━━━━━━━━━┓"); // puts함수는 자동으로 줄바꿈 처리를 한다.

    puts("┃             ┃");

    puts("┃     Mouse Macro    ┃");

    puts("┃             ┃");

    puts("┃  F5 : 매크로 녹화    ┃");

    puts("┃  F6 : 매크로 추가녹화 ┃");

    puts("┃  F7 : 매크로 정지   ┃");

    puts("┃  F8 : 매크로 시작   ┃");

    puts("┃  F10 : 종료하기      ┃");

    puts("┃  F11 : 상세 도움말    ┃");

    puts("┃             ┃");

    puts("┗━━━━━━━━━━━━━┛");

 

    while(1)

    { 

        if(GetKeyState(VK_F10) < 0) // F10키 누르면

        {

            return 0; // 프로그램 종료

        }

        else if(GetKeyState(VK_F11) < 0 ) // F11키 누르면

        {

            gotoxy(0,0);

            puts("┏━━━━━━━━━━━━━┓");

            puts("┃  F5 : 매크로 녹화    ┃");

            puts("┃  >>처음부터 녹화를 시작 ┃");

            puts("┃  F6 : 매크로 추가녹화 ┃");

            puts("┃ >>계속 이어서 녹화     ┃");

            puts("┃             ┃");

            puts("┃  녹화 뒤 매크로 정지 후 ┃");

            puts("┃  매크로 시작을 누르면   ┃");

            puts("┃  매크로가 진행됩니다.  ┃");

            puts("┃  (마우스 매크로만 가능)  ┃");

            puts("┃   Esc : 돌아가기   ┃");

            puts("┗━━━━━━━━━━━━━┛");

 

            while(1)

            {

                if(GetKeyState(27) < 0) // Esc키 누르면

                {

                    gotoxy(0,0);

                    puts("┏━━━━━━━━━━━━━┓");

                    puts("┃             ┃");

                    puts("┃     Mouse Macro    ┃");

                    puts("┃             ┃");

                    puts("┃  F5 : 매크로 녹화    ┃");

                    puts("┃  F6 : 매크로 추가녹화 ┃");

                    puts("┃  F7 : 매크로 정지   ┃");

                    puts("┃  F8 : 매크로 시작   ┃");

                    puts("┃  F10 : 종료하기      ┃");

                    puts("┃  F11 : 상세 도움말    ┃");

                    puts("┃             ┃");

                    puts("┗━━━━━━━━━━━━━┛");

                    break; // while문 탈출

                }

            }

        }

        else if(GetKeyState(VK_F5) < 0 ) // 처음부터 다시 매크로 설정

        {

            for(i = 0 ; i <= 50000 ; i ++)

            {

                x[i] = -858993460; y[i] = -858993460; // 초기화 과정

                sub_x[i] = -858993460; sub_y[i] = -858993460;

                // 이때 모든 값은 모니터 해상도에 따라 마우스 좌표값이

                // 될 수 있어서 쓰레기값인 -858993460을 이용했다.

                // 추천하는 방법은 아니다.

            }

            i = 0;

 

            while(1)

            {

                GetCursorPos(&pt); // 마우스 좌표값들 받아옴

                x[i] = pt.x; // x좌표값 저장

                y[i] = pt.y; // y좌표값 저장

                sub_x[i] = 0, sub_y[i] = 0; // 왼쪽버튼 누르고 떼는 모습 저장하는 곳

                i++; // i는 프레임을 의미

                Sleep(10); //  0.01초 마다 1프레임 찍힘

 

                if(GetKeyState(VK_LBUTTON) < 0 && check_mouse >= 1)  // 왼쪽버튼 눌렀을 때

                {

 

                    sub_x[i] = x[i-1];

                    sub_y[i] = y[i-1];

                    x[i] = 5000;

                    y[i] = 5000;

 

                    check_mouse = 0;

 

                    i++;        

                }

                else if(GetKeyState(VK_LBUTTON) >= 0 && check_mouse == 0) // 왼쪽버튼 뗄 때

                {

 

                    sub_x[i] = x[i-1];

                    sub_y[i] = y[i-1];

                    x[i] = 6000;

                    y[i] = 6000;

 

                    check_mouse = 1;

 

                    i++;        

                }

 

 

                if(GetKeyState(VK_F7) < 0 )

                {

                    break;

                }

                if(GetKeyState(VK_F10) < 0 )

                {

                    return 0;

                }

            }

        }

        else if(GetKeyState(VK_F6) < 0 ) // 이어서 매크로 설정

        {

 

            while(1)

            {

                GetCursorPos(&pt);

                x[i] = pt.x;

                y[i] = pt.y;

                sub_x[i] = 0, sub_y[i] = 0;

 

                i++;         

                Sleep(10);

 

                if(GetKeyState(VK_LBUTTON) < 0 && check_mouse >= 1)  // 왼쪽버튼 눌렀을 때

                {

 

                    sub_x[i] = x[i-1];

                    sub_y[i] = y[i-1];

 

                    x[i] = 5000;

                    y[i] = 5000;

                    check_mouse = 0;

 

                    i++;        

                }

                else if(GetKeyState(VK_LBUTTON) >= 0 && check_mouse == 0) // 왼쪽버튼 뗄 때

                {

                    sub_x[i] = x[i-1];

                    sub_y[i] = y[i-1];

                    x[i] = 6000;

                    y[i] = 6000;

                    check_mouse = 1;

 

                    i++;        

                }        

 

                if(GetKeyState(VK_F7) < 0 )

                {

                    break;

                }

                if(GetKeyState(VK_F10) < 0 )

                {

                    return 0;

                }

            }

        }

        else if(GetKeyState(VK_F8) < 0 ) // 매크로 재생

        {

            n = 0; // 프레임 처음으로 돌아가서 재생하기 위한 n

 

            while(1)

            {

                if(x[n] == 5000) // 왼쪽버튼 눌러지는 것을 5000이라고 가정

                {

                    mouse_event(MOUSEEVENTF_LEFTDOWN, sub_x[n], sub_y[n], 0, 0); // 좌표에 맞게 왼쪽버튼 누르기

                    Sleep(1);

                }

                else if(x[n] == 6000) // 왼쪽버튼 떼지는 것을 6000이라고 가정

                {

                    mouse_event(MOUSEEVENTF_LEFTUP, sub_x[n], sub_y[n], 0, 0);  // 좌표에 맞게 왼쪽버튼 떼기

                    Sleep(1);

                }

 

                if(x[n] == -858993460) // 쓰레기값 만나면 처리되는 작동

                {

                    n = 0; // 즉, 매크로의 끝부분으로 가면 다시 n = 0 으로 하여 다시 처음부터 시작

                }

 

                SetCursorPos(x[n],y[n]); // 지정한 곳의 좌표로 마우스 이동

                Sleep(10);

 

                n++;

 

                if(GetKeyState(VK_F7) < 0 )

                {

                    break;

                }

                if(GetKeyState(VK_F10) < 0 )

                {

                    return 0;

                }

            }

        }

        Sleep(10);

    }

    return 0;

}

 

 

Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation. All rights reserved.

bash-3.1$
bash-3.1$ cat Makefile

CC = gcc

CFLAGS += -I./include/ -g -Wall -Wno-unused-variable
LIBS += -L. -lcurl -ljson-c -lwsock32

.c.o:
        $(CC) -c $< $(CFLAGS)

all: build

common.o : common.c
calc_server.o : calc_server.c
pushcall.o : pushcall.c
win_calc_server.o : win_calc_server.c

win_calc_server: win_calc_server.o pushcall.o common.o calc_server.o
        $(CC) -o $@ $^ $(LIBS)
BUILD_FILES += win_calc_server

build: $(BUILD_FILES)

clean:
        rm -f *.o
        rm -f $(BUILD_FILES)
bash-3.1$ make clean
rm -f *.o
rm -f win_calc_server
bash-3.1$
bash-3.1$
bash-3.1$
bash-3.1$
bash-3.1$
bash-3.1$
bash-3.1$
bash-3.1$
bash-3.1$
bash-3.1$
bash-3.1$
bash-3.1$
bash-3.1$ make all
gcc -c win_calc_server.c -I./include/ -g -Wall -Wno-unused-variable
gcc -c pushcall.c -I./include/ -g -Wall -Wno-unused-variable
gcc -c common.c -I./include/ -g -Wall -Wno-unused-variable
gcc -c calc_server.c -I./include/ -g -Wall -Wno-unused-variable
gcc -o win_calc_server win_calc_server.o pushcall.o common.o calc_server.o -L. -lcurl -ljson-c -lwsock32
bash-3.1$
bash-3.1$
bash-3.1$
bash-3.1$
bash-3.1$
bash-3.1$
bash-3.1$
bash-3.1$
bash-3.1$
bash-3.1$
bash-3.1$
bash-3.1$
bash-3.1$

 

 

 

 

 

#include <WinSock2.h>

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

 

#define  MAXLINE 1024

 

DWORD WINAPI stdin_input_send_thread(LPVOID arg);

 

char line[MAXLINE], chatdata[MAXLINE+1];

 

struct sockaddr_in server_addr;

SOCKET clientsocket; //server connect socket

char *escape = "quit"; //exit command message

BOOL bisquit;           //exit falg variable

 

int main(int argc, char *argv[])

{

    WSADATA wsa;    //socket

    HANDLE hthread; //thread

    DWORD threadid;

    int size;

 

    if (argc != 3) 

    {

        printf("usage : %s server_address port\n", argv[0]);

        return(-1);

    }

    bisquit = FALSE;

 

    //socket initialization

    if (WSAStartup(MAKEWORD(2,2), &wsa) != 0) 

    {

        return(-2);

    }

    //socket creation

    if ((clientsocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) 

    {

        printf("fail make socket\n");

        return(-3);

    }

 

    //memory initialization

    memset(&server_addr, 0x00, sizeof(server_addr));

    server_addr.sin_family = AF_INET;

    server_addr.sin_addr.s_addr = inet_addr(argv[1]);

    server_addr.sin_port = htons(atoi(argv[2]));

 

    //connection with server

    if (connect(clientsocket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) 

    {

        printf("fail connect to server\n");

        return(-4);

    }

    else 

    {

        printf("connected server\n");

    }

 

 

    //stdin & send data thread creation

//stdin & send data thread creation

//stdin & send data thread creation

//stdin & send data thread creation

//stdin & send data thread creation

    hthread = CreateThread(NULL, 0, stdin_input_send_thread, 0, 0, &threadid);

    if (hthread == NULL) 

    {

        printf("fail make thread\n");

    }

    else 

    {

        CloseHandle(hthread);

    }

 

    while (!bisquit) 

    {

        memset(chatdata, 0x00, sizeof(chatdata));

 

        if ((size = recv(clientsocket, chatdata, MAXLINE, 0)) == INVALID_SOCKET) 

{

break;

}

else 

{

chatdata[size] = '\0';

printf("%s", chatdata);

}

    }

    closesocket(clientsocket);

    WSACleanup();

 

return(0);

}

 

//user data input mechanism

DWORD WINAPI stdin_input_send_thread(LPVOID arg)

{

    while(TRUE) 

    {

//stream read in stdin, input '\n' character is ended.

//stream read in stdin, input '\n' character is ended.

        if (fgets(chatdata, MAXLINE, stdin))

        {

            chatdata[strlen(chatdata) - 1] = 0x00;

            sprintf(line, "%s", chatdata);

 

if (strstr(line, escape) != 0) //exit command str

            {

                printf("GoodBye!!!!!!!\n");

                closesocket(clientsocket);

                bisquit = TRUE;

                return(-1);

            }

            

if (send(clientsocket, line, strlen(line), 0) < 0) 

            {

                printf("write fail\n");

return(-2);

            }

        }

    }

    return 0;

}

 

 

 

 

 

 

/*

WINDOWS,SOCKET,SELECT,SERVER,TCP

WINDOWS,SOCKET,SELECT,SERVER,TCP

WINDOWS,SOCKET,SELECT,SERVER,TCP,MULTI CHAT

WINDOWS,SOCKET,SELECT,SERVER,TCP,MULTI CHAT

WINDOWS,SOCKET,SELECT,SERVER,TCP,MULTI CHAT

WINDOWS,SOCKET,SELECT,SERVER,TCP,MULTI CHAT

*/

 

 

#include <stdio.h>

#include <fcntl.h>

#include <stdlib.h>

#include <winsock2.h>

#include <string.h>

 

#define MAXLINE 512

#define MAX_SOCK 64

 

#define bzero(b,len) (memset(b,0,len))

#define bcopy(b1,b2,len) (memcpy(b1,b2,len))

 

char *escapechar = "exit";

char send_calc_msg[MAXLINE+1];

 

//EXTERN LINK VARIABLE

char input[MAXLINE+1];

 

int maxfdp1;

int g_num_chat = 0;

int client_s[MAX_SOCK];

 

 

//STATIC LINK

static int getmax(int);

static void removeclient(int);

static int getdottedipaddr(int sd, struct sockaddr_in *addr);

 

//EXTERN LINK(calc_server.c)

int calculation_socket(char send_calc_msg[MAXLINE+1]);

//EXTERN LINK(pushcall.c)

int pushcall(void);

//EXTERN LINK(common.c)

int GetDate();

int GetTime();

 

int main(int argc, char *argv[]) 

{

    char rline[MAXLINE+1], send_calc_msg[MAXLINE+1];

    char *welcome_msg = "Connected to Server, Welcome!!!!!!!\n";

    char tmp[1024];

    int ii, kk, nn;

    int client_fd, clilen, rc;

 

    fd_set read_fds;

    WSADATA wsadata;

    SOCKET hservsock;

    SOCKADDR_IN client_addr, server_addr;

 

    if (argc != 2) {

        printf("usage : %s port\n", argv[0]);

        return(-1);

    }

 

    //The Windows Sockets WSAStartup function initiates use of WS2_32.DLL by a process.

    //The WSAStartup function must be the first Windows Sockets function called by an application or DLL. 

    //It allows an application or DLL to specify the version of Windows Sockets required and to retrieve details of the specific Windows Sockets implementation. 

    //The application or DLL can only issue further Windows Sockets functions after a successfully calling

    if(WSAStartup(MAKEWORD(2,2), &wsadata) != 0)

    {

        printf("Load Winsock 2.2 DLL Error\n");

        return(-9);

    }

 

    printf(">>>>>1. wsastartup succ!!(%d)(%d)\n", GetDate(), GetTime());

 

    hservsock=socket(PF_INET, SOCK_STREAM, 0);

    if(hservsock==INVALID_SOCKET)

    {

        printf("socket() error\n");

        return(-8);

    }

    printf(">>>>>2. socket succ!!(%d)(%d)\n", GetDate(), GetTime());

 

    bzero((char *)&server_addr, sizeof(server_addr));

    server_addr.sin_family = AF_INET;

    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    server_addr.sin_port = htons(atoi(argv[1]));

 

    if (bind(hservsock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {

        printf("server: can't bind local address.\n");

        return(-3);

    }

    printf(">>>>>3. bind succ!!(%d)(%d)\n", GetDate(), GetTime());

 

    listen(hservsock, 5); /* backlog = 5 */

    printf(">>>>>4. listen succ!!(%d)(%d)\n", GetDate(), GetTime());

 

    maxfdp1 = hservsock + 1;

 

    printf(">>>>>5. main ok!!!!!!!(%d)(%d)\n", GetDate(), GetTime());

    printf(">>>>>5. main ok!!!!!!!(%d)(%d)\n", GetDate(), GetTime());

    printf(">>>>>5. main ok!!!!!!!(%d)(%d)\n", GetDate(), GetTime());

 

    while (1) 

    {

        //initialization with all user(send), server(receive)

        FD_ZERO(&read_fds);

 

        //FD_SET은 관찰을 할 소켓들을 등록하는 변수입니다. 

        //소켓이 새로 만들어지고 select()함수를 통해 관찰을 하고 싶다면 fd_set변수에 소켓을 등록해야 합니다.

 

        //set register reference value with all user(send), server(receive)

        FD_SET(hservsock, &read_fds);

        for (ii=0; ii < g_num_chat; ii++)

        {

            FD_SET(client_s[ii], &read_fds);

        }

 

        //maxfdp1 variavle values re-calculation

        maxfdp1 = getmax(hservsock) + 1;

 

        /*wait & response, all client & server */

        /*wait & response, all client & server */

        /*wait & response, all client & server */

        /*wait & response, all client & server */

        if (select(maxfdp1, &read_fds, (fd_set *)0, (fd_set *)0, (struct timeval *)0) < 0) 

        {

            printf("server: select error.\n");

            break;

        }

 

        //1. SELECT call and search change socket-filediscriptor

        //2. CHANGED socket-filediscriptor, find socket-filediscriptor, send, recv, accept function call

        //3. FD_ISSET(hservsock, &read_fds) is accept function calling

        //4. FD_ISSET(client_s[ii], &read_fds) is recv, send function calling

        if (FD_ISSET(hservsock, &read_fds)) 

        {

            //관찰의 대상은 server socket도 대상이 됩니다. 

            //기존에 존재하는 클라이언트가 아닌 새로운 클라이언트의 접속요청을 받앗을때에 해당됩니다.

 

            //select target is two groups

            //1. server socket

            //2. client socket(when multi, loop is needed)

 

            //1 user connected with server

            clilen = sizeof(client_addr);

            client_fd = accept(hservsock, (struct sockaddr *)&client_addr, &clilen);

            if (client_fd == -1) 

            {

                printf("server: accept error\n");

                break;

            }

            client_s[g_num_chat] = client_fd;

            g_num_chat++;

 

            printf("1. server: accept ok.cient fd[%d],all user cnt[%d]-------------------------\n", 

                      client_fd, g_num_chat);

    printf("1. server: accept ok.cient fd[%d],all user cnt[%d]-------------------------\n", 

                      client_fd, g_num_chat);

    printf("1. server: accept ok.cient fd[%d],all user cnt[%d]-------------------------\n", 

                      client_fd, g_num_chat);

 

            /*welcome message*/

            printf("2. server: send [welcome message] ok.--------------------------------------\n");

            send(client_fd, welcome_msg, strlen(welcome_msg), 0);

 

            if (getdottedipaddr(client_fd, &client_addr) > -1)

                printf("3. %d number additional(IP: %s)\n", g_num_chat, inet_ntoa(client_addr.sin_addr));

            else

                printf("3. %d number additional\n", g_num_chat);

        }

 

        /*ABOUT SERVER CONNECTED, g_num_chat수에 대해 RECEIVE 메세지가 있는지 ALL 조사해서,

        g_num_chat수만큼 다시 해당메세지를 ALL SENDING.*/

        for (ii=0; ii<g_num_chat; ii++) 

        {

            //client_s[ii]에 read_fds의 값이 설정되어 있으면 0이 아닙니다.

            if (FD_ISSET(client_s[ii], &read_fds)) 

            {

                printf("4. server: recv ok,client_s[%.5d][%d].------------------------------------------\n", 

                          ii+1, client_s[ii]);

                if ((nn = recv(client_s[ii], rline, MAXLINE, 0)) <= 0) 

                {

                    removeclient(ii); /* abrupt exit *//* abrupt exit *//* abrupt exit *//* abrupt exit */

                    continue;

                }

                rline[nn] = 0x00;

 

                if (strstr(rline, escapechar) != NULL) 

                {

                    removeclient(ii); /* abrupt exit *//* abrupt exit *//* abrupt exit *//* abrupt exit *//* abrupt exit */

                    continue;

                }

 

                //according to recv msg, logic execute

                //according to recv msg, logic execute

                //according to recv msg, logic execute

                if(strstr(rline, "GOOGLE") != NULL) //unique user response

                {

                    rc = pushcall();

                    if(rc)

                    {

                        //ERROR

                    }

                    memset(send_calc_msg,0x00,sizeof(send_calc_msg));

                    strcpy(send_calc_msg, "google pushcall succ!!\n");

 

                    send(client_s[ii], send_calc_msg, strlen(send_calc_msg), 0);

                }

                if(strstr(rline, "help") != NULL) //unique user response

                {

                    memset(tmp,0x00,sizeof(tmp));

                    strcat(tmp, "1. GOOGLE\n");

strcat(tmp, "2. calc>>\n");

strcat(tmp, "3. msg>>\n");

 

                    send(client_s[ii], tmp, strlen(tmp), 0);

                }

                else if(strstr(rline, "calc>>") != NULL) //all user response

                {

                    memset(send_calc_msg,0x00,sizeof(send_calc_msg));

                    memset(input,0x00,sizeof(input));

                    sprintf(input, "%s", strstr(rline, "calc>>") + strlen("calc>>"));

                    rc = calculation_socket(send_calc_msg);

                    if(rc)

                    {

                        //ERROR

                    }

 

                    for (kk=0; kk<g_num_chat; kk++)

                    {

                        printf("5. server: send ok,client_s[%.5d][%d]-------------------------------------------\n", kk+1, client_s[kk]);

                        if(client_s[kk] == client_s[ii])

                        {

                            send(client_s[kk], send_calc_msg, strlen(send_calc_msg), 0);

                        }

                        else

                        {

                            memset(tmp,0x00,sizeof(tmp));

                            memcpy(tmp, rline, nn);

                            strcat(tmp, "other user request & response:");

                            strcat(tmp, send_calc_msg);

                            send(client_s[kk], tmp, strlen(tmp), 0);

                        }

                    }

                }

                else if(strstr(rline, "msg>>") != NULL) //all user response

                {

                    memset(tmp,0x00,sizeof(tmp));

                    sprintf(tmp, "%s", strstr(rline, "msg>>") + strlen("msg>>"));

 

                    for (kk=0; kk<g_num_chat; kk++)

                    {

                        printf("5. server: send ok,client_s[%.5d][%d]-------------------------------------------\n", kk+1, client_s[kk]);

                        if(client_s[kk] == client_s[ii])

                        {

                            send(client_s[kk], tmp, strlen(tmp), 0);

                        }

                        else

                        {

                            send(client_s[kk], tmp, strlen(tmp), 0);

                        }

                    }

                }

 

                if (getdottedipaddr(client_fd, &client_addr) > -1)

                {

                    printf("6. IP:(%s),message:%s", inet_ntoa(client_addr.sin_addr), rline);

                }

                else

                {

                    printf("6. message:%s", rline);

                }

            }

        }

    } /* while */

 

    //The WSACleanup function terminates use of the Winsock 2 DLL (Ws2_32.dll).

    //The WSACleanup function terminates use of the Winsock 2 DLL (Ws2_32.dll).

    //The WSACleanup function terminates use of the Winsock 2 DLL (Ws2_32.dll).

    rc = WSACleanup();

    if(rc == WSANOTINITIALISED)

    {

        printf(">>error::A successful WSAStartup call must occur before using this function.\n");

    }

    else if(rc == WSAENETDOWN)

    {

        printf(">>error::The network subsystem has failed.\n");

    }

    else if(rc == WSAEINPROGRESS)

    {

        printf(">>error::A blocking Windows Sockets 1.1 call is in progress, or the service provider is still processing a callback function.\n");

    }

    closesocket(hservsock);

}

 

void removeclient(int indx) 

{

    struct sockaddr_in client_addr;

 

    if (getdottedipaddr(client_s[indx], &client_addr) > -1)

    {

        printf("\nserver>>removeclient>>1 number expired!!(IP: %s).", inet_ntoa(client_addr.sin_addr));

    }

    else

    {

        printf("\nserver>>removeclient>>1 number expired!!.");

    }

 

    closesocket(client_s[indx]);

 

    if (indx != g_num_chat-1)

    {

        client_s[indx] = client_s[g_num_chat-1];

    }

 

    g_num_chat--;

    printf("\nserver>>removeclient>>now number = %d\n", g_num_chat);

}

 

int getmax(int k) 

{

    int max = k;

    int r;

 

    for (r=0; r < g_num_chat; r++)

    {

        if (client_s[r] > max) max = client_s[r];

    }

    return max;

}

 

int getdottedipaddr(int sd, struct sockaddr_in *addr) 

{

    struct sockaddr_in client_addr;

    int len, r;

 

    len = sizeof(client_addr);

    if ((r = getpeername(sd, (struct sockaddr *)&client_addr, &len)) == 0)

    {

        *addr = client_addr;

    }

    return r;

}

 

+ Recent posts