1. 服务端
#include <stdlib.h> #include <string.h> #include <errno.h> #include <signal.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <unistd.h> #include <iostream> #include <forward_list> #include <thread> class Server { constexpr static int DEFAULT_BACKLOG = 10; public: Server(): _listener(-1), _should_exit(false) {} ~Server() { for (auto it = _threads.begin(); it != _threads.end(); it++) { it->join(); } } // 判断 server 是否有效 operator bool() const { return _listener != -1; } // 监听并接受连接 void listen_and_serve(unsigned short port, int backlog= DEFAULT_BACKLOG) { // 创建套接字 _listener = socket(AF_INET, SOCK_STREAM, 0); if (_listener == -1) { std::cerr << "cannot create listener\n"; return; } // 设置套接字选项 int value = 1; if (setsockopt(_listener, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value)) == -1) { std::cerr << "cannot set option: reuse_address\n"; } // 绑定地址 struct sockaddr_in addr; memset(&addr, 0, sizeof(sockaddr_in)); addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(_listener, (struct sockaddr*)&addr, sizeof(addr)) == -1) { std::cerr << "bind failed\n"; return; } // 监听连接 if (listen(_listener, backlog) == -1) { std::cerr << "listen failed\n"; return; } int conn; std::cout << "listening ...\n"; // 接受连接 while (!_should_exit) { conn = accept(_listener, NULL, NULL); if (conn == -1) { std::cerr << "accept failed\n"; } _threads.push_front(std::thread(Server::handle_connection, conn)); } } // 关闭套接字 void close() { _should_exit = true; ::close(_listener); } // 处理连接 static void handle_connection(int conn) { char buf[16] = { 0 }; int n = recv(conn, buf, sizeof(buf), 0); send(conn, buf, n, 0); ::close(conn); } private: int _listener; std::forward_list<std::thread> _threads; bool _should_exit; }; Server server; // 信号处理器 void handler(int signum) { std::cout << "exit ...\n"; if (server) { server.close(); } exit(EXIT_SUCCESS); } int main() { // 处理 ctrl+c signal(SIGINT, handler); server.listen_and_serve(6666); }
2. 客户端
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <stdint.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> const char* SERVER_IP = "127.0.0.1"; const short SERVER_PORT = 6666; int main() { int sockfd; struct sockaddr_in addr; // 创建套接字 sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd == -1) { printf("socket: %s\n", strerror(errno)); return 1; } // 发起连接 memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(SERVER_PORT); if (inet_pton(AF_INET, SERVER_IP, &addr.sin_addr) <= 0) { printf("inet_pton: %s\n", strerror(errno)); return 1; } if (connect(sockfd, (const struct sockaddr*)&addr, sizeof(addr)) < 0) { printf("connect: %s\n", strerror(errno)); return 1; } // 发送、接收数据 const char* msg = "hello"; char buf[16] = { 0 }; send(sockfd, msg, strlen(msg), 0); int n = recv(sockfd, buf, sizeof(buf), 0); printf("%s\n", buf); close(sockfd); return 0; }