Differences

This shows you the differences between two versions of the page.

Link to this comparison view

codaz:c:c_threaded_tcp_server [2010/01/12 13:29] (current)
Line 1: Line 1:
 +<code c>
 +/* 
 + * threaded TCP server template ​
 + * Copyright (c) 2004 iMil <imil @gcu.info>​. ​ All rights reserved.
 + *
 + * Redistribution and use in source and binary forms, with or without
 + * modification,​ are permitted provided that the following conditions
 + * are met:
 + * 1. Redistributions of source code must retain the above copyright
 + ​* ​   notice, this list of conditions and the following disclaimer.
 + * 2. Redistributions in binary form must reproduce the above copyright
 + ​* ​   notice, this list of conditions and the following disclaimer in the
 + ​* ​   documentation and/or other materials provided with the distribution.
 + * 3. All advertising materials mentioning features or use of this software
 + ​* ​   must display the following acknowledgement:​
 + ​* ​     This product includes software developed by iMil.
 + * 4. Neither the name of the author nor the names of any co-contributors
 + ​* ​   may be used to endorse or promote products derived from this software
 + ​* ​   without specific prior written permission.
 + *
 + * THIS SOFTWARE IS PROVIDED BY iMil AND CONTRIBUTORS ``AS IS''​ AND
 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 + * ARE DISCLAIMED. ​ IN NO EVENT SHALL iMil OR THE VOICES IN HIS HEAD
 + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 + * THE POSSIBILITY OF SUCH DAMAGE.
 + *
 + * $Id$
 + */
  
 +/* BSD Makefile
 + *
 + * #--- begin
 + * PROG=           ​whatyouwant
 + * LDADD+= ​        ​-pthread
 + * NOMAN= ​         true
 + *
 + * .include <bsd .prog.mk>​
 + * #--- end
 + */
 + 
 +/* google related keywords so you can find this code easily
 + * example exemple tcp server serveur thread threads pthread pthreads
 + * hope it helps you somewhat, I don't pretend it's a perfect code (far away
 + * from it) but maybe it could save you some hours.
 + * Feel free to contribute !
 + * iMil </​imil><​imil @gcu.info>​
 + */
 +
 +#include <​limits.h>​
 +#include <​stdio.h>​
 +#include <​stdarg.h>;​
 +#include <​sys/​socket.h>​
 +#include <​netinet/​in.h>​
 +#include <​arpa/​inet.h>​
 +#include <​signal.h>​
 +#include <​pthread.h>​
 +
 +#define SVR_PORT 6666
 +#define MAXLEN LINE_MAX
 +
 +#define D_WARN 5
 +
 +int verbose = 1;
 +
 +/* debug printf, show info if global verbose >= verbosity */
 +void
 +d_printf(uint8_t verbosity, char *fmt, ...) {
 +        char buffer[MAXLEN];​
 +
 +        if (verbose >= verbosity ) {
 +                va_list args;
 +                va_start(args,​ fmt);
 +                vsnprintf(buffer,​ MAXLEN, fmt, args);
 +                fprintf(stderr,​ "​%s",​ buffer);
 +                va_end(args);​
 +        }
 +}
 +
 +
 +void *
 +service(void *arg)
 +{
 + int fd = (int)arg;
 +
 + pthread_detach(pthread_self());​
 +
 + /* do whatever you want here */
 +
 + close(fd);
 +
 + pthread_exit(NULL);​
 +}
 +
 +void
 +sighandle(int signo) {
 + if ((signo==SIGTERM) || (signo==SIGINT)) {
 + exit(0);
 + }
 + if (signo == SIGHUP) {
 + }
 + if (signo == SIGALRM) {
 + }
 +}
 +
 +int
 +main(int argc, char *argv[]) {
 + int  port = SVR_PORT;
 + int clt_fd,​srv_fd;​
 + struct sockaddr_in local_addr;
 + struct sockaddr_in clt_addr;
 + socklen_t sin_size;
 + int yes = 1, err;
 + pthread_t tid;
 + struct timeval timeout = {5, 0};  ​
 + struct linger lng = {1, 5};
 + time_t stamp;
 +
 + /* ignore SIGPIPE and catch  SIGTERM|INT */
 +
 + if (signal(SIGPIPE,​ sighandle) == SIG_ERR)
 + fprintf(stderr,​ "​can'​t catch SIGPIPE signal\n"​);​
 + if (signal(SIGTERM,​ sighandle) == SIG_ERR)
 + fprintf(stderr,​ "​can'​t catch SIGTERM signal\n"​);​
 + if (signal(SIGINT,​ sighandle) == SIG_ERR)
 + fprintf(stderr,​ "​can'​t catch SIGINT signal\n"​);​
 + if (signal(SIGALRM,​ sighandle) == SIG_ERR)
 + fprintf(stderr,​ "​can'​t catch SIGALRM signal\n"​);​
 + if (signal(SIGHUP,​ sighandle) == SIG_ERR)
 + fprintf(stderr,​ "​can'​t catch SIGHUP signal\n"​);​
 +
 + if ((srv_fd = socket(AF_INET,​ SOCK_STREAM,​ 0)) == -1) {
 + perror("​socket"​);​
 + exit(1);
 + }
 +
 + local_addr.sin_family = AF_INET;
 + local_addr.sin_port = htons(port);​
 + local_addr.sin_addr.s_addr = INADDR_ANY;
 + memset(&​(local_addr.sin_zero),​ 0, 8);
 +
 + if (setsockopt(srv_fd, ​
 +        ​SOL_SOCKET, ​
 +        ​SO_REUSEADDR, ​
 +        &​yes, ​
 +        ​sizeof(int)) == -1){
 + perror("​setsockopt"​);​
 + exit(1);
 +
 +
 + setsockopt(srv_fd,​ SOL_SOCKET, SO_RCVTIMEO,​
 +    &​timeout,​ sizeof(struct timeval));
 + setsockopt(srv_fd,​ SOL_SOCKET, SO_SNDTIMEO,​
 +    &​timeout,​ sizeof(struct timeval));
 + setsockopt(srv_fd,​ SOL_SOCKET, SO_LINGER,
 +    &​lng,​ sizeof(struct linger));
 +
 + if (bind(srv_fd,​ (struct sockaddr *)&​local_addr,​
 + sizeof(struct sockaddr)) == -1) {
 + perror("​bind"​);​
 + exit(1);
 + }
 +
 + if (listen(srv_fd,​ 5) < 0) {
 + perror("​listen"​);​
 + exit(1);
 + }
 +
 + while(1) {
 + sin_size = sizeof(struct sockaddr_in);​
 +
 + if ((clt_fd = accept(srv_fd,​
 +      ​(struct sockaddr *)&​clt_addr,​
 +      &​sin_size)) < 0) {
 + continue;​
 + }
 + err = pthread_create(&​tid,​ NULL, service, (void *)clt_fd);
 + if (err != 0)
 + d_printf(D_WARN,​
 + "​error creating thread, err: %d\n", err);
 +
 + }
 +
 + /* never reached */
 + return (0);
 +}
 +</​code>​
codaz/c/c_threaded_tcp_server.txt ยท Last modified: 2010/01/12 13:29 (external edit)