Riucc's Storage
RSS
태그
관리
쓰기
카테고리
  • IT (593)
    • 정리 (0)
    • C# (42)
    • ASP.NET MVC (16)
    • JQuery&Javascript (12)
    • CSS (11)
    • 데이터베이스 (32)
    • Windows Server (6)
    • Active Directory (3)
    • Exchange (9)
    • JAVA (2)
    • JSP (39)
    • JSP 게시판 만들기 (21)
    • JSP 개발 참고 (15)
    • JSP 안드로이드 (4)
    • Servlet (17)
    • Spring (42)
    • HTML (14)
    • NodeJS (46)
    • MongoDB (11)
    • 리눅스 (18)
    • 자료구조 (16)
    • 아이폰 (24)
    • 안드로이드 (68)
    • API 활용하기 (10)
    • 소켓네트워크 (28)
    • 라즈베리파이 (11)
    • AWS클라우드 (10)
    • 빅데이터Hadoop (22)
    • 커널모듈프로그래밍 (8)
    • 기타 (10)
    • 자격증 (26)
Riucc's Storage

[소켓네트워크] - 채팅 서버 코드

소켓네트워크|2017. 6. 2. 00:05
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

○ 채팅 서버 코드

 

※ strtok, strstr 이용하여 클라이언트 닉네임, 보내는 메시지 등 문자열 처리

※ 귓속말 기능, 메뉴얼 기능, 욕 필터링 기능, 접속 명단 추가

※ 라즈베리파이 wiringPi와 thread를 이용하여 LED 및 부저 병행 처리

 

#include        <stdio.h>
#include        <stdlib.h>
#include        <string.h>
#include        <unistd.h>
#include        <netinet/in.h>
#include        <sys/socket.h>
#include        <pthread.h>
#include        <wiringPi.h>

void*         do_chat(void *);
char* word[10] = {"kill", "sibal", "gese", "18", "ssibal", "fuck", "fucking", "lol", "shut", "hell"};  // 필터링 할 욕설
int checkword(char *word,const char *find);   // 문자열 욕설인지 비교

pthread_t    thread;
pthread_mutex_t    mutex;

#define MAX_NAME 100
int usercnt =0;
struct user{   // 소켓, 닉네임, 욕설 카운트
    int clientsocket;
    char name[MAX_NAME];
    int checkcnt;
};

void* do_redLed();

void* do_yellowLed();

void* do_blueLed();

void* do_buzzer();

#define         MAX_CLIENT      10
#define         CHATDATA        1024

#define         INVALID_SOCK        -1

struct user list_c[MAX_CLIENT];
char        escape[] = "exit";
char        greeting[] = "Welcome to chatting room\n";
char        CODE200[] = "Sorry No More Connection\n";

main(int argc, char *argv[])
{
 wiringPiSetup();
 pinMode(1, OUTPUT); // RED
 pinMode(4, OUTPUT); // YELLOW
 pinMode(5, OUTPUT); // GREEN
 pinMode(6, OUTPUT); // PIAZO BUZZER

        int     c_socket, s_socket;
        struct  sockaddr_in s_addr, c_addr;
        int     len;
        int     nfds = 0;
        int     i, j, n;
        fd_set  read_fds;
    int    res;

        if (argc < 2) {
                printf("usage: %s port_number\n", argv[0]);
                exit(-1);
        }

    if (pthread_mutex_init(&mutex, NULL) != 0) {
        printf("Can not create mutex\n");
        return -1;
    }

        s_socket = socket(PF_INET, SOCK_STREAM, 0);

        memset(&s_addr, 0, sizeof(s_addr));
        s_addr.sin_addr.s_addr = htonl(INADDR_ANY);
        s_addr.sin_family = AF_INET;
        s_addr.sin_port = htons(atoi(argv[1]));

        if (bind(s_socket, (struct sockaddr *)&s_addr, sizeof(s_addr)) == -1) {
                printf("Can not Bind\n");
                return -1;
        }

        if(listen(s_socket, MAX_CLIENT) == -1) {
                printf("listen Fail\n");
                return -1;
        }

 //chatting server is ready blue light on
 //digitalWrite(5, 1);
 //delay(30000);
 //digitalWrite(5, 0);
 

        pthread_create(&thread, NULL, do_blueLed, NULL);


    for (i = 0; i < MAX_CLIENT; i++)
        list_c[i].clientsocket = INVALID_SOCK;

    while(1) {
        len = sizeof(c_addr);
        c_socket = accept(s_socket, (struct sockaddr *)&c_addr, &len);

 
 // user logged on !! yellow light on
 //digitalWrite(4,1);
 //delay(5000);
 //digitalWrite(4,0);

        pthread_create(&thread, NULL, do_yellowLed, NULL);


        res = pushClient(c_socket);
        if (res < 0) {
            write(c_socket, CODE200, strlen(CODE200));
            close(c_socket);
        } else {
            write(c_socket, greeting, strlen(greeting));
            pthread_create(&thread, NULL, do_chat, (void *) c_socket);
        }   
    }
}

 

