create socket by pthread

来源:互联网 发布:有淘宝秒杀软件吗 编辑:程序博客网 时间:2024/05/21 01:58



#include <pthread.h>#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <sys/types.h>#include <sys/socket.h>#include <arpa/inet.h>#include <netinet/in.h>#include <sys/wait.h>#include <signal.h>#include <time.h>#include <string.h>#include <errno.h>//--------------------------------------------------------------------// Function prototype//--------------------------------------------------------------------void signal_handler(int signum);void *thread_main(void *arg);//--------------------------------------------------------------------// Main function//--------------------------------------------------------------------int main(int argc, char **argv){  int listening_socket;  unsigned short port;  int backlog;  //------------------------------------------------------------------  // Parse command line arguments  //------------------------------------------------------------------  port = (unsigned short) strtol(argv[2], NULL, 10);  backlog = (int) strtol(argv[3], NULL, 10);  //------------------------------------------------------------------  // step 1, create socket  //------------------------------------------------------------------  //int socket(int domain, int type, int protocol);  if ((listening_socket = socket(PF_INET, SOCK_STREAM, 0)) < 0)  {    // failed    fprintf(stderr, "[%d]Create new TCP socket failed: %s\n", getpid(), strerror(errno));    exit(1);  }  fprintf(stderr, "[%d]New TCP socket created, listening_socket = %d\n", getpid(), listening_socket);  //------------------------------------------------------------------  // Set SO_REUSEADDR & SO_REUSEPORT options  //------------------------------------------------------------------  int optval;  optval = 1;  //int setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen);  if (setsockopt(listening_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0)  {    fprintf(stderr, "[%d]Set socket option SO_REUSEADDR failed: %s\n", getpid(), strerror(errno));  }  else  {    fprintf(stderr, "[%d]Set socket option SO_REUSEADDR successfully.\n", getpid());  }#ifdef SO_REUSEPORT  optval = 1;  //int setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen);  if (setsockopt(listening_socket, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval)) < 0)  {    fprintf(stderr, "[%d]Set socket option SO_REUSEPORT failed: %s\n", getpid(), strerror(errno));  }  else  {    fprintf(stderr, "[%d]Set socket option SO_REUSEPORT successfully.\n", getpid());  }#endif  //------------------------------------------------------------------  // step 2, bind  //------------------------------------------------------------------  struct sockaddr_in local_ipv4_address;// IPv4  memset(&local_ipv4_address, 0, sizeof(local_ipv4_address));  local_ipv4_address.sin_family = AF_INET;// IPv4  local_ipv4_address.sin_port = htons(port);// Network byte order  // int inet_pton(int af, const char *src, void *dst);  inet_pton(AF_INET, argv[1], &local_ipv4_address.sin_addr);  // Bind all interfaces  //local_ipv4_address.sin_addr.s_addr = INADDR_ANY;  //int bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen);  if (bind(listening_socket, (struct sockaddr *) &local_ipv4_address, sizeof(local_ipv4_address)) < 0)  {    fprintf(stderr, "[%d]Bind to %s:%d failed: %s\n", getpid(), argv[1], port, strerror(errno));    close(listening_socket);    exit(1);  }  fprintf(stderr, "[%d]Bound to %s:%d successfully.\n", getpid(), argv[1], port);  //------------------------------------------------------------------  // step 3, listen  //------------------------------------------------------------------  //int listen(int sockfd, int backlog);  if (listen(listening_socket, backlog) < 0)  {    fprintf(stderr, "[%d]Listen on %s:%d failed: %s\n", getpid(), argv[1], port, strerror(errno));    close(listening_socket);    exit(1);  }  fprintf(stderr, "[%d]Listen on %s:%d successfully.\n", getpid(), argv[1], port);  fprintf(stderr, "[%d]Waiting for incomming connections ...\n", getpid());  //------------------------------------------------------------------  // Register signal handler  //------------------------------------------------------------------  struct sigaction act, oact;#if 0  struct sigaction  {    void (*sa_handler) (int);    void (*sa_sigaction) (int, siginfo_t *, void *);    sigset_t sa_mask;    int sa_flags;    void (*sa_restorer) (void);  };#endif  memset(&act, 0, sizeof(act));  act.sa_handler = signal_handler;  //int sigemptyset(sigset_t *set);  sigemptyset(&act.sa_mask);  act.sa_flags = 0;  //int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);  sigaction(SIGCHLD, &act, &oact);  //------------------------------------------------------------------  // Main loop  //------------------------------------------------------------------  for (;;)  {    //----------------------------------------------------------------    // accept(), create a new_connected_socket    //----------------------------------------------------------------    /*     * The accept() system call is used  with  connection-based socket types (SOCK_STREAM, SOCK_SEQPACKET).      *     * It extracts the first connection request on the queue of pending connections, creates a new connected      * socket, and returns a new file descriptor referring to that socket.        *     * The newly created socket is not in the listening state(in ESTABLISHED state)     *      * The original socket sockfd is unaffected by this call(still in LISTEN state)     */    int new_connected_socket;    struct sockaddr_in peer_ipv4_address;    socklen_t peer_ipv4_address_length;    // peer_ipv4_address_length is a value-result parameter    peer_ipv4_address_length = sizeof(peer_ipv4_address);    //int accept(int sockfd, struct sockaddr *addr, socklen_t * addrlen);    if ((new_connected_socket = accept(listening_socket, (struct sockaddr *) &peer_ipv4_address, &peer_ipv4_address_length)) < 0)    {      // failed      if (errno == EINTR)      {// Interrupted by signalcontinue;      }      else      {// TODO: check other error code      }      fprintf(stderr, "[%d]Accept new connections on socket %d failed: %s\n", getpid(), listening_socket, strerror(errno));      break;    }    else    {      // success      char peer_ipv4_address_string[] = "ddd.ddd.ddd.ddd";      //const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt);      inet_ntop(AF_INET, &peer_ipv4_address.sin_addr, peer_ipv4_address_string, sizeof(peer_ipv4_address_string));      fprintf(stderr, "[%d]Accepted a new connection %d from %s:%d.\n", getpid(), new_connected_socket, peer_ipv4_address_string, ntohs(peer_ipv4_address.sin_port));      //--------------------------------------------------------------      // create new thread      //--------------------------------------------------------------      pthread_t tid;      pthread_attr_t attr;      int code;      //int pthread_attr_init(pthread_attr_t *attr);      pthread_attr_init(&attr);      //int pthread_attr_setdetachstate(pthread_attr_t * attr, int detach - state);      pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);      //int pthread_create(pthread_t * restrict thread, const pthread_attr_t * restrict attr, void *(*start_routine) (void *), void *restrict arg);      if ((code = pthread_create(&tid, &attr, thread_main, (void *) &new_connected_socket)) != 0)      {fprintf(stderr, "[%d]Create new thread failed: %s\n", getpid(), strerror(code));      }      else      {fprintf(stdout, "[%d]New thread created.\n", getpid());      }      //int pthread_attr_destroy(pthread_attr_t *attr);      pthread_attr_destroy(&attr);    }  }  //------------------------------------------------------------------  // final, close listening_socket  //------------------------------------------------------------------  close(listening_socket);  return 0;}void signal_handler(int signum){  fprintf(stderr, "[%d]Caught signal %d.\n", getpid(), signum);  pid_t pid;  int status;  //pid_t wait(int *status);  if ((pid = wait(&status)) < 0)  {    // failed    fprintf(stderr, "wait() failed: %s\n", strerror(errno));  }  else  {    fprintf(stderr, "[%d]Child process %d terminated, status = 0x%08x\n", getpid(), pid, status);    // check status  }}void *thread_main(void *arg){  int fd = *(int *) arg;  //--------------------------------------------------------------  // Compose current time information  //--------------------------------------------------------------  // time_t time(time_t *t);  time_t now = time(NULL);  struct tm *tm;  //struct tm *localtime(const time_t *timep);  tm = localtime(&now);  char buffer[128];#if 0  struct tm  {    int tm_sec;/* seconds */    int tm_min;/* minutes */    int tm_hour;/* hours */    int tm_mday;/* day of the month */    int tm_mon;/* month */    int tm_year;/* year */    int tm_wday;/* day of the week */    int tm_yday;/* day in the year */    int tm_isdst;/* daylight saving time */  };#endif  memset(buffer, 0, sizeof(buffer));  //int snprintf(char *str, size_t size, const char *format,...);  snprintf(buffer, sizeof(buffer) - 1, "Current time: %04d-%02d-%02d %02d:%02d:%02d", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);  //--------------------------------------------------------------  // Send current time to client  //--------------------------------------------------------------  ssize_t n;  //ssize_t write(int listening_socket, const void *buf, size_t count);  if ((n = write(fd, buffer, strlen(buffer))) < 0)  {    fprintf(stderr, "[%d]Send data to client fialed: %s\n", getpid(), strerror(errno));  }  else  {    fprintf(stderr, "[%d]Sent %d bytes (\"%s\" to client successfully.\n", getpid(), n, buffer);  }  //--------------------------------------------------------------  // close new_connected_socket  //--------------------------------------------------------------  close(fd);  pthread_exit((void *) 0);}// vim:tabstop=8