// // ask the server to wait for a client connection // and accept one connection if possible // // uses select to make this non-blocking. // int connect_to_client(int server_fd) { int ret_val = 1; int newsockfd = -1; socklen_t clilen; struct sockaddr_in cli_addr; fd_set c_set; struct timeval time_limit; time_limit.tv_sec = 0; time_limit.tv_usec = 1000; clilen = sizeof(cli_addr); FD_ZERO(&c_set); FD_SET(server_fd,&c_set); select(server_fd+1, &c_set,NULL,NULL,&time_limit); if(FD_ISSET(server_fd,&c_set)) { #ifdef USE_GNUPTH newsockfd = pth_accept(server_fd,(struct sockaddr *) &cli_addr,&clilen); #else newsockfd = accept(server_fd,(struct sockaddr *) &cli_addr,&clilen); #endif if (newsockfd >= 0) { #ifdef DEBUG fprintf(stderr,"Info: new client connection %d \n",newsockfd); #endif } else { fprintf(stderr,"Info: failed in accept()\n"); } } return(newsockfd); }
int main(int argc, char *argv[]) { struct sockaddr_in sar; struct protoent *pe; struct sockaddr_in peer_addr; socklen_t peer_len; int sr; int port; /* initialize scheduler */ pth_init(); signal(SIGPIPE, SIG_IGN); signal(SIGINT, myexit); signal(SIGTERM, myexit); /* argument line parsing */ if (argc != 2) { fprintf(stderr, "Usage: %s <port>\n", argv[0]); exit(1); } port = atoi(argv[1]); if (port <= 0 || port >= 65535) { fprintf(stderr, "Illegal port: %d\n", port); exit(1); } fprintf(stderr, "This is TEST_HTTPD, a Pth test using socket I/O.\n"); fprintf(stderr, "\n"); fprintf(stderr, "Multiple connections are accepted on the specified port.\n"); fprintf(stderr, "For each connection a separate thread is spawned which\n"); fprintf(stderr, "reads a HTTP request the socket and writes back a constant\n"); fprintf(stderr, "(and useless) HTTP response to the socket.\n"); fprintf(stderr, "Additionally a useless ticker thread awakens every 5s.\n"); fprintf(stderr, "Watch the average scheduler load the ticker displays.\n"); fprintf(stderr, "Hit CTRL-C for stopping this test.\n"); fprintf(stderr, "\n"); /* run a just for fun ticker thread */ attr = pth_attr_new(); pth_attr_set(attr, PTH_ATTR_NAME, "ticker"); pth_attr_set(attr, PTH_ATTR_JOINABLE, FALSE); pth_attr_set(attr, PTH_ATTR_STACK_SIZE, 64*1024); pth_spawn(attr, ticker, NULL); /* create TCP socket */ if ((pe = getprotobyname("tcp")) == NULL) { perror("getprotobyname"); exit(1); } if ((s = socket(AF_INET, SOCK_STREAM, pe->p_proto)) == -1) { perror("socket"); exit(1); } /* bind socket to port */ sar.sin_family = AF_INET; sar.sin_addr.s_addr = INADDR_ANY; sar.sin_port = htons(port); if (bind(s, (struct sockaddr *)&sar, sizeof(struct sockaddr_in)) == -1) { perror("socket"); exit(1); } /* start listening on the socket with a queue of 10 */ if (listen(s, REQ_MAX) == -1) { perror("listen"); exit(1); } /* finally loop for requests */ pth_attr_set(attr, PTH_ATTR_NAME, "handler"); fprintf(stderr, "listening on port %d (max %d simultaneous connections)\n", port, REQ_MAX); for (;;) { /* accept next connection */ peer_len = sizeof(peer_addr); if ((sr = pth_accept(s, (struct sockaddr *)&peer_addr, &peer_len)) == -1) { perror("accept"); pth_sleep(1); continue; } if (pth_ctrl(PTH_CTRL_GETTHREADS) >= REQ_MAX) { fprintf(stderr, "currently no more connections acceptable\n"); continue; } fprintf(stderr, "connection established (fd: %d, ip: %s, port: %d)\n", sr, inet_ntoa(peer_addr.sin_addr), ntohs(peer_addr.sin_port)); /* spawn new handling thread for connection */ pth_spawn(attr, handler, (void *)((long)sr)); } }
int ath_accept (int s, struct sockaddr *addr, socklen_t *length_ptr) { return pth_accept (s, addr, length_ptr); }