본문 바로가기

지식/Network

libevent 윈도우 예제


#include<sys/types.h>
#include<winsock2.h>

//#include<netinet/in.h> // for unix
#include<windows.h>

//#include<arpa/inet.h> // for unix

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
//#include<unistd.h> // for unix
#include<fcntl.h>
#include<errno.h>

#include<event.h>

#define SERV_PORT   8888

struct client
{
 struct event ev_read;
};

int setnonblock(int fd)
{
 /* // for unix
 int flags;
 flags = fcntl(fd, F_GETFL);

 if(flags < 0)
 {
  return flags;
 }
 flags |= O_NONBLOCK;
 if(fcntl(fd, F_SETFL, flags) < 0)
 {
  return -1;
 }
 */
 
 // for windows
 u_long on = 1;
 ioctlsocket(fd, FIONBIO, &on);
 return 0;
}

void read_cb(int fd, short event, void *arg)
{
 printf("read cb\n");
 struct client *client = (struct client *)arg;
 //u_char buf[8196];
 char buf[8196];
 int len, wlen;

 memset(buf,0,8196);
 len = recv(fd, buf, sizeof(buf),0);

 if(len == 0)
 {
  printf("client disconnected\n");
  closesocket(fd);
  event_del(&client->ev_read);
  free(client);
 }
 else if(len < 0)
 {
  printf("Socket failure, disconnecting client \n");
  closesocket(fd);
  event_del(&client->ev_read);
  free(client);
 }
 else
 {
  printf("recv %d : %s\n",len,buf);
 
 wlen = send(fd, buf, len,0);
 if(wlen < len)
 {
  printf("Short write, not all data echoed back to client\n");
 }

}

void accept_cb(int fd, short event, void *arg)
{
 printf("accept cb\n");
 int client_fd;
 struct sockaddr_in client_addr;
 int client_len = sizeof(client_addr);
 struct client *client;
 client_fd = accept(fd, (struct sockaddr *)&client_addr,
  &client_len);
 if(client_fd == -1)
 {
  return;
 }
 if(setnonblock(client_fd) < 0)
 {
 }
 client = (struct client*)calloc(1, sizeof(*client));
 if(client == NULL)
 {
  //err(1, "malloc failed");
 }
 event_set(&client->ev_read,
  client_fd, EV_READ | EV_PERSIST ,
  read_cb, client);
 event_add(&client->ev_read, NULL);
 printf("Accepted connection from %s\n",
  inet_ntoa(client_addr.sin_addr));
}

int main(int argc, char **argv)
{

 WSADATA data;
 int sock;
 struct sockaddr_in sa;
 struct event ev;
 int reuseaddr_on = 1;

 WSAStartup(MAKEWORD(2,2), &data);

 sock = socket(AF_INET, SOCK_STREAM, 0);
 if (sock==-1)
 {
  fprintf(stderr, "소켓 생성 오류\n");
  return 0;
 }
 event_init();

 memset(&sa, 0x00, sizeof(sa));
 sa.sin_family = AF_INET;
 sa.sin_addr.s_addr = INADDR_ANY;
 sa.sin_port = htons(SERV_PORT);
 
 if(setsockopt(sock,
  SOL_SOCKET,
  SO_REUSEADDR,
  (char*)&reuseaddr_on,
  sizeof(reuseaddr_on)) == -1)
 {
  printf("setsockopt error\n");
 }
 
 if ( -1 == bind(sock, (struct sockaddr*)&sa, sizeof(sa)) )
 {
  printf("소켓 바인드 오류\n");
  return 0;
 }

 if ( -1 == listen(sock, 15) )
 {
  printf("소켓 리슨 오류\n");
  return 0;
 }


 if(setnonblock(sock) < 0)
 {
  printf("set nonblocking error\n");
 }
 
 event_set(&ev,
  sock,
  EV_READ | EV_PERSIST,
  accept_cb, NULL);
 event_add(&ev, NULL);

 event_dispatch();

 return 0;
}

telnet으로 테스트했더니 잘 돌아간다...

어쨋든 참 생소한 방식이다..편하기도 하고..
이제 서버를 만들어야하는데...
이걸가기고 class를 만들까 그냥 C로 만들까..고민이다..
C++해본지도 오래됐는데.. class를 잘 만들수있을런지..
이번기회에 class로 잘 구성해 놓으면 두고두고 평생 잘 우려 먹을꺼같은데 ㅎㅎㅎㅎㅎ