poll을 이용한 채팅서버
OS/리눅스 & 유닉스 2012. 5. 24. 18:38#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/poll.h> //poll
#include <errno.h> //errno
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h> //socket
#include <netinet/in.h> //sockaddr
#include <netdb.h> //hostent
#define PORT 8001
#define BUFFSIZE 1024 // 송수신을 위한 버퍼크기
#define MAXPOLL 128 // pollfd의 최대 크기
// tcp server
int main() {
struct pollfd polls[MAXPOLL]; // pollfd 배열
int count=0;
char buff[BUFFSIZE];
int yes=1;
int i, poll_result;
int server_socket, client_socket;
struct sockaddr_in server_addr, client_addr;
int server_addrlen=sizeof(server_addr); //서버소켓주소의 길이
int client_addrlen=sizeof(client_addr); //클라이언트 소켓주소의 길이
// 인터넷 도메인 TCP 서버 소켓 생성
if ( (server_socket=socket(AF_INET,SOCK_STREAM,0)) < 0 ) {
perror("socket");
exit(1);
}
// 서버 포트번호를 재사용 할 수 있도록 소켓 옵션 설정
if ( setsockopt(server_socket, //socket
SOL_SOCKET, // level
SO_REUSEADDR, // option
&yes, //option value
sizeof(int)) < 0 ) { // option length
perror("setsockopt");
exit(9);
}
//서버의 소켓주소를 생성
bzero((void *)&server_addr,sizeof(server_addr));
server_addr.sin_family=AF_INET;
server_addr.sin_addr.s_addr=INADDR_ANY;
server_addr.sin_port=htons(PORT);
//소켓과 서버주소 연결 bind()
if ( bind(server_socket,(struct sockaddr *)&server_addr,
sizeof(server_addr)) < 0) {
perror("bind");
exit(2);
}
//커널에 포트 알림 listen()
if ( listen(server_socket,5) < 0 ) {
perror("listen");
exit(3);
}
printf("서버가 시작됨: %d\n",PORT);
// 서버 소켓에 대한 이벤트 등록
polls[0].fd=server_socket;
polls[0].events=POLLIN;
count++; // 등록된 소켓의 수
// 서버소켓을 제외한 나머지 pollfd의 디스크립트 값을 -1 로 설정하여 할당되지 않음을 표시
for(i=1;i<MAXPOLL;i++) polls[i].fd=-1;
// 클라이언트 연결을 처리하기 위해 대기중
while (1) {
poll_result=poll(polls,count,1000);
if (poll_result == 0 ) continue; // 타임아웃에 걸린 경우 다시 while loop를 테스트하도록 한다.
if (polls[0].revents & POLLIN) { //서버소켓에 이벤트가 발생한 경우
bzero((void *)&client_addr,sizeof(client_addr));
if ( (client_socket= accept(server_socket,
(struct sockaddr *)&client_addr,&client_addrlen)) < 0) {
perror("accept");
exit(4);
}
printf("클라이언트가 접속됨:\n");
printf("IP: %s PORT: %d\n",inet_ntoa(client_addr.sin_addr),
ntohs(client_addr.sin_port));
polls[count].fd=client_socket; // 새로 연결된 클라이언트 소켓을 pollfd에 등록하여 이벤트를 감시하도록 한다.
polls[count].events = POLLIN;
count++;
continue;
} else { //클라이언트 소켓에서 이벤트가 발생한 경우
for(i=1;i<count;i++) {
if ( polls[i].revents & POLLIN ) {
//클라이언트가 전송한 메시지를 buff에 수신함
bzero(buff,sizeof(buff));
if ( recv(polls[i].fd, buff,sizeof(buff),0) < 0 ) {
perror("recv");
break;
}else
printf("[%d]수신 %s",polls[i].fd, buff);
//클라이언트가 종료를 요청하면 소켓을 닫아주고
//pollfd에서 삭제해준다.
if ( bcmp(buff,"exit",4) == 0 ) {
close(polls[i].fd);
polls[i].fd=-1;
// polls이사를 시키세요
break;
}
//클라이언트에게 수신된 메시지 echo
if ( send(polls[i].fd,buff,strlen(buff),0) < 0) {
perror("send");
break;
}else
printf("[%d]송신 %s",polls[i].fd, buff);
}//if
}//for
}//else
}//while
close(polls[0].fd);
exit(0);
}
'OS > 리눅스 & 유닉스' 카테고리의 다른 글
ibm aix polling (0) | 2012.05.31 |
---|---|
공유 메모리 (shared memory) (0) | 2012.05.29 |
AIX 32bit/64bit 컴파일 (0) | 2012.05.23 |
Compiler 옵션 (0) | 2012.05.23 |
gcc 옵션 [출처] gcc 옵션 간단 정리|작성자 열이 (0) | 2012.05.23 |