void *
do_chat(void *arg)
{
    int c_socket = (int) arg;
    char    chatData[CHATDATA];
    int    i, n, j, k, l, s, rcv, helpi, whoi, checki;
    int checknum, start, checkI;
    char *checkPoint;    
    int idCheck=0;

    char temp[MAX_NAME]; // chatData COPY
    char temp1[MAX_NAME]; // 받는 사람
    char temp2[MAX_NAME]; // 보낼 메시지
    char sendid[MAX_NAME]; // 보내는 사람 아이디
    char sendtemp[13] = {"'s send -> "};
    char send[MAX_NAME]; // 보내는 메시지 + 보내는 사람
    char forhelp[MAX_NAME]; // help를 위한 복사본
    char helpid[MAX_NAME]; // HELP 받을 ID   
    char help[400] = {"귓속말 : sendto 보낼닉네임 보낼내용\n금지어 : kill, sibal, gese, 18, ssibal, fuck, fucking, lol, shut, hell 입력 시 * 표시\n도움말 : /help\n접속명단 확인 : /Who\n채팅방 종료시 : exit\n"}; // help 설명문 작성
    char forwho[MAX_NAME]; // who를 위한 복사본
    char whoid[MAX_NAME]; // who 받을 id  
    char who[MAX_NAME]; // who 출력문 작성
    char line[MAX_NAME] = {"\n"}; // 줄바꿈 위한
    char whotext[MAX_NAME] = {"-- 접속 명단 --\n"}; // 접속명단 출력위한
    char checkChat[MAX_NAME]; // checkChat 위해 저장
    char forcheck[MAX_NAME]; // check를 위한 복사본
    char checkid[MAX_NAME]; // checkChat 받을 id
    char *token;
   

    while(1) {
        memset(chatData, 0, sizeof(chatData));
             if ((n = read(c_socket, chatData, sizeof(chatData))) > 0 ) {


  // filtering test! red light on, bujjer on
  // strstr(chatData, badworkds)
  // change badworkds -> ****

                    strcpy(temp,chatData); // ChatData를 temp에 카피 저장
      strcpy(forhelp, chatData); //help를 위해 카피 저장
      strcpy(forwho, chatData);  // who를 위해 카피 저장
      strcpy(forcheck, chatData); // chckChat 위해 카피 저장

      token = strtok(forcheck, "[]"); // 욕설 하는사람 소켓번호 찾기
             strcpy(checkid, token);
      for(s=0; s<usercnt; s++){
  if(strcmp(list_c[s].name, checkid)== 0){
   checki = s;
  }
             }
 
      for(checknum=0 ; checknum<10; checknum++){ // 욕설 문자열 비교
                idCheck += checkword(chatData,word[checknum]);
             }
             if(idCheck !=0){  // 욕설 카운트
               
  //digitalWrite(1, 1);
  //delay(5000);
  //digitalWrite(1, 0);
          pthread_create(&thread, NULL, do_redLed, NULL);
  pthread_create(&thread, NULL, do_buzzer, NULL);

  list_c[checki].checkcnt += 1;
                printf("%s - %d회 욕설\n",list_c[checki].name,list_c[checki].checkcnt);
             }
             idCheck =0;
           

          //  sendto 받는사람 보내는내용
      if(strstr(temp, "sendto") != NULL){ // 문자열 중에 sendto 있으면 귓속말로 간다
         //chatData [%s] : 내가 입력한 문자열로 들어옴
  token= strtok(temp, " ");  // [%s] 문자열 버림
  strcpy(sendid, token);
  token= strtok(NULL, " ");  // : 문자열 버림
  token=strtok(NULL, " ");   // sendto 문자열 버림
             token= strtok(NULL, " ");  // 2번째 문자열(받는 사람)
             strcpy(temp1, token);  // 받는 사람=문자열 -> temp1 저장
             token= strtok(NULL, " ");  // 3번째 문자열(보낼 메시지)
             strcpy(temp2,token);  // 보낼 메시지=문자열 -> temp2 저장
      

         for(j=0; j<usercnt; j++){  // 해당 유저이름 있으면 그 유저번호 찾음
                 if(strcmp(list_c[j].name, temp1) == 0 ){
                     rcv = j;
                  }
             } 
      strcat(sendid, sendtemp);
     strcat(sendid, temp2);
       strcpy(send, sendid); 
 
               // 그 유저이름의 클라이언트 소켓에 보낼 메시지 보냄
                  write(list_c[rcv].clientsocket, send, sizeof(send));
     }
    else if(strstr(forhelp, "/help") != NULL){ // /help -> 해당 소켓 설명문 출력
  token = strtok(forhelp, "[]");
  strcpy(helpid, token);
  for(k=0; k<usercnt; k++){
   if(strcmp(list_c[k].name, helpid) == 0){
    helpi = k;
   }
  }
  write(list_c[helpi].clientsocket, help, sizeof(help));
           }
    else if(strstr(forwho, "/who") != NULL){ // /who -> 해당 소켓 리스트 출력
  token = strtok(forwho, "[]");
  strcpy(whoid, token);
  for(l=0; l<usercnt; l++){
   if(strcmp(list_c[l].name, whoid) == 0){
    whoi = l;
   }
  }
  strcat(who, whotext);
         for(l=0; l<usercnt; l++){
   strcat(who, list_c[l].name);
   strcat(who, line);
  }
  write(list_c[whoi].clientsocket, who, sizeof(who));
     }
   

            // 귓속말 안하면 소켓번호 생성되있으면 소켓에 해당 채팅 보내라
            // escape(exit)라면 pop해라 client를
            else {
       for (i = 0; i < MAX_CLIENT; i++) {
  if (list_c[i].clientsocket != INVALID_SOCK) {
   write(list_c[i].clientsocket, chatData, n);
                 }
         if(strstr(chatData, escape) != NULL){                     
   popClient(c_socket);
                 break;
                }
              }
            }
     }
    } 
}

 

