int mread_poll(struct mread_pool * self , int timeout) { self->skip = 0; if (self->active >= 0) { struct socket * s = &self->sockets[self->active]; if (s->status == SOCKET_READ) { return self->active; } } if (self->closed > 0 ) { return _report_closed(self); } if (self->queue_head >= self->queue_len) { if (_read_queue(self, timeout) == -1) { self->active = -1; return -1; } } for (;;) { struct socket * s = _read_one(self); if (s == NULL) { self->active = -1; return -1; } if (s == LISTENSOCKET) { struct sockaddr_in remote_addr; socklen_t len = sizeof(struct sockaddr_in); int client_fd = accept(self->listen_fd , (struct sockaddr *)&remote_addr , &len); if (client_fd >= 0) { // printf("MREAD connect %s:%u (fd=%d)\n",inet_ntoa(remote_addr.sin_addr),ntohs(remote_addr.sin_port), client_fd); struct socket * s = _add_client(self, client_fd); if (s) { self->active = -1; return s - self->sockets; } } } else { int index = s - self->sockets; assert(index >=0 && index < self->max_connection); self->active = index; s->status = SOCKET_POLLIN; return index; } } }
int mread_poll(struct mread_pool * self , int timeout) { self->skip = 0; if (self->active >= 0) { struct socket * s = &self->sockets[self->active]; if (s->status == SOCKET_READ) { return self->active; } } if (self->closed > 0 ) { return _report_closed(self); } if (self->queue_head >= self->queue_len) { if (_read_queue(self, timeout) == -1) { self->active = -1; return -1; } } /* #if defined(_WIN32) for(;;){//accept socket int n = WSAWaitForMultipleEvents(1, self->events, 0, timeout, 0); WSANETWORKEVENTS ne; if (n == WAIT_FAILED) { break; } if (n == WAIT_TIMEOUT) { break; } n -= WSA_WAIT_EVENT_0; if (WSAEnumNetworkEvents(self->listen_fd, self->events[n], &ne) == -1) { break; } if (ne.lNetworkEvents & FD_ACCEPT) { SOCKET fd = accept(self->listen_fd, NULL, NULL); struct socket * s = _add_client(self, fd); if (CreateIoCompletionPort((HANDLE)fd,self->iocp,s, 0) == NULL) { break; } if (CreateIoCompletionPort((HANDLE)fd,self->iocp,1, 0) == NULL) { printf("add connection GetLastError is : %d %d \n",GetLastError(),fd); break; } DWORD flags = 0; DWORD recvBytes =0; ZeroMemory(&s->ol,sizeof(OVERLAPPED)); if (WSARecv(fd, NULL,0, &recvBytes, &flags, &(s->ol), NULL) == SOCKET_ERROR) { DWORD error; error = GetLastError(); printf("GetLastError is : %d , recvBytes = %d \n",error,recvBytes); } continue; } } #endif */ for (;;) { struct socket * s = _read_one(self); if (s == NULL) { self->active = -1; return -1; } if (s == LISTENSOCKET) { struct sockaddr_in remote_addr; socklen_t len = sizeof(struct sockaddr_in); int client_fd = accept(self->listen_fd , (struct sockaddr *)&remote_addr , &len); if (client_fd >= 0) { // printf("MREAD connect %s:%u (fd=%d)\n",inet_ntoa(remote_addr.sin_addr),ntohs(remote_addr.sin_port), client_fd); struct socket * s = _add_client(self, client_fd); if (s) { self->active = -1; return s - self->sockets; } } } else { int index = s - self->sockets; assert(index >=0 && index < self->max_connection); self->active = index; s->status = SOCKET_POLLIN; return index; } } }
static int _read_queue(struct mread_pool * self, int timeout) { self->queue_head = 0; #ifdef HAVE_EPOLL int n = epoll_wait(self->epoll_fd , self->ev, READQUEUE, timeout); #elif HAVE_KQUEUE struct timespec timeoutspec; timeoutspec.tv_sec = timeout / 1000; timeoutspec.tv_nsec = (timeout % 1000) * 1000000; int n = kevent(self->kqueue_fd, NULL, 0, self->ev, READQUEUE, &timeoutspec); #elif defined(WIN32) int n,key,flags=0; u_long bytes=0; struct socket * _socket; int rc = GetQueuedCompletionStatus(self->iocp, &bytes, (LPDWORD) &key, (LPOVERLAPPED*)&_socket, (u_long) timeout); if (rc == 0) { self->queue_len = 0; return -1; } if(key==self->listen_fd){//accept int peer_socket = socket(AF_INET,SOCK_STREAM,0); if(peer_socket== INVALID_SOCKET){ printf("create socket error:%d \n",WSAGetLastError()); self->queue_len = 0; return -1; } struct socket * s2=_add_client(self,peer_socket); BOOL bRet = lpfnAcceptEx(self->listen_fd,peer_socket , s2->data, 0, sizeof(SOCKADDR_IN)+16, sizeof(SOCKADDR_IN)+16, &bytes, &(s2->ol)); if (bRet == FALSE) { if (WSAGetLastError() != ERROR_IO_PENDING){ printf("WSAIoctl error:%d \n",WSAGetLastError()); self->queue_len = 0; return -1; } } if (setsockopt(_socket->fd, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (char*)&(self->listen_fd), sizeof(self->listen_fd)) == SOCKET_ERROR) { printf("set opt error:%d \n",WSAGetLastError()); self->queue_len = 0; return -1; } //recv zero data for iocp CreateIoCompletionPort(_socket->fd,self->iocp,_socket->fd,0); ZeroMemory(&(_socket->ol),sizeof(OVERLAPPED)); if (WSARecv(_socket->fd, &(_socket->buffer),1, &bytes, &flags, &(_socket->ol), NULL) == SOCKET_ERROR) { DWORD error; error = GetLastError(); printf("GetLastError is : %d , recvBytes = %d \n",error,bytes); } n=-1; }else{ //read n=1; self->ev[0]=_socket; } #endif if (n == -1) { self->queue_len = 0; return -1; } self->queue_len = n; return n; }
struct mread_pool * mread_create(uint32_t addr, int port , int max , int buffer_size) { int listen_fd = socket(AF_INET, SOCK_STREAM, 0); if (listen_fd == -1) { return NULL; } if ( -1 == _set_nonblocking(listen_fd) ) { return NULL; } int reuse = 1; setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int)); struct sockaddr_in my_addr; memset(&my_addr, 0, sizeof(struct sockaddr_in)); my_addr.sin_family = AF_INET; my_addr.sin_port = htons(port); my_addr.sin_addr.s_addr = addr; // printf("MREAD bind %s:%u\n",inet_ntoa(my_addr.sin_addr),ntohs(my_addr.sin_port)); if (bind(listen_fd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) { close(listen_fd); return NULL; } if (listen(listen_fd, BACKLOG) == -1) { close(listen_fd); return NULL; } struct mread_pool * self = malloc(sizeof(*self)); self->max_connection = max; self->closed = 0; self->active = -1; self->skip = 0; self->sockets = _create_sockets(max); self->free_socket = &self->sockets[0]; self->queue_len = 0; self->queue_head = 0; if (buffer_size == 0) { self->rb = _create_rb(RINGBUFFER_DEFAULT); } else { self->rb = _create_rb(buffer_size); } #ifdef HAVE_EPOLL int epoll_fd = epoll_create(max + 1); if (epoll_fd == -1) { close(listen_fd); return NULL; } struct epoll_event ev; ev.events = EPOLLIN; ev.data.ptr = LISTENSOCKET; if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listen_fd, &ev) == -1) { close(listen_fd); close(epoll_fd); return NULL; } #elif HAVE_KQUEUE int kqueue_fd = kqueue(); if (kqueue_fd == -1) { close(listen_fd); return NULL; } struct kevent ke; EV_SET(&ke, listen_fd, EVFILT_READ, EV_ADD, 0, 0, LISTENSOCKET); if (kevent(kqueue_fd, &ke, 1, NULL, 0, NULL) == -1) { close(listen_fd); close(kqueue_fd); return NULL; } #elif defined(_WIN32) HANDLE iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0,2);//todo fix 2 if(iocp == NULL){ printf("error:create iocp:%d \n",WSAGetLastError()); return NULL; } CreateIoCompletionPort((HANDLE)listen_fd,iocp,listen_fd, 0); GUID guidAcceptEx = WSAID_ACCEPTEX; DWORD dwBytes = 0; if (!WSAIoctl(listen_fd, SIO_GET_EXTENSION_FUNCTION_POINTER, &guidAcceptEx, sizeof(guidAcceptEx), &lpfnAcceptEx, sizeof(lpfnAcceptEx), &dwBytes, NULL, NULL) == 0) { printf("WSAIoctl error:%d \n",WSAGetLastError()); return NULL; } int peer_socket = socket(AF_INET,SOCK_STREAM,0); if(peer_socket== INVALID_SOCKET){ printf("create socket error:%d \n",WSAGetLastError()); return NULL; } struct socket * s2=_add_client(self,peer_socket); BOOL bRet = lpfnAcceptEx(listen_fd,peer_socket,s2->data, 0, sizeof(SOCKADDR_IN)+16, sizeof(SOCKADDR_IN)+16, &dwBytes, &(s2->ol)); if (bRet == FALSE) { if (WSAGetLastError() != ERROR_IO_PENDING){ printf("WSAIoctl error:%d \n",WSAGetLastError()); return NULL; } } #endif self->listen_fd = listen_fd; #ifdef HAVE_EPOLL self->epoll_fd = epoll_fd; #elif HAVE_KQUEUE self->kqueue_fd = kqueue_fd; #elif defined(_WIN32) self->iocp= iocp; #endif return self; }