Linux socket

Linux下socket有select、poll、epoll和AIO等方式,其中,前三種爲同步方式。linux

有不少種方法能夠設置socket爲非阻塞模式,經常使用的是使用fcntl(sockfd, F_SETFL, O_NONBLOCK);segmentfault

在阻塞模式下,能夠經過setsockopt來設置(讀/寫)超時,connect也能夠用setsockopt來設置,與寫參數一致:異步

setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO,&timeo, len);

connect的超時通常是nonblocking+select。socket

同步、異步與阻塞、非阻塞的區別async

參考

Linux IO模式及 select、poll、epoll詳解ide

使用異步 I/O 大大提升應用程序的性能性能

TCP服務端

建立socket -> bind -> listen -> accept -> send/recv -> closespa

代碼摘自http://blog.csdn.net/shallnet/article/details/17734919,後同.net

  #include <stdio.h>
  #include <unistd.h>
  #include <errno.h>
  #include <string.h>
  #include <sys/types.h>
  #include <sys/socket.h>
  #include <stdlib.h>
  #include <arpa/inet.h>
  #include <netinet/in.h>
  
  #include "server.h"
  #include "ly_debug.h"
  
  void accept_handle(int connfd, struct sockaddr_in peeraddr);
  
  int main(int argc, const char *argv[])
  {
      int                 sockfd, connfd;
      struct sockaddr_in  seraddr, peeraddr;
      socklen_t           addrlen;
  
      COMPILE_TIME_PRINT;
  
      if (argc != 2) {
          printf("Usage: %s <port>\n", argv[0]);
          return -1;
      }
      sockfd = socket(AF_INET, SOCK_STREAM, 0);
      if (sockfd < 0) {
          LY_ERR("socket: %s\n", strerror(errno));
          return -1;
      }
  
      seraddr.sin_family = AF_INET;
      seraddr.sin_port = ntohs(atoi(argv[1]));
      seraddr.sin_addr.s_addr = htonl(INADDR_ANY);
  
      if (bind(sockfd, (struct sockaddr *)&seraddr, sizeof(struct sockaddr))) {
          LY_ERR("bind: %s\n", strerror(errno));
          return -1;
      }
  
      if (listen(sockfd, MAX_CONN) < 0) {
          LY_ERR("listen: %s\n", strerror(errno));
          return -1;
      }
  
      addrlen = sizeof(struct sockaddr);
      for (;;) {
          connfd = accept(sockfd, (struct sockaddr *)(&peeraddr), &addrlen);
          if (connfd < 0) {
              LY_ERR("accept: %s\n", strerror(errno));
              continue;
          }
          
          accept_handle(connfd, peeraddr);
      }
      return 0;
  }
  
  void accept_handle(int connfd, struct sockaddr_in peeraddr)
  {
      char            buf[32] = "Hello, welcome to server!";
  
      LY_IFO("Receive request from %s, port %d\n",
              inet_ntop(AF_INET, &peeraddr.sin_addr, buf, sizeof(buf)),
              ntohs(peeraddr.sin_port));
  //sleep(10);
      if (send(connfd, buf, sizeof(buf), 0) < 0) {
          LY_ERR("send: %s\n", strerror(errno));
          return;
      }
  close(connfd);
      LY_IFO("send info: %s\n", buf);
  }

TCP客戶端

建立socket -> connect -> send/recv->closedebug

  #include <stdio.h>
  #include <unistd.h>
  #include <errno.h>
  #include <string.h>
  #include <sys/types.h>
  #include <sys/socket.h>
  #include <stdlib.h>
  #include <netinet/in.h>
  #include <arpa/inet.h>
  
  #include "ly_debug.h"
  
  int main(int argc, const char *argv[])
  {
      int                 sockfd;
      struct sockaddr_in  seraddr;
      char                recvbuf[32];
  
      COMPILE_TIME_PRINT;
  
      if (argc != 3) {
          LY_PRT("Usage: %s <ip> <port>\n", argv[0]);
          return -1;
      }
      if (inet_pton(AF_INET, argv[1], &seraddr.sin_addr) < 0) {
          LY_ERR("inet_pton: %s\n", strerror(errno));
          return -1;
      }
  
      sockfd = socket(AF_INET, SOCK_STREAM, 0);
      if (sockfd < 0) {
          LY_ERR("socket: %s\n", strerror(errno));
          return -1;
      }
  
      seraddr.sin_family = AF_INET;
      seraddr.sin_port = htons(atoi(argv[2]));
  
      if (connect(sockfd, (struct sockaddr *)(&seraddr), 
                  sizeof(struct sockaddr)) < 0) {
          LY_ERR("connect: %s\n", strerror(errno));
          return -1;
      }
  
      if (recv(sockfd, recvbuf, sizeof(recvbuf), 0) < 0) {
          LY_ERR("recv: %s\n", strerror(errno));
          return -1;
      }
  
      LY_PRT("From server: %s\n", recvbuf);
  close(sockfd);
      return 0;
  }
相關文章
相關標籤/搜索