1 #include <iostream> 2 #include <sstream> 3 #include <map> 4 5 #include <stdio.h> 6 #include <errno.h> 7 #include <string.h> 8 9 #include <sys/socket.h> 10 #include <netinet/in.h> 11 #include <arpa/inet.h> 12 13 #include <unistd.h> 14 #include <fcntl.h> 15 #include <poll.h> 16 17 #define LOCAL_AF AF_INET // 本地地址类型 18 #define LOCAL_IP_ADDR "172.20.0.115" 19 #define LOCAL_PORT 8090 20 21 #define BACKLOG 10 // 监听等待队列个数 22 23 #define MAX_FD 1024 // 最大打开文件描述符数目 24 #define MAX_USER 3 // 最大用户数 25 26 #define FAILED_TEST_CNT 10 // socket调用失败, 连续测试次数 27 28 // 统计连接socket和对应的socket连续调用失败次数, 失败 FAILED_TEST_CNT 次,关闭移除socket 29 typedef std::map<int, int> Clients; 30 31 using namespace std; 32 33 static void showErr() 34 { 35 printf("errno: %d, err_msg: %s\n", errno, strerror(errno)); 36 } 37 38 // 设置socket为非阻塞 39 static bool setSocketNonBlock(int socketFd) 40 { 41 int flags = fcntl(socketFd, F_GETFL); 42 if (-1 == flags) 43 { 44 cout << "fcntl F_GETFL error" << endl; 45 return false; 46 } 47 48 int ret = fcntl(socketFd, F_SETFL, O_NONBLOCK | flags); 49 if (-1 == ret) 50 { 51 cout << "fcntl F_SETFL error" << endl; 52 return false; 53 } 54 return true; 55 } 56 57 // 设置socket关闭时不等待缓存区数据发送完毕(等待可能导致缓冲区数据无法发送导致一直占用端口: 连接一直处于FIN_WAIT1状态) 58 static int disableLinger(int socketFd) 59 { 60 struct linger lingerVal; 61 lingerVal.l_onoff = 1; 62 lingerVal.l_linger = 0; 63 int ret = setsockopt(socketFd, SOL_SOCKET, SO_LINGER, &lingerVal, sizeof(lingerVal)); 64 if (0 != ret) 65 { 66 cout << "setsockopt linger error" << endl; 67 return false; 68 } 69 return true; 70 } 71 72 int main(int argc, char **argv) 73 { 74 int ret(0); 75 76 // 生成监听socket 77 int listenSocket(-1); 78 listenSocket = socket(LOCAL_AF, SOCK_STREAM, IPPROTO_TCP); 79 if (-1 == listenSocket) 80 { 81 cout << "socket error" << endl; 82 return 1; 83 } 84 85 if (!setSocketNonBlock(listenSocket)) 86 { 87 return 1; 88 } 89 90 if (!disableLinger(listenSocket)) 91 { 92 return 1; 93 } 94 95 // 绑定监听socket到指定网卡和端口 96 in_addr localAddr; 97 inet_pton(LOCAL_AF, LOCAL_IP_ADDR, &localAddr); 98 sockaddr_in localSockAddr; 99 localSockAddr.sin_family = LOCAL_AF; 100 localSockAddr.sin_addr = localAddr; 101 // localSockAddr.sin_addr.s_addr = htonl(INADDR_ANY); // 绑定到所有网卡的指定端口(多网卡自适应) 102 localSockAddr.sin_port = htons(LOCAL_PORT); 103 ret = bind(listenSocket, (sockaddr *)&localSockAddr, sizeof(localSockAddr)); 104 if (0 != ret) 105 { 106 cout << "bind error" << endl; 107 return 1; 108 } 109 110 ret = listen(listenSocket, BACKLOG); 111 if (0 != ret) 112 { 113 cout << "listen error" << endl; 114 return 1; 115 } 116 117 // 创建pollfd结构体数组, 使用poll函数管理监听socket和所有的连接socket 118 pollfd pollFds[MAX_FD]; 119 memset(pollFds, 0, sizeof(pollFds)); // memset初始化内存只适用于POD类型 120 int usedFdIdx = -1; // 已用到的pollfd数组索引 121 122 // 将监听socket纳入pollfd数组第一个元素 123 ++usedFdIdx; 124 pollFds[usedFdIdx].fd = listenSocket; 125 pollFds[usedFdIdx].events = POLLIN; // 客户端请求到达事件(connect等) 126 127 Clients clients; 128 129 bool done(false); 130 while (!done) 131 { 132 ret = poll(pollFds, usedFdIdx + 1, 1000); // 等待1秒 133 switch(ret) 134 { 135 case -1: 136 showErr(); 137 return 1; 138 case 0: 139 cout << "timeout" << endl; 140 break; 141 default: 142 // 遍历客户端连接socket 143 for (int idx = 1; idx <= usedFdIdx; ++idx) 144 { 145 Clients::iterator iter = clients.find(pollFds[idx].fd); 146 147 // 客户端可写 148 if (pollFds[idx].revents & POLLOUT) 149 { 150 string msg = "i‘m client\r\n"; 151 ret = send(pollFds[idx].fd, msg.c_str(), msg.length(), 0); 152 // send failed 153 if (-1 == ret && EAGAIN != errno) // EAGAIN代表缓冲区满了, 不是错误需要排除 154 { 155 iter->second++; 156 157 // 连续 158 if (iter->second >= 10) 159 { 160 ret = close(pollFds[idx].fd); 161 if (0 == ret) 162 { 163 cout << "close socket :" << pollFds[idx].fd << " success" <<endl; 164 } 165 else 166 { 167 cout << "close socket :" << pollFds[idx].fd << " failed" <<endl; 168 } 169 170 clients.erase(iter); 171 for (int i = idx; i < usedFdIdx; ++i) 172 { 173 pollFds[i] = pollFds[i + 1]; 174 } 175 --usedFdIdx; 176 } 177 } 178 else 179 { 180 iter->second = 0; 181 } 182 183 cout << "send ret: " << ret << endl; 184 } 185 else if (pollFds[idx].revents & POLLERR) 186 { 187 cout << pollFds[idx].fd << " error" << endl; 188 189 iter->second++; 190 191 // remove socket 192 if (iter->second >= 10) 193 { 194 ret = close(pollFds[idx].fd); 195 if (0 == ret) 196 { 197 cout << "close socket :" << pollFds[idx].fd << " success" <<endl; 198 } 199 else 200 { 201 cout << "close socket :" << pollFds[idx].fd << " failed" <<endl; 202 } 203 204 clients.erase(iter); 205 for (int i = idx; i < usedFdIdx; ++i) 206 { 207 pollFds[i] = pollFds[i + 1]; 208 } 209 --usedFdIdx; 210 } 211 } 212 213 if (idx == usedFdIdx) 214 { 215 sleep(1); 216 } 217 } 218 219 // 客户端connect请求到达 220 if (pollFds[0].revents & POLLIN) 221 { 222 if (usedFdIdx < MAX_USER) 223 { 224 int connectSocket(-1); 225 connectSocket = accept(listenSocket, NULL, NULL); 226 if (-1 == connectSocket) 227 { 228 cout << "accept error" << endl; 229 break; 230 } 231 cout << "accept success" << endl; 232 233 if (!setSocketNonBlock(connectSocket)) 234 { 235 break; 236 } 237 238 if (!disableLinger(connectSocket)) 239 { 240 break; 241 } 242 243 // 连接socket使用poll管理 244 ++usedFdIdx; 245 pollFds[usedFdIdx].fd = connectSocket; 246 pollFds[usedFdIdx].events = POLLOUT; 247 248 // 249 clients.insert(make_pair<int, int>(connectSocket, 0)); 250 } 251 else // fd too many 252 { 253 254 } 255 } 256 } 257 } 258 259 260 return 0; 261 }
时间: 2024-10-16 22:09:38