socket

Linux:select、poll、epoll,Windows:IOCP,BSD/Mac:Kqueue,在这之上封装了 Libevent 等库。

客户端

#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>

int main() {
  int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);

  struct sockaddr_in server_addr = {.sin_family = AF_INET, .sin_port = htons(6666), .sin_addr.s_addr = inet_addr("127.0.0.1")};
  connect(fd, (struct sockaddr *) &server_addr, sizeof(server_addr));

  uint8_t type = 9;
  send(fd, &type, sizeof(uint8_t), 0);
  char *value = "hello!";
  size_t length = sizeof(char) * (strlen(value) + 1);
  send(fd, &length, sizeof(size_t), 0);
  send(fd, value, length, 0);

  recv(fd, &type, sizeof(uint8_t), MSG_WAITALL);
  recv(fd, &length, sizeof(size_t), MSG_WAITALL);
  recv(fd, value, sizeof(unsigned char) * length, MSG_WAITALL);
  printf("Received TLV data - Type: %u, Length: %lu, Value: %s\n", type, length, value);

  close(fd);
  return EXIT_SUCCESS;
}

服务端

#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>

int main() {
  int server_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);

  struct sockaddr_in server_addr = {.sin_family = AF_INET, .sin_port = htons(6666), .sin_addr.s_addr = htonl(INADDR_ANY)};
  bind(server_fd, (struct sockaddr *) &server_addr, sizeof(server_addr));

  listen(server_fd, SOMAXCONN);

  while (true) {
    struct sockaddr_in client_addr;
    socklen_t client_addr_len = sizeof(struct sockaddr_in);
    int client_fd = accept(server_fd, (struct sockaddr *) &client_addr, &client_addr_len);
    printf("client connected: %s:%d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));

    uint8_t type;
    recv(client_fd, &type, sizeof(uint8_t), MSG_WAITALL);
    size_t length;
    recv(client_fd, &length, sizeof(size_t), MSG_WAITALL);
    unsigned char value[length];
    recv(client_fd, value, sizeof(unsigned char) * length, MSG_WAITALL);
    printf("Received TLV data - Type: %u, Length: %lu, Value: %s\n", type, length, value);

    send(client_fd, &type, sizeof(uint8_t), 0);
    send(client_fd, &length, sizeof(size_t), 0);
    send(client_fd, value, sizeof(unsigned char) * length, 0);
    close(client_fd);
  }

  close(server_fd);
  return EXIT_SUCCESS;
}

服务端,多线程

#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <pthread.h>
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>

void *handle_client(void *arg) {
  int client_fd = *((int *) arg);

  struct sockaddr_in client_addr;
  socklen_t client_addr_len = sizeof(struct sockaddr_in);
  getpeername(client_fd, (struct sockaddr *) &client_addr, &client_addr_len);
  printf("Client connected: %s:%d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));

  uint8_t type;
  recv(client_fd, &type, sizeof(uint8_t), MSG_WAITALL);
  size_t length;
  recv(client_fd, &length, sizeof(size_t), MSG_WAITALL);
  unsigned char value[length];
  recv(client_fd, value, sizeof(unsigned char) * length, MSG_WAITALL);
  printf("Received TLV data - Type: %u, Length: %lu, Value: %s\n", type, length, value);

  send(client_fd, &type, sizeof(uint8_t), 0);
  send(client_fd, &length, sizeof(size_t), 0);
  send(client_fd, value, sizeof(unsigned char) * length, 0);

  close(client_fd);
  pthread_exit(NULL);
}

int main(int argc, char *argv[]) {
  int server_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);

  struct sockaddr_in server_addr = {.sin_family = AF_INET, .sin_port = htons(6666), .sin_addr.s_addr = htonl(INADDR_ANY)};
  bind(server_fd, (struct sockaddr *) &server_addr, sizeof(server_addr));

  listen(server_fd, SOMAXCONN);

  while (true) {
    struct sockaddr_in client_addr;
    socklen_t client_addr_len = sizeof(struct sockaddr_in);
    int client_fd = accept(server_fd, (struct sockaddr *) &client_addr, &client_addr_len);

    pthread_t tid;
    pthread_create(&tid, NULL, handle_client, &client_fd);
    pthread_detach(tid);
  }

  close(server_fd);
  return EXIT_SUCCESS;
}
View Code

服务端,select

#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>

int main(int argc, char *argv[]) {
  int server_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);

  struct sockaddr_in server_addr = {.sin_family = AF_INET, .sin_port = htons(6666), .sin_addr.s_addr = htonl(INADDR_ANY)};
  bind(server_fd, (struct sockaddr *) &server_addr, sizeof(server_addr));

  listen(server_fd, SOMAXCONN);

  fd_set readfds;
  FD_ZERO(&readfds);
  FD_SET(server_fd, &readfds);
  int max_fd = server_fd;
  while (true) {
    select(max_fd + 1, &readfds, NULL, NULL, NULL);

    for (int fd = 0; fd <= max_fd; fd++) {
      if (!FD_ISSET(fd, &readfds)) continue;
      if (fd == server_fd) {
        struct sockaddr_in client_addr;
        socklen_t client_addr_len = sizeof(struct sockaddr_in);
        int client_fd = accept(server_fd, (struct sockaddr *) &client_addr, &client_addr_len);
        printf("Client connected: %s:%d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
        FD_SET(client_fd, &readfds);
        if (client_fd > max_fd) max_fd = client_fd;
      } else {
        uint8_t type;
        recv(fd, &type, sizeof(uint8_t), MSG_WAITALL);
        size_t length;
        recv(fd, &length, sizeof(size_t), MSG_WAITALL);
        unsigned char value[length];
        recv(fd, value, sizeof(unsigned char) * length, MSG_WAITALL);
        printf("Received TLV data - Type: %u, Length: %lu, Value: %s\n", type, length, value);

        send(fd, &type, sizeof(uint8_t), 0);
        send(fd, &length, sizeof(size_t), 0);
        send(fd, value, sizeof(unsigned char) * length, 0);

        close(fd);
        FD_CLR(fd, &readfds);
      }
    }
  }

  close(server_fd);
  return EXIT_SUCCESS;
}
View Code