int
pushClient(int c_socket) {
    int    i, n;   
    char    chatData[CHATDATA];

    char tmp[MAX_NAME]; // 닉네임 저장 위한
    char tokensep1[] = "[]";
    char *token;

 // 유저 닉네임들 배열에 넣기
    if(( n = read(c_socket, chatData, sizeof(chatData))) > 0 ){
         token = strtok(chatData, tokensep1);
     strcpy(list_c[usercnt].name, token);
  list_c[usercnt].checkcnt=0;
     usercnt++;
    }   

 // -1로 초기화했고 들어오면 c_socket번호 넣어준다 (위에서 소켓번호 정상출력 4부터)
    for (i = 0; i < MAX_CLIENT; i++) {
 read(c_socket, chatData, sizeof(chatData));
 token = strtok(chatData, tokensep1);

        pthread_mutex_lock(&mutex);
        if(list_c[i].clientsocket == INVALID_SOCK) {
            list_c[i].clientsocket = c_socket;
     strcpy(list_c[i].name, token);
            pthread_mutex_unlock(&mutex);
            return i;
        }   
        pthread_mutex_unlock(&mutex);
    }
        return -1;
}

 

int
popClient(int s)
{
        int     i;

        close(s);

        for (i = 0; i < MAX_CLIENT; i++) {
        pthread_mutex_lock(&mutex);
                if ( s == list_c[i].clientsocket ) {
            list_c[i].clientsocket = INVALID_SOCK;
            pthread_mutex_unlock(&mutex);
            break;
        }
        pthread_mutex_unlock(&mutex);
        }

        return 0;
}
 
