유닉스상에서 실행하였습니다.
1.chat_server.c
/*----------------------------------------------------------------------------------------------
파일명 : chat_server.c
기 능 : 채팅 참가자 관리, 채팅 메시지 수신 및 방송
컴파일 : gcc -o chat_server chat_server.c readline.c -lsocket -lnsl
실행예 : chat_server 6546
-----------------------------------------------------------------------------------------------*/
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <netinet/in.h>
#define MAXLINE 1024
#define MAX_SOCK 512
char *escapechar = "exit\n";
int readline(int, char *, int);
int main(int argc, char *argv[]) {
char rline[MAXLINE], my_msg[MAXLINE];
char *start = "대화방에 오신걸 환영합니다...\n";
int i, j, n;
int s, client_fd, clilen;
int nfds; /* 최대 소켓번호 +1 */
fd_set read_fds; /* 읽기를 감지할 소켓번호 구조체 */
int num_chat = 0; /* 채팅 참가자 수 */
/* 채팅에 참가하는 클라이언트들의 소켓번호 리스트 */
int client_s[MAX_SOCK];
struct sockaddr_in client_addr, server_addr;
if (argc < 2) {
printf("실행방법 :%s 포트번호\n",argv[0]);
return -1;
}
printf("대화방 서버 초기화 중....\n");
/* 초기소켓 생성 */
if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
printf("Server: Can't open stream socket.");
return -1;
}
/* server_addr 구조체의 내용 세팅 */
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(s,(struct sockaddr *)&server_addr,sizeof(server_addr)) < 0) {
printf("Server: Can't bind local address.\n");
return -1;
}
/* 클라이언트로부터 연결요청을 기다림 */
listen(s, 5);
nfds = s + 1; /* 최대 소켓번호 +1 */
FD_ZERO(&read_fds);
while(1) {
/* (최대 소켓번호 +1) 값을 갱신 */
if ((num_chat-1) >= 0) nfds = client_s[num_chat-1] + 1;
/* 읽기 변화를 감지할 소켓번호를 fd_set 구조체에 지정 */
FD_SET(s, &read_fds);
for (i=0; i<num_chat; i++) FD_SET(client_s[i], &read_fds);
/*---------------------------------- select() 호출 ------------------------------------- */
if (select(nfds, &read_fds, (fd_set *)0, (fd_set *)0,(struct timeval *)0) < 0) {
printf("select error\n");
return -1;
}
/*-------------------------- 클라이언트 연결요청 처리 --------------------------- */
if (FD_ISSET(s, &read_fds)) {
clilen = sizeof(client_addr);
client_fd = accept(s, (struct sockaddr *)&client_addr, &clilen);
if (client_fd != -1) {
/* 채팅 클라이언트 목록에 추가 */
client_s[num_chat] = client_fd;
num_chat++;
send(client_fd, start, strlen(start), 0);
printf("%d 번째 사용자 추가.\n",num_chat);
}
}
/*- 임의의 클라이언트가 보낸 메시지를 모든 클라이언트에게 방송 - */
for (i = 0; i < num_chat; i++) {
if (FD_ISSET(client_s[i], &read_fds)) {
if ((n = recv(client_s[i], rline, MAXLINE,0)) > 0) {
rline[n] = '\0';
/* 종료문자 입력시 채팅 탈퇴 처리 */
if (exitCheck(rline, escapechar, 5) == 1) {
shutdown(client_s[i], 2);
if(i != num_chat-1) client_s[i] = client_s[num_chat-1];
num_chat--;
continue;
}
/* 모든 채팅 참가자에게 메시지 방송 */
for (j = 0; j < num_chat; j++) send(client_s[j], rline, n, 0);
printf("%s", rline);
}
}
}
}
}
/* ------------------------------- 종료문자 확인 함수 ----------------------------
exitCheck()는 다음의 세 개의 인자를 필요로 한다
rline: 클라이언트가 전송한 문자열 포인터
escapechar: 종료문자 포인터
len: 종료문자의 크기
---------------------------------------------------------------------------------------------*/
int exitCheck(rline, escapechar, len)
char *rline; /* 클라이언트가 전송한 메시지 */
char *escapechar; /* 종료문자 */
int len;
{
int i, max;
char *tmp;
max = strlen(rline);
tmp = rline;
for(i = 0; i<max; i++) {
if (*tmp == escapechar[0]) {
if(strncmp(tmp, escapechar, len) == 0)
return 1;
} else
tmp++;
}
return -1;
}
컴파일 하시는 방법은
gcc -o 사용할이름(보통 .c파일과 같은 이름) chat_server.c... 아래에 재정리
gcc -o chat_server chat_server.c readline.c -lsocket -lnsl
오류가 없으면 chat_server가 생성됩니다.
readline.c
int readline(int fd, char *ptr, int maxlen) {
int n, rc;
char c;
for(n = 1; n < maxlen; n++) {
if((rc = read(fd, &c, 1)) == 1) {
*ptr++ = c;
if (c == '\n') break;
} else if (rc == 0) {
if(n == 1) return (0);
else break;
}
}
*ptr = 0;
return (n);
}
초기 대기 상태가 되었습니다.
/*-----------------------------------------------------------------------------------------
파일명 : chat_client.c
기 능 : 서버에 접속한 후 키보드의 입력을 서버에 전달하고,
서버로부터 오는 메시지를 화면에 출력한다.
컴파일 : cc -o chat_client chat_client.c readline.c -lsocket -lnsl
실행예 : chat_client 203.246.1.xxx 6546 사용자_ID
-------------------------------------------------------------------------------------------*/
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/time.h>
#define MAXLINE 1024
#define MAX_SOCK 512
char *escapechar = "exit\n";
int readline(int, char *, int);
int s; /* 서버와 연결된 소켓번호 */
struct Name {
char n[20]; /* 대화방에서 사용할 이름 */
int len; /* 이름의 크기 */
} name;
int main(int argc, char *argv[]) {
char line[MAXLINE], sendline[MAXLINE+1];
int n, pid, size;
struct sockaddr_in server_addr;
int nfds;
fd_set read_fds;
if( argc < 4 ) {
printf("실행방법 : %s 호스트 IP 주소 포트번호 사용자이름 \n", argv[0]);
return -1;
}
/* 채팅 참가자 이름 구조체 초기화 */
sprintf(name.n, "[%s]", argv[3]);
name.len = strlen(name.n);
/* 소켓 생성 */
if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
printf("Client : Can't open stream socket.\n");
return -1;
}
/* 채팅 서버의 소켓주소 구조체 server_addr 초기화 */
bzero((char *)&server_addr, 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]));
/* 연결요청 */
if(connect(s, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
printf("Client : Can't connect to server.\n");
return -1;
} else {
printf("접속에 성공했습니다..\n");
}
nfds = s + 1;
FD_ZERO(&read_fds);
while(1) {
/* -------------------------------------- selelct() 호출 ---------------------------------------*/
FD_SET(0, &read_fds);
FD_SET(s, &read_fds);
if(select(nfds, &read_fds, (fd_set *)0, (fd_set *)0, (struct timeval *)0) < 0) {
printf("select error\n");
return -1;
}
/*------------------------- 서버로부터 수신한 메시지 처리 -------------------------*/
if (FD_ISSET(s, &read_fds)) {
char recvline[MAXLINE];
int size;
if ((size = recv(s, recvline, MAXLINE, 0)) > 0) {
recvline[size] = '\0';
printf("%s \n", recvline);
}
}
/* --------------------------------- 키보드 입력 처리 ----------------------------------*/
if (FD_ISSET(0, &read_fds)) {
if (readline(0, sendline, MAXLINE) > 0) {
size = strlen(sendline);
sprintf(line, "%s %s", name.n, sendline);
if (send(s, line, size + name.len, 0) != (size+name.len))
printf("Error : Written error on socket.\n");
if (size == 5 && strncmp(sendline, escapechar, 5) == 0) {
printf("Good bye.\n");
close(s);
return -1;
}
}
} /* end of 키보드 입력 처리 */
} /* end of while() */
}
설레는 마음으로 채팅하러 꼬꼬고~
접속 방법은,
chat_client [ip주소] [port] [채팅이름명]
정상적으로 접속하시면
위와 같이 나오겠죠??
'전공' 카테고리의 다른 글
[IT/Programming] 소켓프로그래밍을 이용한 숫자 야구 게임 만들기 (4) | 2011.12.01 |
---|---|
[IT] 유럽의 미래인터넷과 연구 동향 (0) | 2011.11.30 |
[IT] Q 함수 (Q-Function) (0) | 2011.10.11 |
[IT] 셀룰러 시스템의 기초 (0) | 2011.10.10 |
[IT] 가우시안 노이즈 (Gaussian Noise) & 백색잡음 (0) | 2011.10.10 |