服务端,poll

#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/poll.h>
#include <sys/socket.h>
#include <unistd.h>

int main() {
  int server_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);

  struct sockaddr_in server_addr = {.sin_family = AF_INET, .sin_port = htons(6666), .sin_addr.s_addr = htonl(INADDR_ANY)};
  bind(server_fd, (struct sockaddr *) &server_addr, sizeof(server_addr));

  listen(server_fd, SOMAXCONN);

  struct pollfd fds[SOMAXCONN];
  for (int i = 0; i < SOMAXCONN; i++) fds[i].fd = -1;
  fds[0].fd = server_fd, fds[0].events = POLLIN;
  while (true) {
    poll(fds, SOMAXCONN, -1);

    if (fds[0].revents & POLLIN) {
      struct sockaddr_in client_addr;
      socklen_t client_addr_len = sizeof(struct sockaddr_in);
      int client_fd = accept(server_fd, (struct sockaddr *) &client_addr, &client_addr_len);
      printf("client connected: %s:%d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
      for (int i = 0; i < SOMAXCONN; i++) {
        if (fds[i].fd == -1) {
          fds[i].fd = client_fd, fds[i].events = POLLIN;
          break;
        }
      }
    }

    for (int i = 1; i < SOMAXCONN; i++) {
      if (!(fds[i].revents & POLLIN)) continue;
      int client_fd = fds[i].fd;

      uint8_t type;
      recv(client_fd, &type, sizeof(uint8_t), MSG_WAITALL);
      size_t length;
      recv(client_fd, &length, sizeof(size_t), MSG_WAITALL);
      unsigned char value[length];
      recv(client_fd, value, sizeof(unsigned char) * length, MSG_WAITALL);
      printf("Received TLV data - Type: %u, Length: %lu, Value: %s\n", type, length, value);

      send(client_fd, &type, sizeof(uint8_t), 0);
      send(client_fd, &length, sizeof(size_t), 0);
      send(client_fd, value, sizeof(unsigned char) * length, 0);
      close(client_fd);
      fds[i].fd = -1;
    }
  }

  close(server_fd);
  return EXIT_SUCCESS;
}
View Code

服务端,epoll

#include <arpa/inet.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/epoll.h>
#include <sys/socket.h>
#include <unistd.h>

int main() {
  int server_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);

  // int optval = 1;
  // setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
  // setsockopt(server_fd, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval));

  struct sockaddr_in server_addr = {.sin_family = AF_INET, .sin_port = htons(6666), .sin_addr.s_addr = htonl(INADDR_ANY)};
  bind(server_fd, (struct sockaddr *) &server_addr, sizeof(server_addr));

  listen(server_fd, SOMAXCONN);

  int epoll_fd = epoll_create1(0);
  struct epoll_event events[SOMAXCONN], event = {.data.fd = server_fd, .events = EPOLLIN};
  epoll_ctl(epoll_fd, EPOLL_CTL_ADD, server_fd, &event);

  while (true) {
    int nfds = epoll_wait(epoll_fd, events, SOMAXCONN, -1);

    for (int i = 0; i < nfds; i++) {
      if (events[i].data.fd == server_fd) {
        struct sockaddr_in client_addr;
        socklen_t client_addr_len = sizeof(struct sockaddr_in);
        int client_fd = accept(server_fd, (struct sockaddr *) &client_addr, &client_addr_len);
        printf("client connected: %s:%d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));

        // fcntl(client_fd, F_SETFL, fcntl(client_fd, F_GETFL, 0) | O_NONBLOCK); // 设置客户端 socket 为非阻塞模式
        event.data.fd = client_fd, event.events = EPOLLIN | EPOLLET; // 设置为边缘触发模式
        epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_fd, &event);
      } else {
        int client_fd = events[i].data.fd;

        uint8_t type;
        recv(client_fd, &type, sizeof(uint8_t), MSG_WAITALL);
        size_t length;
        recv(client_fd, &length, sizeof(size_t), MSG_WAITALL);
        unsigned char value[length];
        recv(client_fd, value, sizeof(unsigned char) * length, MSG_WAITALL);
        printf("Received TLV data - Type: %u, Length: %lu, Value: %s\n", type, length, value);

        send(client_fd, &type, sizeof(uint8_t), 0);
        send(client_fd, &length, sizeof(size_t), 0);
        send(client_fd, value, sizeof(unsigned char) * length, 0);

        epoll_ctl(epoll_fd, EPOLL_CTL_DEL, client_fd, NULL);
        close(client_fd);
      }
    }
  }

  close(epoll_fd);
  close(server_fd);
  return EXIT_SUCCESS;
}
View Code

 


https://en.wikipedia.org/wiki/Type-length-value

https://chenshuo.com & https://github.com/chenshuo

posted @ 2020-08-13 18:38  江湖小小白  阅读(1013)  评论(0编辑  收藏  举报