#include <iostream> #include <cstdlib> #include <string> #include <cstring> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> #include <sys/time.h> #include <sys/select.h> using namespace std; #define BUF_SIZE 100 void deal_error(string error_msg) { cout << error_msg << endl; exit(1); } int before_socket_accept() { int ser_sock = 0; ser_sock = socket(PF_INET, SOCK_STREAM, 0); if (ser_sock == -1) { deal_error("socket() failed"); return ser_sock; } sockaddr_in ser_addr; ser_addr.sin_family = AF_INET; ser_addr.sin_addr.s_addr = htonl(INADDR_ANY); ser_addr.sin_port = htons(33333); if (bind(ser_sock, (sockaddr *)&ser_addr, sizeof(ser_addr)) == -1) { close(ser_sock); deal_error("bind() failed"); return -1; } if (listen(ser_sock, 5) == -1) { close(ser_sock); deal_error("listen() failed"); return -1; } return ser_sock; } void accept_connect(int ser_sock) { fd_set reads; FD_ZERO(&reads); FD_SET(ser_sock, &reads); int fd_max = ser_sock; char message[BUF_SIZE]; while(true) { fd_set cpy_reads = reads; timeval timeout; timeout.tv_sec = 5; timeout.tv_usec = 500; int fd_num = select(fd_max + 1, &cpy_reads, 0, 0, &timeout); if (fd_num == -1) { break; } else if (fd_num == 0) { // select超时返回 continue; } else { // select监测到有变化 for (int i = 0; i < fd_max + 1; i++) { if (FD_ISSET(i, &cpy_reads)) { if (i == ser_sock) { // 如果是服务器端的套接字描述符发生变化,说明是客户端连接请求(SYN报文) // 接受客户端的连接请求 sockaddr_in clnt_addr; socklen_t addr_length = sizeof(clnt_addr); int clnt_sock = accept(ser_sock, (sockaddr *)&clnt_addr, &addr_length); FD_SET(clnt_sock, &reads); if (fd_max < clnt_sock) { fd_max = clnt_sock; } } else { // 接收客户端的数据,并回传给客户端 int str_len = read(i, message, BUF_SIZE); if (str_len == 0) { FD_CLR(i, &reads); close(i); } else { write(i, message, str_len); } } } } } } } int main() { int ser_sock = before_socket_accept(); if (ser_sock == -1) { return 0; } accept_connect(ser_sock); close(ser_sock); return 0; }