본문 바로가기

지식/Network

LibEvent For Windows Bug..

사용자 삽입 이미지



아래 예제 코드는 간단한 에코 서버다.
스트레스 툴을 만들어서 십여개의 connexction을 생성한 후 일괄 close하면
메모리에러가 발생하면서 프로그램이 종료된다.
원인은 이벤트 구조체가 잘못된듯한다..

free부분을 제거하면 이러한 에러가 사라지기는 하지만 어떻게 그럴수가 있는가 -_-;;
결국 일주일간의 노력은 모두 물거품이 되어버렸다.

일단 멀티 스레드 서버로 프로젝트는 후다닥 진행해야겠다..



struct client {
 struct event ev_read;
 struct event ev_write;
 int id;
};



int  main(int argc, char **argv)
{
 nametag = 0;
 timer = 0;
 Initialize();
 Initialize_Net();

 event_init();
 event_priority_init(1); 
 memset(&ev_accept,0,sizeof(ev_accept));

 event_set(&ev_accept, listen_sock, EV_READ | EV_PERSIST, on_accept, NULL);
 event_add(&ev_accept, NULL);
 StartQueryService();

 event_dispatch();
 WSACleanup();
 return 0;
}

void on_accept(int fd, short ev, void *arg)
{
 int client_fd;
 struct sockaddr_in client_addr;
 int client_len = sizeof(client_addr);
 struct client *client;

 /* Accept the new connection. */
 client_fd = accept(fd, (struct sockaddr *)&client_addr, &client_len);
 if (client_fd == -1) {
  printf("accept failed");
  return;
 }

 if (setnonblock(client_fd) < 0)
  printf("failed to set client socket non-blocking");

 client = (struct client *)calloc(1, sizeof(struct client));

 client->id = i_client;
 i_client++;

 event_set(&client->ev_read, client_fd, EV_READ|EV_PERSIST, on_read, client);
 event_add(&client->ev_read, NULL);

 /* Create the write event, but don’t add it until we have
 * something to write. */
 event_set(&client->ev_write, client_fd, EV_WRITE, on_write, client);

 /* Initialize the clients write queue. */
 printf("Accepted connection from %s\n",
  inet_ntoa(client_addr.sin_addr));
}


void on_write(int fd, short ev, void *arg)
{
 struct client *client = (struct client *)arg;
 struct bufferq *bufferq;
 int len;
 
 char buf[DEFAULT_RECV_LEN];

 len = send(fd,buf,DEFAULT_RECV_LEN,0);
 if (len == -1) {
  if (errno == EINTR || errno == EAGAIN) {
   event_add(&client->ev_write, NULL);
   return;
  }
  else {
   printf("send error\n");
  }
 }
 
 printf("%d: %d byte send\n",client->id,len);


}


/**
* This function will be called by libevent when the client socket is
* ready for reading.
*/
void on_read(int fd, short ev, void *arg)
{
 struct client *client = (struct client *)arg;
 struct bufferq *bufferq;
 char buf[DEFAULT_RECV_LEN];
 int len;

 len = recv(fd, buf, DEFAULT_RECV_LEN,0);

 if (len == 0) // disconnected
 {

  printf("%d Client disconnected.\n",client->id);
  closesocket(fd);
  if (event_initialized(&client->ev_read))
  {
   if(event_del(&client->ev_read) == 0)
   {
    free(client);
    client = NULL;
   }
   else
    printf("event delete failed\n");
  } 
  return;
 }
 
 else if (len < 0) // socket error :
 {
  printf("%d Socket failure, wsagetlasterror:%d \n",client->id,WSAGetLastError() );
  closesocket(fd);
 
  if (event_initialized(&client->ev_read))
  {
   if(event_del(&client->ev_read) == 0)
   {
    free(client);
    client = NULL;
   }
   else
    printf("event delete failed\n");
  }
 
  return;
 }
 printf("%d: %d byte recv\n",client->id,len);

 event_add(&client->ev_write, NULL);
}