int EgSock::Connect(const char* ip, uint16_t port, function<void(sp_EgSock)> callback) { _fd = CreateSocket(); SetNonblock(fd); SetNodelay(fd); _peer_ip = ip; _port = port; _state = EG_SOCK_CONNECTING; _callback = callback; sockaddr_in serv_addr; SetAddr(ip, port, &serv_addr); if (connect(_fd, (sockaddr*)&serv_addr, sizeof(serv_addr)) == SOCKET_ERROR) { if (!((errno == EINPROGRESS) || (errno == EWOULDBLOCK))) { loge("connect failed, err_code=%d", errno); close(_fd); throw egex("connect failed, errno=%d", errno); } } else { _state = EG_SOCK_CONNECTED; callback(shared_from_this()); } return _fd; }
//生成套接字,并设置为非阻塞 bool Server::InitSockfd() { log::log(Info,"init sock fd"); if((m_sockfd = socket(AF_INET, SOCK_STREAM, 0))==-1) { return false; } //设置非阻塞 return SetNonblock(m_sockfd); }
int EgSock::Listen(const char* ip, uint16_t port, function<void(sp_EgSock)> callback) { _fd = CreateSocket(); SetReuseAddr(_fd); SetNonblock(_fd); Bind(_fd, ip, port); if (listen(_fd, 64) == SOCKET_ERROR) { loge("listen failed, err_code=%d", errno); close(_fd); throw egex("listen failed, err_code=%d", errno); } _state = EG_SOCK_LISTENING; _callback = callback; return _fd; }
void EgSock::_OnAccept() { int sessionFd = 0; sockaddr_in peer_addr; socklen_t addr_len = sizeof(sockaddr_in); char ip_str[64]; while((sessionFd = accept(fd, (sockaddr*)&peer_addr, &addr_len)) != INVALID_SOCKET) { EgSock* sock = new EgSock(); uint32_t ip = ntohl(peer_addr.sin_addr.s_addr); uint16_t port = ntohs(peer_addr.sin_port); snprintf(ip_str, sizeof(ip_str), "%d.%d.%d.%d", ip >> 24, (ip >> 16) & 0xFF, (ip >> 8) & 0xFF, ip & 0xFF); sock->SetPeerIp(ip_str); sock->SetPeerPort(port); sock->SetFd(sessionFd); sock->SetCallback(_callback); SetNodelay(sessionFd); SetNonblock(sessionFd); EgDispatch::Instance()->AddEvent(sessionFd); } }
//服务器侦听套接字上的事件 void Server::OnRead() { log::log(Info,"handle accept evets!"); //建立新的连接 struct sockaddr_in addr; socklen_t len = sizeof(sockaddr); int sockfd = accept(m_sockfd,(sockaddr *)&addr,&len); if(sockfd<0) { log::log(Error,"connfd < 0"); return; } //设置为非阻塞 SetNonblock(sockfd); //创建连接 Connection* conn = new Connection(sockfd,addr,this); std::map<uint64_t, Connection*>::iterator it = m_connections.find(sockfd); if(it != m_connections.end()) { Connection* connection =it->second; //这个连接已经存在,其实是不可能的,但是还是删除把 m_selector->Remove(connection); m_connections.erase(it); delete connection; } //插入m_connections中,以IP为键,这样不合理,同一个IP会登陆多个客户端,所以还是用套接字作为键吧 m_connections[sockfd] = conn; //打印一些信息 log::log(Info,"m_connections.size() = ",m_connections.size()); char *str = inet_ntoa(addr.sin_addr); unsigned short port = ntohs(addr.sin_port); log::log(Info,"accept a connection from ip:",str,"port",port); //添加到epoll中 m_selector->Select(conn,0,0); log::log(Info,"m_selector.size:",m_selector->Size()); }
BOOL CTcpEpollServer::EpollAcceptSocket(SOCKET hSocket, const sockaddr_in& SockAddr) { if(INVALID_SOCKET == hSocket) return FALSE; // 设置程非阻塞式SOCKET if (!SetNonblock(hSocket, TRUE)) { return FALSE; } // 回调上层创建context CTcpContext *pContext = CreateContext(); if (pContext == NULL) { return FALSE; } // Context 赋值 pContext->m_hSocket = hSocket; memcpy(&pContext->m_oSocketAddr, &SockAddr, sizeof(sockaddr_in)); // 添加至队列 AddTcpContext(pContext); struct epoll_event ev; ev.events = EPOLLIN | EPOLLOUT | EPOLLET; //ET模式+读事件+写事件 ev.data.ptr = (void*)pContext; if (epoll_ctl(m_hEpollHandle, EPOLL_CTL_ADD, hSocket, &ev) < 0) { RemoveTcpContext(pContext); DestroyContext(pContext); return FALSE; } return TRUE; }
//生成套接字,并设置为非阻塞 void Client::InitSockfd(int& sockfd) { sockfd = socket(AF_INET, SOCK_STREAM, 0);//tcp //设置非阻塞 SetNonblock(sockfd); }
/// 创建SOCKET套接字 SOCKET CTcpEpollServer::CreateSocket(uint16_t nSvrPort) { SOCKET hSocket = INVALID_SOCKET; BOOL bIsSucceed = FALSE; do { // 创建监听Socket SOCKET hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); if (hSocket == INVALID_SOCKET) { TraceLogError("CTcpEpollServer::CreateSocket 创建SOCKET失败 ERROR=%s!\n", strerror(errno)); break; } //设置Socket绑定的服务器IP地址、端口可以重用。 //防止服务器在发生意外时,端口未被释放,造成无法启动;设置后可以重新使用了。 unsigned int optval = 0x1; setsockopt(hSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&optval, sizeof(unsigned int)); //设置程非阻塞式SOCKET if (!SetNonblock(hSocket,TRUE)) { TraceLogError("CTcpEpollServer::CreateSocket SetNonblock失败 SOCKET=%d!\n", hSocket); break; } //绑定端口 sockaddr_in addr; memset(&addr,0,sizeof(sockaddr_in)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; addr.sin_port = htons(nSvrPort); if (SOCKET_ERROR == bind(hSocket,(sockaddr *)&addr, sizeof(sockaddr_in))) { TraceLogError("CTcpEpollServer::CreateSocket 绑定端口失败 PORT=%d ERROR=%s!\n", nSvrPort, strerror(errno)); break; } //开始侦听 if (listen(hSocket, 100) == SOCKET_ERROR) { TraceLogError("CTcpEpollServer::CreateSocket 监听失败 ERROR=%s!\n", strerror(errno)); break; } bIsSucceed = TRUE; } while (FALSE); if(!bIsSucceed) { if(INVALID_SOCKET != hSocket) { close(hSocket); hSocket = INVALID_SOCKET; } } return hSocket; }