#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define port 8082 #define REQUIRED_STACK_SIZE 200*1024 #define OK 0 #define NOT_OK (!OK) int logger(const char *file, const char *function, int line, const char *fmt, ...) { va_list arglist; fprintf(stderr, "%s (%s) - line %04d : ", file, function, line); va_start(arglist, fmt); vfprintf(stderr, fmt, arglist); va_end(arglist); fprintf(stderr, "\n"); return 0; } #define _log(fmt, ...) logger(__FILE__, (char *)__FUNCTION__, __LINE__, fmt, ## __VA_ARGS__) int close_socket_fd(int fd) { int rc; if(fd < 0) return OK; rc = shutdown(fd, SHUT_RDWR); rc = close(fd); if(rc) { _log("close %d : %s", fd, strerror(errno)); } return OK; } static void *serverthread(void *parm) { struct pollfd pfd; char buff; int fd = (int)parm; int rc; #ifdef noleak sleep(3); rc = 1; #else pfd.fd = fd; pfd.events = POLLIN | POLLPRI; pfd.revents = 0; rc = poll(&pfd, 1, 3000); #endif if (rc == 1) { _log("ICI %d", fd); rc = read(fd, &buff, 1); _log("read %d bytes", rc); } close_socket_fd(fd); pthread_exit(0); return NULL; } int create_thread(pthread_t * thread, void * thread_func, void * arg, unsigned char must_detach) { int err = OK; pthread_attr_t attr; pthread_t null_thread; /* Initialize the attribute */ err = pthread_attr_init(&attr); if(err) { _log("pthread_attr_init err=%d: %s", err, strerror(errno)); return NOT_OK; } err = pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED); if(err) { _log("pthread_attr_setinheritsched: %s", strerror(errno)); pthread_attr_destroy(&attr); return NOT_OK; } err = pthread_attr_setstacksize(&attr, REQUIRED_STACK_SIZE); if(err) { _log("pthread_attr_setstacksize: %s", strerror(errno)); pthread_attr_destroy(&attr); return NOT_OK; } if(must_detach) { err = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); if(err) { _log("pthread_attr_setdetachstate: %s", strerror(errno)); pthread_attr_destroy(&attr); return NOT_OK; } } /* Create the thread with our attribute */ err = pthread_create((thread != NULL) ? (thread) : (&null_thread), &attr, thread_func, arg); if(err) { _log("pthread_create: %s", strerror(errno)); pthread_attr_destroy(&attr); return (err); } pthread_attr_destroy(&attr); return OK; } int main(void) { struct sockaddr_in addr; int new_sock, on; struct pollfd pfd; int fd; socklen_t addrlen; int ret, rc; addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = INADDR_ANY; memset(&(addr.sin_zero), '\0', 8); fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(fd < 0) { _log("socket : %s", strerror(errno)); return NOT_OK; } else { _log("Socket OK"); } on = 1; ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); if(ret < 0) { _log("setsockopt : %s", strerror(errno)); } ret = -1; while(ret < 0) { ret = bind(fd, (struct sockaddr *) & addr, sizeof(struct sockaddr_in)); if(ret < 0) { _log("bind : %s", strerror(errno)); sleep(1); // close_socket(listen_socket); } else { _log("Bind OK on port %d", port); } } ret = listen(fd, 1); if(ret != 0) { _log("listen : %s", strerror(errno)); close_socket_fd(fd); return NOT_OK; } else { _log("Listen OK on port %d", port); } while(1) { addrlen = sizeof(struct sockaddr_in); pfd.fd = fd; pfd.events = POLLIN | POLLPRI; pfd.revents = 0; rc = poll(&pfd, 1, 2000); if(rc == -1) { _log("poll : %s", strerror(errno)); sleep(1); continue; } if(pfd.revents == 0) { continue; } new_sock = accept(fd, (struct sockaddr *) & addr, &addrlen); if(new_sock < 0) { _log("accept : %s", strerror(errno)); close_socket_fd(new_sock); } else { struct linger linger; int option; struct timeval wait_timeout; _log("The client %s are connected", inet_ntoa(addr.sin_addr)); ret = create_thread(NULL, serverthread, (void *) new_sock, 1); if(ret < 0) { _log("Impossible de demarrer le thread client sur le port %d", port); close_socket_fd(new_sock); } } } return NOT_OK; }