voidlt_mode(epoll_event *events, int number, int epoll_fd, int listen_fd){ char buf[512]; for (int i = 0; i < number; ++i) { int sock_fd = events[i].data.fd; if (sock_fd == listen_fd) { sockaddr_in client_socket_addr{}; socklen_t sock_len; int conn_fd = accept(listen_fd, (sockaddr *)&client_socket_addr, &sock_len); monitorEventForFd(epoll_fd, conn_fd, false); //使用ET模式监听客户端socket fd
} elseif (events[i].events & EPOLLIN) {//客户端socket fd有数据可读 printf("client socket fd %d is readable\n", sock_fd); memset(buf, 0, BUFFER_SIZE); int ret = recv(sock_fd, buf, BUFFER_SIZE-1, 0); if (ret <= 0) { close(sock_fd); continue; } printf("sock fd %d get %d bytes of content: %s\n", sock_fd, ret, buf); } else { printf("other event happen in le mode\n"); } } }
voidet_mode(epoll_event *events, int number, int epoll_fd, int listen_fd){ char buf[BUFFER_SIZE]; for (int i = 0; i < number; ++i) { int sock_fd = events[i].data.fd; if (sock_fd == listen_fd) { sockaddr_in client_socket_addr{}; socklen_t sock_len; int conn_fd = accept(listen_fd, (sockaddr *)&client_socket_addr, &sock_len); monitorEventForFd(epoll_fd, conn_fd, true); //使用ET模式监听客户端socket fd
} elseif (events[i].events & EPOLLIN) { printf("client socket fd %d is readable\n", sock_fd); while (true) { //循环读,直到无数据可读 memset(buf, 0, BUFFER_SIZE); int ret = recv(sock_fd, buf, BUFFER_SIZE-1, 0); if (ret < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) { //对于非阻塞io,下面的条件成立表示数据已经全部读取完毕, //此后epoll 就能再次触发该sock fd上的EPOLLIN事件,以驱动下一次读操作 printf("read later\n"); break; } close(sock_fd); break; } elseif (ret == 0) { close(sock_fd); } else { printf("sock fd %d get %d bytes of content: %s\n", sock_fd, ret, buf); } } } else { printf("other event happen in et mode\n"); } }
}
intmain(){ sockaddr_in server_sock_addr{}; server_sock_addr.sin_family = AF_INET; inet_pton(AF_INET, "localhost", &server_sock_addr.sin_addr); server_sock_addr.sin_port = htons(9000); int server_fd = socket(PF_INET, SOCK_STREAM, 0); bind(server_fd, (sockaddr *)&server_sock_addr, sizeof(server_sock_addr)); listen(server_fd, 5); epoll_event events[MAX_EVENT_NUM]; int epoll_fd = epoll_create(5); monitorEventForFd(epoll_fd, server_fd, true);//monitor server socket fd use et mode while (true) { int ret = epoll_wait(epoll_fd, events, MAX_EVENT_NUM, -1); if (ret < 0) { printf("epoll wait fail\n"); break; } lt_mode(events, ret, epoll_fd, server_fd); //LT mode to process client connection // et_mode(events, ret, epoll_fd, server_fd);//ET mode to process client connection } close(server_fd); return0; }
如果管道的写端文件描述符fd[1]的引用计数减少至0,即没有任何进程需要往管道中写入数据,则针对管道的读端文件描述符fd[0]的read操作将返回0,即读取到了文件结束标记(End of File, EOF);反之,如果管道的读端文件描述符fd[0]的引用计数减少至0,即没有任何进程需要从管道读取数据,则针对管道的写端文件描述符fd[1]的write操作将失败,并引发SIGPIPE信号。
#version version_number in type in_variable_name; in type in_variable_name;
out type out_variable_name; uniform type uniform_name; void main() { // process input(s) and do some weird graphics stuff ... // output processed stuff to output variable out_variable_name = weird_stuff_we_processed; }
fragment shader要求必须有一个vec4类型的颜色输出变量,因为fragment shader的作用就是生成最后像素的颜色值。如果你没有定义这个颜色输出,OpenGL最后输出的可能就是纯黑色或者纯白色。
So if we want to send data from one shader to the other we’d have to declare an output in the sending shader and a similar input in the receiving shader. When the types and the names are equal on both sides OpenGL will link those variables together and then it is possible to send data between shaders (this is done when linking a program object).
Because of their parallel nature, graphics cards of today have thousands of small processing cores to quickly process your data within the graphics pipeline. The processing cores run small programs on the GPU for each step of the pipeline. These small programs are called shaders.
In order for OpenGL to know what to make of your collection of coordinates and color values OpenGL requires you to hint what kind of render types you want to form with the data. Do we want the data rendered as a collection of points, a collection of triangles or perhaps just one long line? Those hints are called primitives and are given to OpenGL while calling any of the drawing commands. Some of these hints are GL_POINTS, GL_TRIANGLES and GL_LINE_STRIP.