kqueue를 이용한 예제임.
내가 필요한 소스 이긴 한데..
이번엔 잘 돌아갈려나..ㅠㅠ
아무튼 참조 하고,, 공부 하자 아자아자..!!
/* echo.c - Simple `echo' server for N clients written using kqueue/kevent. */
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/event.h>
#include <sys/time.h>
typedef struct in_addr in_addr;
typedef struct sockaddr_in sockaddr_in;
typedef struct servent servent;
typedef struct timespec timespec;
typedef void (action) (register struct kevent const *const kep); /* Event Control Block (ecb) */
typedef struct
{
action *do_read;
action *do_write;
char *buf; unsigned bufsiz;
} ecb;
static char const *pname;
static struct kevent *ke_vec = NULL;
static unsigned ke_vec_alloc = 0;
static unsigned ke_vec_used = 0;
static char const protoname[] = "tcp";
static char const servname[] = "echo";
static void vlog (char const *const fmt, va_list ap)
{
vfprintf (stderr, fmt, ap);
fputc ('\n', stderr);
}
static void fatal (char const *const fmt, ...) __attribute__ ((__noreturn__));
static void fatal (char const *const fmt, ...)
{
va_list ap;
va_start (ap, fmt);
fprintf (stderr, "%s: ", pname);
vlog (fmt, ap);
va_end (ap); exit (1);
}
static void error (char const *const fmt, ...)
{
va_list ap;
va_start (ap, fmt);
fprintf (stderr, "%s: ", pname);
vlog (fmt, ap);
va_end (ap);
}
static void usage (void)
{
fatal(char const * const fmt,...) ("Usage `%s [-p port]'", pname);
}
static int all_digits (register char const *const s)
{
register char const *r;
for (r = s; *r; r++)
if (!isdigit (*r))
return 0;
return 1;
}
static void * xmalloc (register unsigned long const size)
{
register void *const result = malloc (size);
if (!result)
fatal ("Memory exhausted");
return result;
}
static void * xrealloc (register void *const ptr, register unsigned long const size)
{
register void *const result = realloc (ptr, size);
if (!result)
fatal ("Memory exhausted");
return result;
}
static void ke_change (register int const ident, register int const filter, register int const flags, register void *const udata)
{
enum
{
initial_alloc = 64
};
register struct kevent *kep;
if (!ke_vec_alloc)
{
ke_vec_alloc = initial_alloc;
ke_vec = (struct kevent *) xmalloc(ke_vec_alloc * sizeof (struct kevent));
}
else if (ke_vec_used == ke_vec_alloc)
{
ke_vec_alloc <<= 1;
ke_vec = (struct kevent *) xrealloc (ke_vec, ke_vec_alloc * sizeof (struct kevent));
}
kep = &ke_vec[ke_vec_used++];
kep->ident = ident;
kep->filter = filter;
kep->flags = flags;
kep->fflags = 0;
kep->data = 0;
kep->udata = udata;
}
static void do_write (register struct kevent const *const kep)
{
register int n;
register ecb *const ecbp = (ecb *) kep->udata;
n = write (kep->ident, ecbp->buf, ecbp->bufsiz);
free (ecbp->buf); /* Free this buffer, no matter what. */
if (n == -1)
{
error ("Error writing socket: %s", strerror (errno));
close (kep->ident);
free (kep->udata);
}
ke_change (kep->ident, EVFILT_WRITE, EV_DISABLE, kep->udata);
ke_change (kep->ident, EVFILT_READ, EV_ENABLE, kep->udata);
}
static void do_read (register struct kevent const *const kep)
{
enum
{
bufsize = 1024
};
auto char buf[bufsize];
register int n;
register ecb *const ecbp = (ecb *) kep->udata;
if ((n = read (kep->ident, buf, bufsize)) == -1)
{
error ("Error reading socket: %s", strerror (errno));
close (kep->ident);
free (kep->udata);
}
else if (n == 0)
{
error ("EOF reading socket");
close (kep->ident);
free (kep->udata);
}
ecbp->buf = (char *) xmalloc (n);
ecbp->bufsiz = n;
memcpy (ecbp->buf, buf, n);
ke_change (kep->ident, EVFILT_READ, EV_DISABLE, kep->udata);
ke_change (kep->ident, EVFILT_WRITE, EV_ENABLE, kep->udata);
}
static void do_accept (register struct kevent const *const kep)
{
auto sockaddr_in sin;
auto socklen_t sinsiz;
register int s;
register ecb *ecbp;
if ((s = accept (kep->ident, (struct sockaddr *)&sin, &sinsiz)) == -1)
fatal ("Error in accept(): %s", strerror (errno));
ecbp = (ecb *) xmalloc (sizeof (ecb));
ecbp->do_read = do_read;
ecbp->do_write = do_write;
ecbp->buf = NULL;
ecbp->bufsiz = 0;
ke_change (s, EVFILT_READ, EV_ADD | EV_ENABLE, ecbp);
ke_change (s, EVFILT_WRITE, EV_ADD | EV_DISABLE, ecbp);
}
static void event_loop (register int const kq) __attribute__ ((__noreturn__));
static void event_loop (register int const kq)
{
for (;;)
{
register int n;
register struct kevent const *kep;
n = kevent (kq, ke_vec, ke_vec_used, ke_vec, ke_vec_alloc, NULL);
ke_vec_used = 0; /* Already processed all changes. */
if (n == -1)
fatal ("Error in kevent(): %s", strerror (errno));
if (n == 0) fatal ("No events received!");
for (kep = ke_vec; kep < &ke_vec[n]; kep++)
{
register ecb const *const ecbp = (ecb *) kep->udata;
if (kep->filter == EVFILT_READ)
(*ecbp->do_read) (kep);
else (*ecbp->do_write) (kep);
}
}
}
int main (register int const argc, register char *const argv[])
{
auto in_addr listen_addr;
register int optch;
auto int one = 1;
register int portno = 0;
register int option_errors = 0;
register int server_sock;
auto sockaddr_in sin;
register servent *servp;
auto ecb listen_ecb;
register int kq;
pname = strrchr (argv[0], '/');
pname = pname ? pname+1 : argv[0];
listen_addr.s_addr = htonl (INADDR_ANY); /* Default. */
while ((optch = getopt (argc, argv, "p:")) != EOF)
{
switch (optch)
{
case 'p':
if (strlen (optarg) == 0 || !all_digits (optarg))
{
error ("Invalid argument for -p option: %s", optarg);
option_errors++;
}
portno = atoi (optarg);
if (portno == 0 || portno >= (1u << 16))
{
error ("Invalid argument for -p option: %s", optarg);
option_errors++;
}
break;
default:
error ("Invalid option: -%c", optch);
option_errors++;
}
}
if (option_errors || optind != argc)
usage ();
if (portno == 0)
{
if ((servp = getservbyname (servname, protoname)) == NULL)
fatal ("Error getting port number for service `%s': %s", servname, strerror (errno));
portno = ntohs (servp->s_port);
}
if ((server_sock = socket (PF_INET, SOCK_STREAM, 0)) == -1)
fatal ("Error creating socket: %s", strerror (errno));
if (setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one) == -1)
fatal ("Error setting SO_REUSEADDR for socket: %s", strerror (errno));
memset (&sin, 0, sizeof sin); sin.sin_family = AF_INET;
sin.sin_addr = listen_addr;
sin.sin_port = htons (portno);
if (bind (server_sock, (const struct sockaddr *)&sin, sizeof sin) == -1)
fatal ("Error binding socket: %s", strerror (errno));
if (listen (server_sock, 20) == -1)
fatal ("Error listening to socket: %s", strerror (errno));
if ((kq = kqueue ()) == -1)
fatal ("Error creating kqueue: %s", strerror (errno));
listen_ecb.do_read = do_accept;
listen_ecb.do_write = NULL;
listen_ecb.buf = NULL;
listen_ecb.buf = 0;
ke_change (server_sock, EVFILT_READ, EV_ADD | EV_ENABLE, &listen_ecb);
event_loop (kq);
}
내가 필요한 소스 이긴 한데..
이번엔 잘 돌아갈려나..ㅠㅠ
아무튼 참조 하고,, 공부 하자 아자아자..!!
/* echo.c - Simple `echo' server for N clients written using kqueue/kevent. */
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/event.h>
#include <sys/time.h>
typedef struct in_addr in_addr;
typedef struct sockaddr_in sockaddr_in;
typedef struct servent servent;
typedef struct timespec timespec;
typedef void (action) (register struct kevent const *const kep); /* Event Control Block (ecb) */
typedef struct
{
action *do_read;
action *do_write;
char *buf; unsigned bufsiz;
} ecb;
static char const *pname;
static struct kevent *ke_vec = NULL;
static unsigned ke_vec_alloc = 0;
static unsigned ke_vec_used = 0;
static char const protoname[] = "tcp";
static char const servname[] = "echo";
static void vlog (char const *const fmt, va_list ap)
{
vfprintf (stderr, fmt, ap);
fputc ('\n', stderr);
}
static void fatal (char const *const fmt, ...) __attribute__ ((__noreturn__));
static void fatal (char const *const fmt, ...)
{
va_list ap;
va_start (ap, fmt);
fprintf (stderr, "%s: ", pname);
vlog (fmt, ap);
va_end (ap); exit (1);
}
static void error (char const *const fmt, ...)
{
va_list ap;
va_start (ap, fmt);
fprintf (stderr, "%s: ", pname);
vlog (fmt, ap);
va_end (ap);
}
static void usage (void)
{
fatal(char const * const fmt,...) ("Usage `%s [-p port]'", pname);
}
static int all_digits (register char const *const s)
{
register char const *r;
for (r = s; *r; r++)
if (!isdigit (*r))
return 0;
return 1;
}
static void * xmalloc (register unsigned long const size)
{
register void *const result = malloc (size);
if (!result)
fatal ("Memory exhausted");
return result;
}
static void * xrealloc (register void *const ptr, register unsigned long const size)
{
register void *const result = realloc (ptr, size);
if (!result)
fatal ("Memory exhausted");
return result;
}
static void ke_change (register int const ident, register int const filter, register int const flags, register void *const udata)
{
enum
{
initial_alloc = 64
};
register struct kevent *kep;
if (!ke_vec_alloc)
{
ke_vec_alloc = initial_alloc;
ke_vec = (struct kevent *) xmalloc(ke_vec_alloc * sizeof (struct kevent));
}
else if (ke_vec_used == ke_vec_alloc)
{
ke_vec_alloc <<= 1;
ke_vec = (struct kevent *) xrealloc (ke_vec, ke_vec_alloc * sizeof (struct kevent));
}
kep = &ke_vec[ke_vec_used++];
kep->ident = ident;
kep->filter = filter;
kep->flags = flags;
kep->fflags = 0;
kep->data = 0;
kep->udata = udata;
}
static void do_write (register struct kevent const *const kep)
{
register int n;
register ecb *const ecbp = (ecb *) kep->udata;
n = write (kep->ident, ecbp->buf, ecbp->bufsiz);
free (ecbp->buf); /* Free this buffer, no matter what. */
if (n == -1)
{
error ("Error writing socket: %s", strerror (errno));
close (kep->ident);
free (kep->udata);
}
ke_change (kep->ident, EVFILT_WRITE, EV_DISABLE, kep->udata);
ke_change (kep->ident, EVFILT_READ, EV_ENABLE, kep->udata);
}
static void do_read (register struct kevent const *const kep)
{
enum
{
bufsize = 1024
};
auto char buf[bufsize];
register int n;
register ecb *const ecbp = (ecb *) kep->udata;
if ((n = read (kep->ident, buf, bufsize)) == -1)
{
error ("Error reading socket: %s", strerror (errno));
close (kep->ident);
free (kep->udata);
}
else if (n == 0)
{
error ("EOF reading socket");
close (kep->ident);
free (kep->udata);
}
ecbp->buf = (char *) xmalloc (n);
ecbp->bufsiz = n;
memcpy (ecbp->buf, buf, n);
ke_change (kep->ident, EVFILT_READ, EV_DISABLE, kep->udata);
ke_change (kep->ident, EVFILT_WRITE, EV_ENABLE, kep->udata);
}
static void do_accept (register struct kevent const *const kep)
{
auto sockaddr_in sin;
auto socklen_t sinsiz;
register int s;
register ecb *ecbp;
if ((s = accept (kep->ident, (struct sockaddr *)&sin, &sinsiz)) == -1)
fatal ("Error in accept(): %s", strerror (errno));
ecbp = (ecb *) xmalloc (sizeof (ecb));
ecbp->do_read = do_read;
ecbp->do_write = do_write;
ecbp->buf = NULL;
ecbp->bufsiz = 0;
ke_change (s, EVFILT_READ, EV_ADD | EV_ENABLE, ecbp);
ke_change (s, EVFILT_WRITE, EV_ADD | EV_DISABLE, ecbp);
}
static void event_loop (register int const kq) __attribute__ ((__noreturn__));
static void event_loop (register int const kq)
{
for (;;)
{
register int n;
register struct kevent const *kep;
n = kevent (kq, ke_vec, ke_vec_used, ke_vec, ke_vec_alloc, NULL);
ke_vec_used = 0; /* Already processed all changes. */
if (n == -1)
fatal ("Error in kevent(): %s", strerror (errno));
if (n == 0) fatal ("No events received!");
for (kep = ke_vec; kep < &ke_vec[n]; kep++)
{
register ecb const *const ecbp = (ecb *) kep->udata;
if (kep->filter == EVFILT_READ)
(*ecbp->do_read) (kep);
else (*ecbp->do_write) (kep);
}
}
}
int main (register int const argc, register char *const argv[])
{
auto in_addr listen_addr;
register int optch;
auto int one = 1;
register int portno = 0;
register int option_errors = 0;
register int server_sock;
auto sockaddr_in sin;
register servent *servp;
auto ecb listen_ecb;
register int kq;
pname = strrchr (argv[0], '/');
pname = pname ? pname+1 : argv[0];
listen_addr.s_addr = htonl (INADDR_ANY); /* Default. */
while ((optch = getopt (argc, argv, "p:")) != EOF)
{
switch (optch)
{
case 'p':
if (strlen (optarg) == 0 || !all_digits (optarg))
{
error ("Invalid argument for -p option: %s", optarg);
option_errors++;
}
portno = atoi (optarg);
if (portno == 0 || portno >= (1u << 16))
{
error ("Invalid argument for -p option: %s", optarg);
option_errors++;
}
break;
default:
error ("Invalid option: -%c", optch);
option_errors++;
}
}
if (option_errors || optind != argc)
usage ();
if (portno == 0)
{
if ((servp = getservbyname (servname, protoname)) == NULL)
fatal ("Error getting port number for service `%s': %s", servname, strerror (errno));
portno = ntohs (servp->s_port);
}
if ((server_sock = socket (PF_INET, SOCK_STREAM, 0)) == -1)
fatal ("Error creating socket: %s", strerror (errno));
if (setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one) == -1)
fatal ("Error setting SO_REUSEADDR for socket: %s", strerror (errno));
memset (&sin, 0, sizeof sin); sin.sin_family = AF_INET;
sin.sin_addr = listen_addr;
sin.sin_port = htons (portno);
if (bind (server_sock, (const struct sockaddr *)&sin, sizeof sin) == -1)
fatal ("Error binding socket: %s", strerror (errno));
if (listen (server_sock, 20) == -1)
fatal ("Error listening to socket: %s", strerror (errno));
if ((kq = kqueue ()) == -1)
fatal ("Error creating kqueue: %s", strerror (errno));
listen_ecb.do_read = do_accept;
listen_ecb.do_write = NULL;
listen_ecb.buf = NULL;
listen_ecb.buf = 0;
ke_change (server_sock, EVFILT_READ, EV_ADD | EV_ENABLE, &listen_ecb);
event_loop (kq);
}