int checkword(char *word, const char *find){ // 욕설 찾아서 그 부분만큼 *
    int cnt, find_size;
    char *pos;
    int cnt2= 0;
    find_size = strlen(find);
    while((pos = strstr(word,find))!=NULL)
    {
        for(cnt = 0; cnt<find_size; cnt++){
            *(word + (strlen(word)-strlen(pos))+cnt) = '*';
           
        }
        cnt2 += 1;        
    }
    return cnt2;
}
 
void* do_redLed(){
 digitalWrite(1, 1);
 delay(4000);
 digitalWrite(1, 0);

}

void* do_yellowLed(){
 digitalWrite(4, 1);
 delay(10000);
 digitalWrite(4, 0);
}

void* do_blueLed(){
 digitalWrite(5, 1);
 delay(100000);
 digitalWrite(5, 0);
}

void* do_buzzer(){
 digitalWrite(6, 1);
 delay(4000);
 digitalWrite(6, 0);
}

 

 

 

'소켓네트워크' 카테고리의 다른 글

[소켓네트워크] - 채팅 클라이언트 MFC용  (0) 2017.06.02
[소켓네트워크] - 채팅 클라이언트 안드로이드용  (0) 2017.06.02
[소켓네트워크] - strtok 이용한 문자열 분리  (0) 2017.05.05
[소켓네트워크] - 일반 소켓 vs RAW 소켓  (0) 2017.04.21
[소켓네트워크] - Can not Bind 처리방법  (0) 2017.04.21

댓글()
카테고리
  • IT (593)
    • 정리 (0)
    • C# (42)
    • ASP.NET MVC (16)
    • JQuery&Javascript (12)
    • CSS (11)
    • 데이터베이스 (32)
    • Windows Server (6)
    • Active Directory (3)
    • Exchange (9)
    • JAVA (2)
    • JSP (39)
    • JSP 게시판 만들기 (21)
    • JSP 개발 참고 (15)
    • JSP 안드로이드 (4)
    • Servlet (17)
    • Spring (42)
    • HTML (14)
    • NodeJS (46)
    • MongoDB (11)
    • 리눅스 (18)
    • 자료구조 (16)
    • 아이폰 (24)
    • 안드로이드 (68)
    • API 활용하기 (10)
    • 소켓네트워크 (28)
    • 라즈베리파이 (11)
    • AWS클라우드 (10)
    • 빅데이터Hadoop (22)
    • 커널모듈프로그래밍 (8)
    • 기타 (10)
    • 자격증 (26)
최근 등록 현황
최근 글
최근 월별 글
최근 댓글
최근 글
최근 월별 글
최근 댓글
최근 글
최근 월별 글
최근 댓글
달력
지난달
2025.6
다음달
일월화수목금토
1234567
891011121314
15161718192021
22232425262728
2930
태그 구름
  • 정보처리기사 실기 정리
  • nodejs MySQL 연동하기(Connection Pool)
  • 데이터베이스
  • 정보처리산업기사 요약
  • 정보처리산업기사 총정리
  • 리눅스
  • 카카오 로그인
  • 정보처리산업기사 16년
  • 안드로이드
  • 커널 모듈 프로그래밍
  • 이클립스 디비 연동
  • 정규형
  • 이클립스 mysql 연동
  • 안드로이드 intent
  • 정보처리산업기사 필기
  • jsp
  • 정규화
  • 정보처리산업기사 정리
  • 소켓
  • 안드로이드 카카오 로그인 연동
  • HTML
  • 정보처리산업기사 필기 정리
  • 정보처리산업기사 15년 필기
  • 안드로이드 카카오 로그인
  • 카카오 로그인 연동
  • 자료구조
  • 소켓 프로그래밍
  • 정보처리산업기사 15년
  • nodejs express
  • 정보처리산업기사 16년 필기
카운터
전체 방문자
오늘
어제
Skin by M1REACT. Designed by M1STORY.TISTORY.COM. Valid XHTML 1.0 and CSS 3. Copyright ⓒ Riucc's Storage. All rights reserved.

티스토리툴바