├── epoll ├── http-server │ ├── .gitignore │ ├── accepter.h │ ├── tcp_server.h │ ├── handle_msg.h │ ├── CMakeLists.txt │ ├── common.h │ ├── server.c │ ├── buffer_map.h │ ├── tcp_server.c │ ├── buffer.h │ ├── epoll.h │ ├── accepter.c │ ├── buffer_map.c │ ├── handle_msg.c │ ├── epoll.c │ └── buffer.c ├── CMakeLists.txt └── epoll.c ├── poll ├── http-server │ ├── .gitignore │ ├── accepter.h │ ├── tcp_server.h │ ├── handle_msg.h │ ├── CMakeLists.txt │ ├── common.h │ ├── server.c │ ├── buffer_map.h │ ├── tcp_server.c │ ├── buffer.h │ ├── poll.h │ ├── accepter.c │ ├── buffer_map.c │ ├── handle_msg.c │ ├── poll.c │ └── buffer.c ├── CMakeLists.txt └── poll.c ├── cmake ├── lib │ ├── config.h.cmake │ ├── http_response.h │ ├── reader.h │ ├── thread_pool.h │ ├── CMakeLists.txt │ ├── common.h │ ├── tcp_server.h │ ├── http_response.c │ ├── tcp_server.c │ ├── reader.c │ └── thread_pool.c ├── build │ └── README.md └── src │ ├── main.c │ └── CMakeLists.txt ├── README.md ├── select ├── CMakeLists.txt └── select.c ├── non-blocking-socket ├── thread_pool.h ├── CMakeLists.txt ├── common.h ├── tcp_server.h ├── server.c ├── buffer_map.h ├── tcp_server.c ├── buffer.h ├── buffer_map.c ├── buffer.c └── thread_pool.c ├── buffer ├── CMakeLists.txt ├── buffer.h ├── client.c ├── server.c └── buffer.c ├── c-plus-plus ├── xstring │ ├── main.cpp │ └── xstring.hpp ├── thread │ ├── main.cpp │ └── thread-pool.hpp └── operator-reload │ └── main.cpp ├── .gitignore └── LICENSE /epoll/http-server/.gitignore: -------------------------------------------------------------------------------- 1 | src -------------------------------------------------------------------------------- /poll/http-server/.gitignore: -------------------------------------------------------------------------------- 1 | src -------------------------------------------------------------------------------- /cmake/lib/config.h.cmake: -------------------------------------------------------------------------------- 1 | #cmakedefine WORKER_POOL_SIZE @WORKER_POOL_SIZE@ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # c-program 2 | C program and network programming series articles demo program 3 | -------------------------------------------------------------------------------- /cmake/build/README.md: -------------------------------------------------------------------------------- 1 | ```shell 2 | [benggee]# cd build 3 | [benggee]# cmake ../src 4 | [benggee]# cmake --build . 5 | ``` -------------------------------------------------------------------------------- /poll/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | set(CMAKE_C_STANDARD 99) 4 | 5 | project(poll VERSION 1.1) 6 | 7 | add_executable(poll poll.c) -------------------------------------------------------------------------------- /epoll/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | set(CMAKE_C_STANDARD 99) 4 | 5 | project(epoll VERSION 1.1) 6 | 7 | add_executable(epoll epoll.c) -------------------------------------------------------------------------------- /cmake/lib/http_response.h: -------------------------------------------------------------------------------- 1 | #ifndef __HTTP_RESPONSE_H__ 2 | #define __HTTP_RESPONSE_H__ 3 | 4 | #include "common.h" 5 | 6 | void write_response(int fd); 7 | 8 | #endif -------------------------------------------------------------------------------- /cmake/lib/reader.h: -------------------------------------------------------------------------------- 1 | #ifndef __READER_H__ 2 | #define __READER_H__ 3 | 4 | #include "common.h" 5 | 6 | size_t read_line(int fd, char *buf, size_t size); 7 | 8 | #endif -------------------------------------------------------------------------------- /select/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | set(CMAKE_C_STANDARD 99) 4 | 5 | project(select VERSION 1.0) 6 | 7 | add_executable(select select.c) -------------------------------------------------------------------------------- /epoll/http-server/accepter.h: -------------------------------------------------------------------------------- 1 | #ifndef __ACCEPTER_H__ 2 | #define __ACCEPTER_H__ 3 | 4 | void accept_sock(int serv_fd); 5 | 6 | void make_nonblocking(int fd); 7 | 8 | #endif -------------------------------------------------------------------------------- /poll/http-server/accepter.h: -------------------------------------------------------------------------------- 1 | #ifndef __ACCEPTER_H__ 2 | #define __ACCEPTER_H__ 3 | 4 | void accept_sock(int serv_fd); 5 | 6 | void make_nonblocking(int fd); 7 | 8 | #endif -------------------------------------------------------------------------------- /epoll/http-server/tcp_server.h: -------------------------------------------------------------------------------- 1 | #ifndef __TCP_SERVER_H__ 2 | #define __TCP_SERVER_H__ 3 | 4 | #include "common.h" 5 | #include "buffer_map.h" 6 | 7 | int create_tcp_socket(int port); 8 | 9 | #endif -------------------------------------------------------------------------------- /poll/http-server/tcp_server.h: -------------------------------------------------------------------------------- 1 | #ifndef __TCP_SERVER_H__ 2 | #define __TCP_SERVER_H__ 3 | 4 | #include "common.h" 5 | #include "buffer_map.h" 6 | 7 | int create_tcp_socket(int port); 8 | 9 | #endif -------------------------------------------------------------------------------- /cmake/lib/thread_pool.h: -------------------------------------------------------------------------------- 1 | #ifndef __THREAD_POOL_H__ 2 | #define __THREAD_POOL_H__ 3 | 4 | #include "common.h" 5 | 6 | void *worker(void *arg); 7 | 8 | void *accepter_thread(void *arg); 9 | 10 | #endif -------------------------------------------------------------------------------- /non-blocking-socket/thread_pool.h: -------------------------------------------------------------------------------- 1 | #ifndef __THREAD_POOL_H__ 2 | #define __THREAD_POOL_H__ 3 | 4 | #include "common.h" 5 | 6 | void *worker(void *arg); 7 | 8 | void *accepter_thread(void *arg); 9 | 10 | #endif -------------------------------------------------------------------------------- /buffer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | set(CMAKE_C_STANDARD 11) 4 | 5 | project(buffer VERSION 1.0 LANGUAGES C) 6 | 7 | add_executable(server server.c buffer.c) 8 | 9 | add_executable(client client.c) -------------------------------------------------------------------------------- /epoll/http-server/handle_msg.h: -------------------------------------------------------------------------------- 1 | #ifndef __HANDLE_MSG_H__ 2 | #define __HANDLE_MSG_H__ 3 | 4 | #include "buffer_map.h" 5 | #include "buffer.h" 6 | 7 | 8 | #define MSG_LEN 4 9 | 10 | void do_msg(struct sock_buffer *s_buffer, int sock_fd); 11 | 12 | #endif -------------------------------------------------------------------------------- /poll/http-server/handle_msg.h: -------------------------------------------------------------------------------- 1 | #ifndef __HANDLE_MSG_H__ 2 | #define __HANDLE_MSG_H__ 3 | 4 | #include "buffer_map.h" 5 | #include "buffer.h" 6 | 7 | 8 | #define MSG_LEN 4 9 | 10 | void do_msg(struct sock_buffer *s_buffer, int sock_fd); 11 | 12 | #endif -------------------------------------------------------------------------------- /cmake/lib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB SRC_FILES *.c) 2 | 3 | add_library(mylib SHARED ${SRC_FILES}) 4 | target_link_libraries(mylib pthread) 5 | 6 | if (${POOL_SIZE}) 7 | set(WORKER_POOL_SIZE ${POOL_SIZE}) 8 | endif () 9 | 10 | configure_file(config.h.cmake config.h) -------------------------------------------------------------------------------- /cmake/lib/common.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "config.h" -------------------------------------------------------------------------------- /non-blocking-socket/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | set(CMAKE_C_STANDARD 11) 4 | 5 | project(buffer VERSION 1.0 LANGUAGES C) 6 | 7 | file(GLOB SOURCES *.c) 8 | 9 | add_executable(server ${SOURCES}) 10 | 11 | target_link_libraries(server pthread) -------------------------------------------------------------------------------- /epoll/http-server/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | set(CMAKE_C_STANDARD 11) 4 | 5 | project(buffer VERSION 1.0 LANGUAGES C) 6 | 7 | file(GLOB SOURCES *.c) 8 | 9 | add_executable(server ${SOURCES} server.c) 10 | 11 | target_link_libraries(server pthread) -------------------------------------------------------------------------------- /poll/http-server/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | set(CMAKE_C_STANDARD 11) 4 | 5 | project(buffer VERSION 1.0 LANGUAGES C) 6 | 7 | file(GLOB SOURCES *.c) 8 | 9 | add_executable(server ${SOURCES} server.c) 10 | 11 | target_link_libraries(server pthread) -------------------------------------------------------------------------------- /epoll/http-server/common.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #define WORKER_POOL_SIZE 5 -------------------------------------------------------------------------------- /non-blocking-socket/common.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #define WORKER_POOL_SIZE 5 -------------------------------------------------------------------------------- /poll/http-server/common.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #define WORKER_POOL_SIZE 5 -------------------------------------------------------------------------------- /cmake/lib/tcp_server.h: -------------------------------------------------------------------------------- 1 | #ifndef __TCP_SERVER_H__ 2 | #define __TCP_SERVER_H__ 3 | 4 | #include "common.h" 5 | 6 | struct worker_thread_context { 7 | int fd; 8 | pthread_t thread_id; 9 | pthread_mutex_t mutex; 10 | pthread_cond_t cond; 11 | }; 12 | 13 | int create_tcp_socket(int port); 14 | 15 | #endif -------------------------------------------------------------------------------- /c-plus-plus/xstring/main.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by seepr on 2023/9/17. 3 | // 4 | #include 5 | #include "xstring.hpp" 6 | #include 7 | 8 | int main() { 9 | 10 | 11 | // xstring s1; 12 | // xstring s2(s1); 13 | // xstring s3 = std::move(s1); 14 | 15 | xstring s4 = "hello"; 16 | 17 | std::cout << s4 << std::endl; 18 | 19 | return 0; 20 | } -------------------------------------------------------------------------------- /non-blocking-socket/tcp_server.h: -------------------------------------------------------------------------------- 1 | #ifndef __TCP_SERVER_H__ 2 | #define __TCP_SERVER_H__ 3 | 4 | #include "common.h" 5 | #include "buffer_map.h" 6 | 7 | struct worker_thread_context { 8 | int fd; 9 | pthread_t thread_id; 10 | pthread_mutex_t mutex; 11 | pthread_cond_t cond; 12 | struct buffer_map *buffer_map; 13 | }; 14 | 15 | int create_tcp_socket(int port); 16 | 17 | #endif -------------------------------------------------------------------------------- /cmake/src/main.c: -------------------------------------------------------------------------------- 1 | #include "tcp_server.h" 2 | #include "thread_pool.h" 3 | #include "reader.h" 4 | #include "http_response.h" 5 | 6 | int main(int argc, char *argv[]) { 7 | if (argc != 2) { 8 | perror("usage: ./server "); 9 | exit(1); 10 | } 11 | 12 | int sock_fd = create_tcp_socket(atoi(argv[1])); 13 | 14 | printf("server started on port %s\n", argv[1]); 15 | 16 | accepter_thread((void *)&sock_fd); 17 | } -------------------------------------------------------------------------------- /epoll/http-server/server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "tcp_server.h" 4 | #include "accepter.h" 5 | 6 | int main(int argc, char *argv[]) { 7 | if (argc != 2) { 8 | perror("usage: ./server "); 9 | exit(1); 10 | } 11 | 12 | int sock_fd = create_tcp_socket(atoi(argv[1])); 13 | 14 | printf("server started on port %s\n", argv[1]); 15 | 16 | accept_sock(sock_fd); 17 | } 18 | 19 | -------------------------------------------------------------------------------- /poll/http-server/server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "tcp_server.h" 4 | #include "accepter.h" 5 | 6 | int main(int argc, char *argv[]) { 7 | if (argc != 2) { 8 | perror("usage: ./server "); 9 | exit(1); 10 | } 11 | 12 | int sock_fd = create_tcp_socket(atoi(argv[1])); 13 | 14 | printf("server started on port %s\n", argv[1]); 15 | 16 | accept_sock(sock_fd); 17 | } 18 | 19 | -------------------------------------------------------------------------------- /non-blocking-socket/server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "tcp_server.h" 4 | #include "thread_pool.h" 5 | 6 | int main(int argc, char *argv[]) { 7 | if (argc != 2) { 8 | perror("usage: ./server "); 9 | exit(1); 10 | } 11 | 12 | int sock_fd = create_tcp_socket(atoi(argv[1])); 13 | 14 | printf("server started on port %s\n", argv[1]); 15 | 16 | accepter_thread((void *)&sock_fd); 17 | } 18 | 19 | -------------------------------------------------------------------------------- /buffer/buffer.h: -------------------------------------------------------------------------------- 1 | 2 | #define BUFFER_SIZE 65535 3 | 4 | struct buffer { 5 | char *data; // bufer data 6 | int r_idx; // read index 7 | int w_idx; // write index 8 | int size; // buffer size 9 | }; 10 | 11 | struct buffer *new_buffer(); 12 | 13 | void buffer_free(struct buffer *buf); 14 | 15 | int buffer_append(struct buffer *buf, char *data, size_t len); 16 | 17 | int buffer_read_from_socket(struct buffer *buf, int sock_fd); 18 | 19 | int buffer_write_to_socket(struct buffer *buf, int sock_fd); -------------------------------------------------------------------------------- /poll/http-server/buffer_map.h: -------------------------------------------------------------------------------- 1 | #ifndef __BUFFER_MAP_H__ 2 | #define __BUFFER_MAP_H__ 3 | 4 | #include 5 | #include "buffer.h" 6 | 7 | struct sock_buffer { 8 | struct buffer *w_buffer; 9 | struct buffer *r_buffer; 10 | }; 11 | 12 | struct buffer_map { 13 | struct sock_buffer **s_buffer; 14 | int max_idx; 15 | }; 16 | 17 | struct sock_buffer *new_sock_buffer(); 18 | 19 | struct buffer_map *new_buffer_map(); 20 | 21 | int allocation_buffer_map(struct buffer_map *map, int slot); 22 | 23 | void free_buffer_map(struct buffer_map *map); 24 | 25 | #endif -------------------------------------------------------------------------------- /epoll/http-server/buffer_map.h: -------------------------------------------------------------------------------- 1 | #ifndef __BUFFER_MAP_H__ 2 | #define __BUFFER_MAP_H__ 3 | 4 | #include 5 | #include "buffer.h" 6 | 7 | struct sock_buffer { 8 | struct buffer *w_buffer; 9 | struct buffer *r_buffer; 10 | }; 11 | 12 | struct buffer_map { 13 | struct sock_buffer **s_buffer; 14 | int max_idx; 15 | }; 16 | 17 | struct sock_buffer *new_sock_buffer(); 18 | 19 | struct buffer_map *new_buffer_map(); 20 | 21 | int allocation_buffer_map(struct buffer_map *map, int slot); 22 | 23 | void free_buffer_map(struct buffer_map *map); 24 | 25 | #endif -------------------------------------------------------------------------------- /non-blocking-socket/buffer_map.h: -------------------------------------------------------------------------------- 1 | #ifndef __BUFFER_MAP_H__ 2 | #define __BUFFER_MAP_H__ 3 | 4 | #include 5 | #include "buffer.h" 6 | 7 | struct sock_buffer { 8 | struct buffer *w_buffer; 9 | struct buffer *r_buffer; 10 | }; 11 | 12 | struct buffer_map { 13 | struct sock_buffer **s_buffer; 14 | int max_idx; 15 | }; 16 | 17 | struct sock_buffer *new_sock_buffer(); 18 | 19 | struct buffer_map *new_buffer_map(); 20 | 21 | int allocation_buffer_map(struct buffer_map *map, int slot); 22 | 23 | void free_buffer_map(struct buffer_map *map); 24 | 25 | #endif -------------------------------------------------------------------------------- /cmake/lib/http_response.c: -------------------------------------------------------------------------------- 1 | #include "http_response.h" 2 | 3 | void write_response(int fd) { 4 | send(fd, "HTTP/1.1 200 OK\r\n", strlen("HTTP/1.1 200 OK\r\n"), 0); 5 | send(fd, "Host: 127.0.0.1:3000\r\n", strlen("Host: 127.0.0.1:3000\r\n"), 0); 6 | send(fd, "Content-Type: text/html; charset=UTF-8\r\n", strlen("Content-Type: text/html; charset=UTF-8\r\n"), 0); 7 | send(fd, "\r\n", strlen("\r\n"), 0); 8 | 9 | char *body = "hello

This is My HTTP Server

"; 10 | send(fd, body, strlen(body), 0); 11 | 12 | close(fd); 13 | } -------------------------------------------------------------------------------- /cmake/lib/tcp_server.c: -------------------------------------------------------------------------------- 1 | #include "tcp_server.h" 2 | 3 | int create_tcp_socket(int port) { 4 | int sock_fd; 5 | struct sockaddr_in serv_addr; 6 | 7 | sock_fd = socket(AF_INET, SOCK_STREAM, 0); 8 | bzero(&serv_addr, sizeof(serv_addr)); 9 | 10 | serv_addr.sin_family = AF_INET; 11 | serv_addr.sin_port = htons(port); 12 | serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); 13 | 14 | int on = 1; 15 | setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); 16 | 17 | bind(sock_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); 18 | 19 | listen(sock_fd, 1024); 20 | 21 | return sock_fd; 22 | } -------------------------------------------------------------------------------- /epoll/http-server/tcp_server.c: -------------------------------------------------------------------------------- 1 | #include "tcp_server.h" 2 | 3 | int create_tcp_socket(int port) { 4 | int sock_fd; 5 | struct sockaddr_in serv_addr; 6 | 7 | sock_fd = socket(AF_INET, SOCK_STREAM, 0); 8 | bzero(&serv_addr, sizeof(serv_addr)); 9 | 10 | serv_addr.sin_family = AF_INET; 11 | serv_addr.sin_port = htons(port); 12 | serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); 13 | 14 | int on = 1; 15 | setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); 16 | 17 | bind(sock_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); 18 | 19 | listen(sock_fd, 1024); 20 | 21 | return sock_fd; 22 | } -------------------------------------------------------------------------------- /poll/http-server/tcp_server.c: -------------------------------------------------------------------------------- 1 | #include "tcp_server.h" 2 | 3 | int create_tcp_socket(int port) { 4 | int sock_fd; 5 | struct sockaddr_in serv_addr; 6 | 7 | sock_fd = socket(AF_INET, SOCK_STREAM, 0); 8 | bzero(&serv_addr, sizeof(serv_addr)); 9 | 10 | serv_addr.sin_family = AF_INET; 11 | serv_addr.sin_port = htons(port); 12 | serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); 13 | 14 | int on = 1; 15 | setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); 16 | 17 | bind(sock_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); 18 | 19 | listen(sock_fd, 1024); 20 | 21 | return sock_fd; 22 | } -------------------------------------------------------------------------------- /non-blocking-socket/tcp_server.c: -------------------------------------------------------------------------------- 1 | #include "tcp_server.h" 2 | 3 | int create_tcp_socket(int port) { 4 | int sock_fd; 5 | struct sockaddr_in serv_addr; 6 | 7 | sock_fd = socket(AF_INET, SOCK_STREAM, 0); 8 | bzero(&serv_addr, sizeof(serv_addr)); 9 | 10 | serv_addr.sin_family = AF_INET; 11 | serv_addr.sin_port = htons(port); 12 | serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); 13 | 14 | int on = 1; 15 | setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); 16 | 17 | bind(sock_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); 18 | 19 | listen(sock_fd, 1024); 20 | 21 | return sock_fd; 22 | } -------------------------------------------------------------------------------- /epoll/http-server/buffer.h: -------------------------------------------------------------------------------- 1 | #ifndef __BUFFER_H__ 2 | #define __BUFFER_H__ 3 | 4 | 5 | #define BUFFER_SIZE 65535 6 | 7 | struct buffer { 8 | char *data; // bufer data 9 | int r_idx; // read index 10 | int w_idx; // write index 11 | int size; // buffer size 12 | }; 13 | 14 | struct buffer *new_buffer(); 15 | 16 | void buffer_free(struct buffer *buf); 17 | 18 | char buffer_read_char(struct buffer *buf); 19 | 20 | int buffer_append(struct buffer *buf, char *data, size_t len); 21 | 22 | int buffer_read_from_socket(struct buffer *buf, int sock_fd); 23 | 24 | int buffer_write_to_socket(struct buffer *buf, int sock_fd); 25 | 26 | #endif -------------------------------------------------------------------------------- /poll/http-server/buffer.h: -------------------------------------------------------------------------------- 1 | #ifndef __BUFFER_H__ 2 | #define __BUFFER_H__ 3 | 4 | 5 | #define BUFFER_SIZE 65535 6 | 7 | struct buffer { 8 | char *data; // bufer data 9 | int r_idx; // read index 10 | int w_idx; // write index 11 | int size; // buffer size 12 | }; 13 | 14 | struct buffer *new_buffer(); 15 | 16 | void buffer_free(struct buffer *buf); 17 | 18 | char buffer_read_char(struct buffer *buf); 19 | 20 | int buffer_append(struct buffer *buf, char *data, size_t len); 21 | 22 | int buffer_read_from_socket(struct buffer *buf, int sock_fd); 23 | 24 | int buffer_write_to_socket(struct buffer *buf, int sock_fd); 25 | 26 | #endif -------------------------------------------------------------------------------- /non-blocking-socket/buffer.h: -------------------------------------------------------------------------------- 1 | #ifndef __BUFFER_H__ 2 | #define __BUFFER_H__ 3 | 4 | 5 | #define BUFFER_SIZE 65535 6 | 7 | struct buffer { 8 | char *data; // bufer data 9 | int r_idx; // read index 10 | int w_idx; // write index 11 | int size; // buffer size 12 | }; 13 | 14 | struct buffer *new_buffer(); 15 | 16 | void buffer_free(struct buffer *buf); 17 | 18 | char buffer_read_char(struct buffer *buf); 19 | 20 | int buffer_append(struct buffer *buf, char *data, size_t len); 21 | 22 | int buffer_read_from_socket(struct buffer *buf, int sock_fd); 23 | 24 | int buffer_write_to_socket(struct buffer *buf, int sock_fd); 25 | 26 | #endif -------------------------------------------------------------------------------- /c-plus-plus/thread/main.cpp: -------------------------------------------------------------------------------- 1 | #include "thread-pool.hpp" 2 | #include 3 | 4 | using namespace std; 5 | 6 | void threadFunc(int a) { 7 | cout << "a=" << a << endl; 8 | } 9 | 10 | class A { 11 | public: 12 | A() = default; 13 | int run(int a, int b) { 14 | return a + b; 15 | } 16 | }; 17 | 18 | int main() { 19 | TPool p1; 20 | p1.init(10); 21 | p1.start(); 22 | p1.exec(threadFunc, 100); 23 | p1.exec(threadFunc, 200); 24 | 25 | A a1; 26 | auto fu1 = p1.exec(std::bind(&A::run, &a1, std::placeholders::_1, std::placeholders::_2), 10, 20); 27 | int ret = fu1.get(); 28 | std::cout << "res:" << ret << std::endl; 29 | 30 | p1.waitDone(); 31 | return 0; 32 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Object files 5 | *.o 6 | *.ko 7 | *.obj 8 | *.elf 9 | 10 | # Linker output 11 | *.ilk 12 | *.map 13 | *.exp 14 | 15 | # Precompiled Headers 16 | *.gch 17 | *.pch 18 | 19 | # Libraries 20 | *.lib 21 | *.a 22 | *.la 23 | *.lo 24 | 25 | # Shared objects (inc. Windows DLLs) 26 | *.dll 27 | *.so 28 | *.so.* 29 | *.dylib 30 | 31 | # Executables 32 | *.exe 33 | *.out 34 | *.app 35 | *.i*86 36 | *.x86_64 37 | *.hex 38 | 39 | # Debug files 40 | *.dSYM/ 41 | *.su 42 | *.idb 43 | *.pdb 44 | 45 | # Kernel Module Compile Results 46 | *.mod* 47 | *.cmd 48 | .tmp_versions/ 49 | modules.order 50 | Module.symvers 51 | Mkfile.old 52 | dkms.conf 53 | .idea 54 | cmake-build-debug 55 | cmake-build-debug-wsl -------------------------------------------------------------------------------- /cmake/lib/reader.c: -------------------------------------------------------------------------------- 1 | #include "reader.h" 2 | 3 | size_t read_line(int fd, char *buf, size_t size) { 4 | size_t i = 0; 5 | ssize_t n; 6 | char c = '\0'; 7 | 8 | while((i < size) && (c != '\n')) { 9 | n = recv(fd, &c, 1, 0); 10 | if (n > 0) { 11 | if (c == '\r') { 12 | n = recv(fd, &c, 1, MSG_PEEK); 13 | if ((n > 0) && (c == '\n')) { 14 | recv(fd, &c, 1, 0); 15 | } else { 16 | c = '\n'; 17 | } 18 | } 19 | buf[i] = c; 20 | i++; 21 | } else { 22 | c = '\n'; 23 | } 24 | } 25 | buf[i] = '\0'; 26 | return i; 27 | } -------------------------------------------------------------------------------- /poll/http-server/poll.h: -------------------------------------------------------------------------------- 1 | #ifndef __POLL_H__ 2 | #define __POLL_H__ 3 | 4 | #include 5 | 6 | #define MAX_POLL_SIZE 1024 7 | 8 | struct poll_dispatcher { 9 | int size; // max fd nums 10 | int done; // is done 0 not done 1 done 11 | int pair[2]; 12 | pthread_cond_t cond; 13 | pthread_mutex_t mutex; 14 | struct pollfd *fds; 15 | struct buffer_map *buffer_map; 16 | }; 17 | 18 | struct poll_dispatcher *poll_new(); 19 | 20 | int poll_add(struct poll_dispatcher *poll_dis, int fd); 21 | 22 | int poll_del(struct poll_dispatcher *poll_dis, int fd); 23 | 24 | int poll_dispatch(struct poll_dispatcher *poll_dis); 25 | 26 | void poll_free(struct poll_dispatcher *poll_dis); 27 | 28 | #endif -------------------------------------------------------------------------------- /epoll/http-server/epoll.h: -------------------------------------------------------------------------------- 1 | #ifndef __POLL_H__ 2 | #define __POLL_H__ 3 | 4 | #include 5 | #include 6 | 7 | #define MAX_POLL_SIZE 1024 8 | 9 | struct epoll_dispatcher { 10 | int size; // max fd nums 11 | int done; // is done 0 not done 1 done 12 | int epfd; 13 | int pair[2]; 14 | pthread_cond_t cond; 15 | pthread_mutex_t mutex; 16 | struct epoll_event *events; 17 | struct buffer_map *buffer_map; 18 | }; 19 | 20 | struct epoll_dispatcher *epoll_new(); 21 | 22 | int epoll_add(struct epoll_dispatcher *poll_dis, int fd); 23 | 24 | int epoll_del(struct epoll_dispatcher *poll_dis, int fd); 25 | 26 | int epoll_dispatch(struct epoll_dispatcher *poll_dis); 27 | 28 | void epoll_free(struct epoll_dispatcher *poll_dis); 29 | 30 | #endif -------------------------------------------------------------------------------- /cmake/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | set(CMAKE_C_STANDARD 11) 4 | 5 | project(http-server VERSION 1.0 LANGUAGES C) 6 | 7 | 8 | include_directories(${CMAKE_SOURCE_DIR}/../include) 9 | 10 | add_subdirectory(${CMAKE_SOURCE_DIR}/../lib ${CMAKE_SOURCE_DIR}/../lib/build) 11 | 12 | 13 | add_executable(http-server main.c) 14 | 15 | include_directories(${CMAKE_SOURCE_DIR}/../lib) 16 | 17 | target_include_directories(http-server PUBLIC ${CMAKE_SOURCE_DIR}/../lib) 18 | 19 | target_link_libraries(http-server PRIVATE ${CMAKE_SOURCE_DIR}/../build/lib/libmylib.so) 20 | 21 | install(TARGETS http-server DESTINATION ${CMAKE_SOURCE_DIR}/../build/bin) 22 | install(FILES ${CMAKE_SOURCE_DIR}/../lib/build/config.h DESTINATION ${CMAKE_SOURCE_DIR}/../include) 23 | install(FILES ${CMAKE_SOURCE_DIR}/../lib/build/libmylib.so DESTINATION ${CMAKE_SOURCE_DIR}/../build/lib) -------------------------------------------------------------------------------- /buffer/client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | 13 | int main(int argc, char *argv[]) { 14 | int sock_fd; 15 | struct sockaddr_in serv_addr; 16 | sock_fd = socket(AF_INET, SOCK_STREAM, 0); 17 | 18 | serv_addr.sin_family = AF_INET; 19 | serv_addr.sin_port = htons(3000); 20 | inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr); 21 | 22 | int ret = connect(sock_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); 23 | if (ret < 0) { 24 | perror("connect error"); 25 | exit(1); 26 | } 27 | 28 | char buf[1024]; 29 | 30 | while(1) { 31 | memset(buf, 0, sizeof(buf)); 32 | fgets(buf, sizeof(buf), stdin); 33 | write(sock_fd, buf, sizeof(buf)); 34 | printf("write done.\n"); 35 | } 36 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 程序员班吉 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /poll/http-server/accepter.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "accepter.h" 9 | #include "poll.h" 10 | #include "tcp_server.h" 11 | 12 | void *worker(void *arg) { 13 | struct poll_dispatcher *poll_dis = (struct poll_dispatcher *)arg; 14 | 15 | printf("poll-size: %d\n", poll_dis->size); 16 | 17 | poll_dispatch(poll_dis); 18 | 19 | poll_free(poll_dis); 20 | } 21 | 22 | void accept_sock(int serv_fd) { 23 | int conn_fd; 24 | 25 | struct poll_dispatcher *poll_dis = poll_new(); 26 | 27 | // make_nonblocking(serv_fd); 28 | 29 | struct sockaddr_in client_addr; 30 | socklen_t cli_len = sizeof(client_addr); 31 | 32 | pthread_t thread_id; 33 | 34 | pthread_create(&thread_id, NULL, worker, (void *)poll_dis); 35 | 36 | pthread_mutex_lock(&poll_dis->mutex); 37 | while(!poll_dis->done) 38 | pthread_cond_wait(&poll_dis->cond, &poll_dis->mutex); 39 | pthread_mutex_unlock(&poll_dis->mutex); 40 | 41 | while(1) { 42 | memset(&client_addr, 0, sizeof(client_addr)); 43 | 44 | conn_fd = accept(serv_fd, (struct sockaddr *)&client_addr, &cli_len); 45 | if (conn_fd < 0) { 46 | perror("accept error"); 47 | continue; 48 | } 49 | 50 | make_nonblocking(conn_fd); 51 | 52 | printf("accept a new connection: %d\n", conn_fd); 53 | 54 | if (allocation_buffer_map(poll_dis->buffer_map, conn_fd) < 0) { 55 | perror("allocation_buffer_map error"); 56 | continue; 57 | } 58 | 59 | poll_add(poll_dis, conn_fd); 60 | } 61 | } 62 | 63 | void make_nonblocking(int fd) { 64 | fcntl(fd, F_SETFL, O_NONBLOCK); 65 | } -------------------------------------------------------------------------------- /epoll/http-server/accepter.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "accepter.h" 9 | #include "epoll.h" 10 | #include "tcp_server.h" 11 | 12 | void *worker(void *arg) { 13 | struct epoll_dispatcher *poll_dis = (struct epoll_dispatcher *)arg; 14 | 15 | printf("poll-size: %d\n", poll_dis->size); 16 | 17 | epoll_dispatch(poll_dis); 18 | 19 | epoll_free(poll_dis); 20 | } 21 | 22 | void accept_sock(int serv_fd) { 23 | int conn_fd; 24 | 25 | struct epoll_dispatcher *poll_dis = epoll_new(); 26 | 27 | // make_nonblocking(serv_fd); 28 | 29 | struct sockaddr_in client_addr; 30 | socklen_t cli_len = sizeof(client_addr); 31 | 32 | pthread_t thread_id; 33 | 34 | pthread_create(&thread_id, NULL, worker, (void *)poll_dis); 35 | 36 | pthread_mutex_lock(&poll_dis->mutex); 37 | while(!poll_dis->done) 38 | pthread_cond_wait(&poll_dis->cond, &poll_dis->mutex); 39 | pthread_mutex_unlock(&poll_dis->mutex); 40 | 41 | while(1) { 42 | memset(&client_addr, 0, sizeof(client_addr)); 43 | 44 | conn_fd = accept(serv_fd, (struct sockaddr *)&client_addr, &cli_len); 45 | if (conn_fd < 0) { 46 | perror("accept error"); 47 | continue; 48 | } 49 | 50 | make_nonblocking(conn_fd); 51 | 52 | printf("accept a new connection: %d\n", conn_fd); 53 | 54 | if (allocation_buffer_map(poll_dis->buffer_map, conn_fd) < 0) { 55 | perror("allocation_buffer_map error"); 56 | continue; 57 | } 58 | 59 | epoll_add(poll_dis, conn_fd); 60 | } 61 | } 62 | 63 | void make_nonblocking(int fd) { 64 | fcntl(fd, F_SETFL, O_NONBLOCK); 65 | } -------------------------------------------------------------------------------- /epoll/http-server/buffer_map.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "buffer.h" 5 | #include "buffer_map.h" 6 | 7 | struct sock_buffer *new_sock_buffer() { 8 | struct sock_buffer *s_buf = malloc(sizeof(struct sock_buffer)); 9 | if (s_buf == NULL) { 10 | return NULL; 11 | } 12 | s_buf->r_buffer = new_buffer(); 13 | s_buf->w_buffer = new_buffer(); 14 | return s_buf; 15 | } 16 | 17 | struct buffer_map *new_buffer_map() { 18 | struct buffer_map *map = malloc(sizeof(struct buffer_map)); 19 | if (map == NULL) { 20 | return NULL; 21 | } 22 | map->max_idx = 0; 23 | map->s_buffer = NULL; 24 | return map; 25 | } 26 | 27 | int allocation_buffer_map(struct buffer_map *map, int slot) { 28 | if (map->max_idx > slot) { 29 | map->s_buffer[slot] = new_sock_buffer(); 30 | return 0; 31 | } 32 | 33 | int max_idx = map->max_idx ? map->max_idx : 32; 34 | struct sock_bufferr **tmp = NULL; 35 | 36 | while(max_idx <= slot) { 37 | max_idx <<= 1; // max_idx = max_idx * 2 38 | } 39 | 40 | tmp = realloc(map->s_buffer, max_idx * sizeof(struct sock_buffer *)); 41 | if (tmp == NULL) { 42 | return -1; 43 | } 44 | 45 | struct sock_buffer *s_buf = new_sock_buffer(); 46 | if (s_buf == NULL) { 47 | return -1; 48 | } 49 | 50 | tmp[slot] = s_buf; 51 | 52 | map->max_idx = max_idx; 53 | map->s_buffer = tmp; 54 | 55 | return 0; 56 | } 57 | 58 | void free_buffer_map(struct buffer_map *map) { 59 | if (map->max_idx == NULL) { 60 | return; 61 | } 62 | 63 | int i; 64 | for (i = 0; i < map->max_idx; ++i) { 65 | if (map->s_buffer[i] != NULL) { 66 | free(map->s_buffer[i]); 67 | } 68 | free(map->s_buffer); 69 | map->s_buffer = NULL; 70 | } 71 | map->s_buffer = 0; 72 | } -------------------------------------------------------------------------------- /non-blocking-socket/buffer_map.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "buffer.h" 5 | #include "buffer_map.h" 6 | 7 | struct sock_buffer *new_sock_buffer() { 8 | struct sock_buffer *s_buf = malloc(sizeof(struct sock_buffer)); 9 | if (s_buf == NULL) { 10 | return NULL; 11 | } 12 | s_buf->r_buffer = new_buffer(); 13 | s_buf->w_buffer = new_buffer(); 14 | return s_buf; 15 | } 16 | 17 | struct buffer_map *new_buffer_map() { 18 | struct buffer_map *map = malloc(sizeof(struct buffer_map)); 19 | if (map == NULL) { 20 | return NULL; 21 | } 22 | map->max_idx = 0; 23 | map->s_buffer = NULL; 24 | return map; 25 | } 26 | 27 | int allocation_buffer_map(struct buffer_map *map, int slot) { 28 | if (map->max_idx > slot) { 29 | map->s_buffer[slot] = new_sock_buffer(); 30 | return 0; 31 | } 32 | 33 | int max_idx = map->max_idx ? map->max_idx : 32; 34 | struct sock_bufferr **tmp = NULL; 35 | 36 | while(max_idx <= slot) { 37 | max_idx <<= 1; // max_idx = max_idx * 2 38 | } 39 | 40 | tmp = realloc(map->s_buffer, max_idx * sizeof(struct sock_buffer *)); 41 | if (tmp == NULL) { 42 | return -1; 43 | } 44 | 45 | struct sock_buffer *s_buf = new_sock_buffer(); 46 | if (s_buf == NULL) { 47 | return -1; 48 | } 49 | 50 | tmp[slot] = s_buf; 51 | 52 | map->max_idx = max_idx; 53 | map->s_buffer = tmp; 54 | 55 | return 0; 56 | } 57 | 58 | void free_buffer_map(struct buffer_map *map) { 59 | if (map->max_idx == NULL) { 60 | return; 61 | } 62 | 63 | int i; 64 | for (i = 0; i < map->max_idx; ++i) { 65 | if (map->s_buffer[i] != NULL) { 66 | free(map->s_buffer[i]); 67 | } 68 | free(map->s_buffer); 69 | map->s_buffer = NULL; 70 | } 71 | map->s_buffer = 0; 72 | } -------------------------------------------------------------------------------- /poll/http-server/buffer_map.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "buffer.h" 5 | #include "buffer_map.h" 6 | 7 | struct sock_buffer *new_sock_buffer() { 8 | struct sock_buffer *s_buf = malloc(sizeof(struct sock_buffer)); 9 | if (s_buf == NULL) { 10 | return NULL; 11 | } 12 | s_buf->r_buffer = new_buffer(); 13 | s_buf->w_buffer = new_buffer(); 14 | return s_buf; 15 | } 16 | 17 | struct buffer_map *new_buffer_map() { 18 | struct buffer_map *map = malloc(sizeof(struct buffer_map)); 19 | if (map == NULL) { 20 | return NULL; 21 | } 22 | map->max_idx = 0; 23 | map->s_buffer = NULL; 24 | return map; 25 | } 26 | 27 | int allocation_buffer_map(struct buffer_map *map, int slot) { 28 | if (map->max_idx > slot) { 29 | map->s_buffer[slot] = new_sock_buffer(); 30 | return 0; 31 | } 32 | 33 | int max_idx = map->max_idx ? map->max_idx : 32; 34 | struct sock_bufferr **tmp = NULL; 35 | 36 | while(max_idx <= slot) { 37 | max_idx <<= 1; // max_idx = max_idx * 2 38 | } 39 | 40 | tmp = realloc(map->s_buffer, max_idx * sizeof(struct sock_buffer *)); 41 | if (tmp == NULL) { 42 | return -1; 43 | } 44 | 45 | struct sock_buffer *s_buf = new_sock_buffer(); 46 | if (s_buf == NULL) { 47 | return -1; 48 | } 49 | 50 | tmp[slot] = s_buf; 51 | 52 | map->max_idx = max_idx; 53 | map->s_buffer = tmp; 54 | 55 | return 0; 56 | } 57 | 58 | void free_buffer_map(struct buffer_map *map) { 59 | if (map->max_idx == NULL) { 60 | return; 61 | } 62 | 63 | int i; 64 | for (i = 0; i < map->max_idx; ++i) { 65 | if (map->s_buffer[i] != NULL) { 66 | free(map->s_buffer[i]); 67 | } 68 | free(map->s_buffer); 69 | map->s_buffer = NULL; 70 | } 71 | map->s_buffer = 0; 72 | } -------------------------------------------------------------------------------- /epoll/http-server/handle_msg.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "handle_msg.h" 9 | 10 | void do_msg(struct sock_buffer *s_buffer, int sock_fd) { 11 | if (s_buffer == NULL) { 12 | perror("invalid sock_buffer"); 13 | return; 14 | } 15 | 16 | printf("do-msg: %d\n", sock_fd); 17 | 18 | int len = 0; // 0-表示还在读长度 >0表示已经读到长度 19 | char len_char[5]; // 消息长度 20 | int len_idx = 0; // 长度读到哪里了 21 | 22 | int msg_len_idx = 0; 23 | 24 | char msg[9999]; 25 | 26 | struct buffer *r_buffer = s_buffer->r_buffer; 27 | while(1) { 28 | int ret = buffer_read_from_socket(r_buffer, sock_fd); 29 | if (ret == -1) { 30 | if (errno == EAGAIN) { 31 | continue; 32 | } 33 | perror("read error"); 34 | break; 35 | } 36 | if (ret == 0) { 37 | close(sock_fd); 38 | break; 39 | } 40 | 41 | 42 | while(ret > 0) { 43 | while (len == 0 && len_idx < MSG_LEN) { 44 | char c = buffer_read_char(s_buffer->r_buffer); 45 | if (c != '\0') { 46 | len_char[len_idx++] = c; 47 | if (len_idx == MSG_LEN) { 48 | memset(msg, 0, sizeof(msg)); 49 | len_char[len_idx] = '\0'; 50 | len = atoi(len_char); 51 | len_idx = 0; 52 | } 53 | } else { 54 | ret = 0; 55 | break; 56 | } 57 | } 58 | 59 | while (1) { 60 | char c = buffer_read_char(s_buffer->r_buffer); 61 | if (c != '\0') { 62 | msg[msg_len_idx++] = c; 63 | if (msg_len_idx == len) { 64 | msg[msg_len_idx] = '\0'; 65 | printf("msg: %s\n", msg); 66 | msg_len_idx = 0; 67 | len = 0; 68 | 69 | //buffer_append(s_buffer->w_buffer, msg, strlen(msg)); 70 | //buffer_write_to_socket(s_buffer->w_buffer, sock_fd); 71 | break; 72 | } 73 | } else { 74 | ret = 0; 75 | break; 76 | } 77 | } 78 | } 79 | } 80 | } -------------------------------------------------------------------------------- /poll/http-server/handle_msg.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "handle_msg.h" 9 | 10 | void do_msg(struct sock_buffer *s_buffer, int sock_fd) { 11 | if (s_buffer == NULL) { 12 | perror("invalid sock_buffer"); 13 | return; 14 | } 15 | 16 | printf("do-msg: %d\n", sock_fd); 17 | 18 | int len = 0; // 0-表示还在读长度 >0表示已经读到长度 19 | char len_char[5]; // 消息长度 20 | int len_idx = 0; // 长度读到哪里了 21 | 22 | int msg_len_idx = 0; 23 | 24 | char msg[9999]; 25 | 26 | struct buffer *r_buffer = s_buffer->r_buffer; 27 | while(1) { 28 | int ret = buffer_read_from_socket(r_buffer, sock_fd); 29 | if (ret == -1) { 30 | if (errno == EAGAIN) { 31 | continue; 32 | } 33 | perror("read error"); 34 | break; 35 | } 36 | if (ret == 0) { 37 | close(sock_fd); 38 | break; 39 | } 40 | 41 | 42 | while(ret > 0) { 43 | while (len == 0 && len_idx < MSG_LEN) { 44 | char c = buffer_read_char(s_buffer->r_buffer); 45 | if (c != '\0') { 46 | len_char[len_idx++] = c; 47 | if (len_idx == MSG_LEN) { 48 | memset(msg, 0, sizeof(msg)); 49 | len_char[len_idx] = '\0'; 50 | len = atoi(len_char); 51 | len_idx = 0; 52 | } 53 | } else { 54 | ret = 0; 55 | break; 56 | } 57 | } 58 | 59 | while (1) { 60 | char c = buffer_read_char(s_buffer->r_buffer); 61 | if (c != '\0') { 62 | msg[msg_len_idx++] = c; 63 | if (msg_len_idx == len) { 64 | msg[msg_len_idx] = '\0'; 65 | printf("msg: %s\n", msg); 66 | msg_len_idx = 0; 67 | len = 0; 68 | 69 | //buffer_append(s_buffer->w_buffer, msg, strlen(msg)); 70 | //buffer_write_to_socket(s_buffer->w_buffer, sock_fd); 71 | break; 72 | } 73 | } else { 74 | ret = 0; 75 | break; 76 | } 77 | } 78 | } 79 | } 80 | } -------------------------------------------------------------------------------- /buffer/server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "buffer.h" 8 | 9 | int create_sock(); 10 | 11 | void request_with_buffer(int sock_fd); 12 | 13 | void response_with_buffer(int sock_fd); 14 | 15 | void on_http_request(int sock_fd); 16 | 17 | int main(int argc, char *argv[]) { 18 | 19 | int sock_fd = create_sock(); 20 | struct sockaddr_in client_addr; 21 | 22 | while(1) { 23 | socklen_t cli_len = sizeof(client_addr); 24 | memset(&client_addr, 0, sizeof(client_addr)); 25 | 26 | int fd = accept(sock_fd, (struct sockaddr *)&client_addr, &cli_len); 27 | if (fd < 0) { 28 | perror("accept error"); 29 | exit(1); 30 | } 31 | 32 | on_http_request(fd); 33 | } 34 | } 35 | 36 | void on_http_request(int sock_fd) { 37 | request_with_buffer(sock_fd); 38 | 39 | response_with_buffer(sock_fd); 40 | 41 | close(sock_fd); 42 | } 43 | 44 | void request_with_buffer(int sock_fd) { 45 | struct buffer *buf = new_buffer(); 46 | 47 | buffer_read_from_socket(buf, sock_fd); 48 | 49 | printf("%s\n", buf->data); 50 | 51 | buffer_free(buf); 52 | } 53 | 54 | void response_with_buffer(int sock_fd) { 55 | struct buffer *buf = new_buffer(); 56 | 57 | buffer_append(buf, "HTTP/1.1 200 OK\r\n", strlen("HTTP/1.1 200 OK\r\n")); 58 | buffer_append(buf, "Host: 127.0.0.1:3000\r\n", strlen("Host: 127.0.0.1:3000\r\n")); 59 | buffer_append(buf, "Content-Type: text/html; charset=UTF-8\r\n", strlen("Content-Type: text/html; charset=UTF-8\r\n")); 60 | buffer_append(buf, "\r\n", strlen("\r\n")); 61 | 62 | char *body = "hello

This is My HTTP Server

"; 63 | buffer_append(buf, body, strlen(body)); 64 | 65 | buffer_write_to_socket(buf, sock_fd); 66 | 67 | buffer_free(buf); 68 | } 69 | 70 | int create_sock() { 71 | int sock_fd; 72 | struct sockaddr_in serv_addr; 73 | 74 | sock_fd = socket(AF_INET, SOCK_STREAM, 0); 75 | 76 | memset(&serv_addr, 0 , sizeof(serv_addr)); 77 | 78 | serv_addr.sin_family = AF_INET; 79 | serv_addr.sin_port = htons(3000); 80 | serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); 81 | 82 | int on = 1; 83 | setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); 84 | 85 | bind(sock_fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)); 86 | 87 | listen(sock_fd, 1024); 88 | 89 | printf("Server is running at: %d\n", 3000); 90 | 91 | return sock_fd; 92 | } -------------------------------------------------------------------------------- /cmake/lib/thread_pool.c: -------------------------------------------------------------------------------- 1 | #include "thread_pool.h" 2 | #include "tcp_server.h" 3 | #include "reader.h" 4 | #include "http_response.h" 5 | 6 | void *worker(void *arg) { 7 | struct worker_thread_context *ctx = (struct worker_thread_context *) arg; 8 | 9 | while (1) { 10 | pthread_mutex_lock(&ctx->mutex); 11 | 12 | pthread_cond_wait(&ctx->cond, &ctx->mutex); 13 | 14 | if (ctx->fd == -1) { 15 | perror("invalid fd"); 16 | break; 17 | } 18 | 19 | printf("THREAD-ID: %ld; FD: %d\n", ctx->thread_id, ctx->fd); 20 | char buf[1024]; 21 | read_line(ctx->fd, buf, sizeof(buf)); 22 | printf("%s", buf); 23 | memset(buf, 0, sizeof(buf)); 24 | read_line(ctx->fd, buf, sizeof(buf)); 25 | printf("%s", buf); 26 | memset(buf, 0, sizeof(buf)); 27 | read_line(ctx->fd, buf, sizeof(buf)); 28 | printf("%s", buf); 29 | 30 | write_response(ctx->fd); 31 | 32 | pthread_mutex_unlock(&ctx->mutex); 33 | } 34 | } 35 | 36 | void *accepter_thread(void *arg) { 37 | int fd = *(int *)arg; 38 | 39 | #ifdef WORKER_POOL_SIZE 40 | struct worker_thread_context *ctx = malloc(WORKER_POOL_SIZE * sizeof(struct worker_thread_context)); 41 | 42 | for (int i = 0; i < WORKER_POOL_SIZE; i++) { 43 | pthread_mutex_init(&ctx[i].mutex, NULL); 44 | pthread_cond_init(&ctx[i].cond, NULL); 45 | ctx[i].fd = -1; 46 | 47 | pthread_create(&ctx[i].thread_id, NULL, worker, (void *)&ctx[i]); 48 | } 49 | #endif 50 | 51 | struct sockaddr_in client_addr; 52 | 53 | int idx = 0; 54 | while(1) { 55 | bzero(&client_addr, sizeof(client_addr)); 56 | socklen_t len = sizeof(client_addr); 57 | int conn_fd = accept(fd, (struct sockaddr *)&client_addr, &len); 58 | if (conn_fd < 0) { 59 | perror("accept error"); 60 | break; 61 | } 62 | #ifdef WORKER_POOL_SIZE 63 | if (idx + 1 == WORKER_POOL_SIZE) { 64 | idx = 0; 65 | } 66 | 67 | pthread_mutex_lock(&ctx[idx].mutex); 68 | 69 | ctx[idx].fd = conn_fd; 70 | 71 | pthread_mutex_unlock(&ctx[idx].mutex); 72 | pthread_cond_signal(&ctx[idx].cond); 73 | 74 | idx++; 75 | #else 76 | char buf[1024]; 77 | read_line(conn_fd, buf, sizeof(buf)); 78 | printf(buf); 79 | memset(buf, 0, sizeof(buf)); 80 | read_line(conn_fd, buf, sizeof(buf)); 81 | printf(buf); 82 | memset(buf, 0, sizeof(buf)); 83 | read_line(conn_fd, buf, sizeof(buf)); 84 | printf(buf); 85 | 86 | write_response(conn_fd); 87 | #endif 88 | } 89 | } -------------------------------------------------------------------------------- /epoll/http-server/epoll.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "epoll.h" 7 | #include "handle_msg.h" 8 | 9 | struct epoll_dispatcher *epoll_new() { 10 | struct epoll_dispatcher *poll_dis = malloc(sizeof(struct epoll_dispatcher)); 11 | poll_dis->size = MAX_POLL_SIZE; 12 | poll_dis->events = calloc(MAX_POLL_SIZE, sizeof(struct epoll_event)); 13 | poll_dis->epfd = epoll_create1(0); 14 | 15 | pthread_cond_init(&poll_dis->cond, NULL); 16 | pthread_mutex_init(&poll_dis->mutex, NULL); 17 | 18 | if (socketpair(AF_UNIX, SOCK_STREAM, 0, poll_dis->pair) < 0) { 19 | perror("socketpair set fialed"); 20 | } 21 | 22 | struct epoll_event ev; 23 | ev.data.fd = poll_dis->pair[1]; 24 | ev.events = EPOLLIN; 25 | epoll_ctl(poll_dis->epfd, EPOLL_CTL_ADD, poll_dis->pair[1], &ev); 26 | 27 | poll_dis->done = 0; 28 | poll_dis->buffer_map = new_buffer_map(); 29 | 30 | return poll_dis; 31 | } 32 | 33 | int epoll_add(struct epoll_dispatcher *poll_dis, int fd) { 34 | struct epoll_event ev; 35 | ev.data.fd = fd; 36 | ev.events = EPOLLIN; 37 | 38 | epoll_ctl(poll_dis->epfd, EPOLL_CTL_ADD, fd, &ev); 39 | 40 | return 0; 41 | } 42 | 43 | int epoll_del(struct epoll_dispatcher *poll_dis, int fd) { 44 | struct epoll_event ev; 45 | ev.data.fd = fd; 46 | ev.events = EPOLLIN; 47 | 48 | epoll_ctl(poll_dis->epfd, EPOLL_CTL_DEL, fd, &ev); 49 | 50 | return 0; 51 | } 52 | 53 | int epoll_dispatch(struct epoll_dispatcher *poll_dis) { 54 | int ret, i; 55 | 56 | pthread_mutex_lock(&poll_dis->mutex); 57 | 58 | epoll_wait(poll_dis->epfd, poll_dis->events, poll_dis->size, 0); 59 | 60 | poll_dis->done = 1; 61 | 62 | pthread_cond_signal(&poll_dis->cond); 63 | pthread_mutex_unlock(&poll_dis->mutex); 64 | 65 | while(1) { 66 | ret = epoll_wait(poll_dis->epfd, poll_dis->events, poll_dis->size, -1); 67 | 68 | for (i = 0; i < ret; i++) { 69 | if (poll_dis->events[i].data.fd == poll_dis->pair[1]) { 70 | char c; 71 | ssize_t n = read(poll_dis->pair[1], &c, sizeof(c)); 72 | if (n != sizeof(c)) { 73 | perror("read error"); 74 | } 75 | printf("wakeup\n"); 76 | continue; 77 | } 78 | 79 | int client_fd = poll_dis->events[i].data.fd; 80 | do_msg(poll_dis->buffer_map->s_buffer[client_fd], client_fd); 81 | } 82 | } 83 | } 84 | 85 | void epoll_free(struct epoll_dispatcher *poll_dis) { 86 | free(poll_dis->events); 87 | free_buffer_map(poll_dis->buffer_map); 88 | poll_dis->buffer_map = NULL; 89 | free(poll_dis); 90 | } -------------------------------------------------------------------------------- /poll/poll.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | int create_sock(); 14 | 15 | void make_nonblocking(int fd); 16 | 17 | int main(int argc, char *argv[]) { 18 | int read_num, conn_fd, n; 19 | char buf[1024]; 20 | struct sockaddr_in client_addr; 21 | 22 | int sock_fd = create_sock(); 23 | 24 | make_nonblocking(sock_fd); 25 | 26 | struct pollfd fds[1024]; 27 | fds[0].fd = sock_fd; 28 | fds[0].events = POLLRDNORM; 29 | 30 | int i; 31 | for (i = 1; i < 1024; i++) { 32 | fds[i].fd = -1; 33 | } 34 | 35 | for (;;) { 36 | if ((read_num = poll(fds, 1024, -1)) < 0) { 37 | perror ("poll failed."); 38 | } 39 | 40 | if (fds[0].revents & POLLRDNORM) { 41 | socklen_t cli_len = sizeof((client_addr)); 42 | conn_fd = accept(sock_fd, (struct sockaddr *)&client_addr, &cli_len); 43 | 44 | printf("have a new connection: %d.\n", conn_fd); 45 | 46 | for (i = 1; i < 1024; i++) { 47 | if (fds[i].fd < 0) { 48 | fds[i].fd = conn_fd; 49 | fds[i].events = POLLRDNORM; 50 | break; 51 | } 52 | } 53 | 54 | if (i == 1024) { 55 | perror("too many clients."); 56 | } 57 | 58 | if (--read_num <= 0) { 59 | continue; 60 | } 61 | } 62 | 63 | for (i = 1; i < 1024; i++) { 64 | int client_fd; 65 | if ((client_fd = fds[i].fd) < 0) { 66 | continue; 67 | } 68 | 69 | if (fds[i].revents & (POLLRDNORM | POLLERR)) { 70 | if ((n = read(client_fd, buf, sizeof(buf))) > 0) { 71 | if (write(client_fd, buf, n) < 0) { 72 | perror("write failed."); 73 | } 74 | } else if (n == 0 || errno == ECONNRESET) { 75 | close(client_fd); 76 | fds[i].fd = -1; 77 | } else { 78 | perror("read failed."); 79 | } 80 | } 81 | 82 | if (--read_num <= 0) { 83 | break; 84 | } 85 | } 86 | } 87 | } 88 | 89 | int create_sock() { 90 | int sock_fd = socket(AF_INET, SOCK_STREAM, 0); 91 | 92 | struct sockaddr_in serv_addr; 93 | memset(&serv_addr, 0, sizeof(serv_addr)); 94 | 95 | serv_addr.sin_family = AF_INET; 96 | serv_addr.sin_port = htons(3000); 97 | serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); 98 | 99 | bind(sock_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); 100 | 101 | listen(sock_fd, 1024); 102 | 103 | printf("listening on port 3000.\n"); 104 | 105 | return sock_fd; 106 | } 107 | 108 | void make_nonblocking(int fd) { 109 | fcntl(fd, F_SETFL, O_NONBLOCK); 110 | } -------------------------------------------------------------------------------- /buffer/buffer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "buffer.h" 6 | 7 | 8 | struct buffer *new_buffer() { 9 | struct buffer *buf = malloc(sizeof(struct buffer)); 10 | if (!buf) { 11 | return NULL; 12 | } 13 | 14 | buf->data = malloc(BUFFER_SIZE); 15 | memset(buf->data, 0, BUFFER_SIZE); 16 | buf->size = BUFFER_SIZE; 17 | buf->r_idx = 0; 18 | buf->w_idx = 0; 19 | 20 | return buf; 21 | } 22 | 23 | void buffer_free(struct buffer *buf) { 24 | free(buf->data); 25 | free(buf); 26 | } 27 | 28 | int buffer_append(struct buffer *buf, char *data, size_t len) { 29 | if (buf->size - buf->r_idx == buf->w_idx) { 30 | return 0; 31 | } 32 | 33 | size_t write_size = 0; 34 | size_t write_total = 0; 35 | 36 | while(1) { 37 | if (buf->size - buf->r_idx == buf->w_idx || write_total == len) { 38 | break; 39 | } 40 | 41 | if (buf->r_idx > buf->w_idx) { 42 | write_size = buf->r_idx - buf->w_idx; 43 | } else if (buf->size - buf->w_idx < len) { 44 | write_size = buf->size - buf->w_idx; 45 | } else { 46 | write_size = len; 47 | } 48 | 49 | memcpy(buf->data + buf->w_idx, data, write_size); 50 | 51 | if (buf->w_idx + write_size < buf->size) { 52 | buf->w_idx += write_size; 53 | } else { 54 | buf->w_idx = 0; 55 | } 56 | write_total += write_size; 57 | } 58 | 59 | return write_total; 60 | } 61 | 62 | // if return is -2, it means that the buffer is full 63 | int buffer_read_from_socket(struct buffer *buf, int sock_fd) { 64 | if (buf->size - buf->r_idx == buf->w_idx) { 65 | return -2; 66 | } 67 | 68 | int read_size = 0; 69 | if (buf->r_idx > buf->w_idx) { 70 | read_size = buf->r_idx - buf->w_idx; 71 | } else if (buf->size - buf->w_idx < BUFFER_SIZE) { 72 | read_size = buf->size - buf->w_idx; 73 | } else { 74 | read_size = BUFFER_SIZE; 75 | } 76 | 77 | int ret = recv(sock_fd, buf->data + buf->w_idx, read_size, 0); 78 | if (ret > 0) { 79 | if (buf->w_idx + ret < buf->size) { 80 | buf->w_idx += ret; 81 | } else { 82 | buf->w_idx = 0; 83 | } 84 | } 85 | 86 | return ret; 87 | } 88 | 89 | // if return is -2, it means that the buffer is empty 90 | int buffer_write_to_socket(struct buffer *buf, int sock_fd) { 91 | if (buf->size - buf->r_idx == buf->w_idx) { 92 | return -2; 93 | } 94 | 95 | int write_size = 0; 96 | int write_total = 0; 97 | while(1) { 98 | if (buf->size - buf->r_idx == buf->w_idx) { 99 | break; 100 | } 101 | 102 | write_size = buf->size - buf->r_idx; 103 | if (buf->r_idx < buf->w_idx) { 104 | write_size = buf->w_idx - buf->r_idx; 105 | } 106 | 107 | int ret = send(sock_fd, buf->data + buf->r_idx, write_size, 0); 108 | if (ret <= 0) { 109 | return ret; 110 | } 111 | write_total += ret; 112 | 113 | if (buf->r_idx < buf->size) { 114 | buf->r_idx += ret; 115 | } else { 116 | buf->r_idx = 0; 117 | } 118 | } 119 | 120 | return write_total; 121 | } -------------------------------------------------------------------------------- /c-plus-plus/xstring/xstring.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class xstring 5 | { 6 | public: 7 | size_t len() const { 8 | return m_len; 9 | } 10 | 11 | size_t cap() const { 12 | return m_cap; 13 | } 14 | 15 | public: 16 | friend std::ostream& operator<<(std::ostream& os, const xstring& s) { 17 | return std::cout << s.m_str; 18 | } 19 | 20 | public: 21 | xstring() = default; 22 | 23 | xstring(const char *s) { 24 | if (s == nullptr) { 25 | m_str = new char[1]; 26 | if (m_str == nullptr) { 27 | exit(-1); 28 | } 29 | *m_str = '\0'; 30 | m_len = 0; 31 | m_cap = 0; 32 | } else { 33 | int len = strlen(s); 34 | m_str = new char[len + 1]; 35 | if (m_str == nullptr) { 36 | exit(-1); 37 | } 38 | 39 | strcpy(m_str, s); 40 | m_len = len; 41 | m_cap = len; 42 | } 43 | } 44 | 45 | xstring(const size_t cap) { 46 | m_str = new char[cap + 1]; 47 | if (m_str == nullptr) { 48 | exit(-1); 49 | } 50 | m_len = 0; 51 | m_cap = cap; 52 | } 53 | 54 | // 拷贝构造函数 55 | // 拷贝构造用于一个对象创建另一个对象 56 | xstring(const xstring &s) { 57 | std::cout << "this is copy construct" << std::endl; 58 | 59 | int len = strlen(s.m_str); 60 | m_str = new char[len + 1]; 61 | if (m_str == nullptr) { 62 | exit(-1); 63 | } 64 | strcpy(m_str, s.m_str); 65 | m_len = len; 66 | m_cap = len; 67 | } 68 | 69 | // 转移构造函数 70 | // 一个临时对象的值移动到一个新的对象上 71 | // 一个对象创建另一个对象,但是创建后原对象不再使用 72 | // 使用转移构造函数可以避免内存拷贝的开销 73 | xstring(xstring&& s) { 74 | std::cout << "this is move construct" << std::endl; 75 | 76 | if (s.m_str != nullptr) { 77 | m_str = s.m_str; 78 | m_len = s.m_len; 79 | m_cap = s.m_cap; 80 | s.m_str = nullptr; 81 | } 82 | } 83 | 84 | // 拷贝赋值函数 85 | // 将一个对象赋值给另一个对象 86 | xstring& operator=(const xstring &s) { 87 | if (this != &s) { 88 | delete[] m_str; 89 | 90 | int len = strlen(s.m_str); 91 | if (m_cap < len) { 92 | m_str = new char[len + 1]; 93 | if (m_str == nullptr) { 94 | exit(-1); 95 | } 96 | m_len = len; 97 | m_cap = len; 98 | } else { 99 | memset(m_str, 0, len + 1); 100 | m_len = len; 101 | m_cap = s.m_cap; 102 | } 103 | strcpy(m_str, s.m_str); 104 | } 105 | 106 | return *this; 107 | } 108 | 109 | // 移动赋值函数 110 | // 将一个临时对象的值移动到当前对象中,可以避免内存拷贝的开销 111 | xstring& operator=(xstring&& s) { 112 | if (this != &s) { 113 | delete[] m_str; 114 | m_str = s.m_str; 115 | m_len = s.m_len; 116 | m_cap = s.m_cap; 117 | s.m_str = nullptr; 118 | } 119 | 120 | return *this; 121 | } 122 | 123 | // 析构函数 124 | ~xstring() { 125 | delete[] m_str; 126 | m_str = nullptr; 127 | } 128 | 129 | private: 130 | char* m_str; 131 | size_t m_len; 132 | size_t m_cap; 133 | }; -------------------------------------------------------------------------------- /epoll/epoll.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #define MAX_EVENTS 1024 14 | 15 | int create_sock(); 16 | 17 | void make_nonblocking(int fd); 18 | 19 | int main(int argc, char *argv[]) { 20 | int read_num, conn_fd, n, efd, i; 21 | char buf[1024]; 22 | struct sockaddr_in client_addr; 23 | 24 | int sock_fd = create_sock(); 25 | 26 | make_nonblocking(sock_fd); 27 | 28 | struct epoll_event event; 29 | struct epoll_event *events; 30 | 31 | efd = epoll_create1(0); 32 | if (efd == -1) { 33 | perror("epoll_create1 failed."); 34 | exit(1); 35 | } 36 | 37 | event.data.fd = sock_fd; 38 | event.events = EPOLLIN | EPOLLET; // 边缘触发 39 | if (epoll_ctl(efd, EPOLL_CTL_ADD, sock_fd, &event) == -1) { 40 | perror("epoll_ctl failed."); 41 | exit(1); 42 | } 43 | 44 | events = calloc(MAX_EVENTS, sizeof(event)); 45 | 46 | for (;;) { 47 | read_num = epoll_wait(efd, events, MAX_EVENTS, -1); 48 | 49 | for (i = 0; i < read_num; i++) { 50 | if ((events[i].events & EPOLLERR) || 51 | (events[i].events & EPOLLHUP || 52 | (!(events[i].events & EPOLLIN)))) 53 | { 54 | perror("epoll error."); 55 | close(events[i].data.fd); 56 | continue; 57 | } else if (sock_fd == events[i].data.fd) { 58 | socklen_t cli_len = sizeof(client_addr); 59 | conn_fd = accept(sock_fd, (struct sockaddr *)&client_addr, &cli_len); 60 | if (conn_fd == -1) { 61 | perror("accept error."); 62 | continue; 63 | } else { 64 | event.data.fd = conn_fd; 65 | event.events = EPOLLIN | EPOLLET; 66 | if (epoll_ctl(efd, EPOLL_CTL_ADD, conn_fd, &event) == -1) { 67 | perror("epoll_ctl error."); 68 | } 69 | } 70 | continue; 71 | } else { 72 | int client_fd = events[i].data.fd; 73 | 74 | if (n = read(client_fd, buf, sizeof(buf)) > 0) { 75 | if (write(client_fd, buf, n) < 0) { 76 | perror("write failed."); 77 | } else if (n == 0 || errno == ECONNRESET) { 78 | close(client_fd); 79 | continue; 80 | } else { 81 | write(client_fd, buf, n); 82 | } 83 | } 84 | } 85 | } 86 | } 87 | } 88 | 89 | int create_sock() { 90 | int sock_fd = socket(AF_INET, SOCK_STREAM, 0); 91 | 92 | struct sockaddr_in serv_addr; 93 | memset(&serv_addr, 0, sizeof(serv_addr)); 94 | 95 | serv_addr.sin_family = AF_INET; 96 | serv_addr.sin_port = htons(3000); 97 | serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); 98 | 99 | bind(sock_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); 100 | 101 | listen(sock_fd, 1024); 102 | 103 | printf("listening on port 3000.\n"); 104 | 105 | return sock_fd; 106 | } 107 | 108 | void make_nonblocking(int fd) { 109 | fcntl(fd, F_SETFL, O_NONBLOCK); 110 | } -------------------------------------------------------------------------------- /poll/http-server/poll.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "poll.h" 7 | #include "handle_msg.h" 8 | 9 | struct poll_dispatcher *poll_new() { 10 | struct poll_dispatcher *poll_dis = malloc(sizeof(struct poll_dispatcher)); 11 | poll_dis->size = MAX_POLL_SIZE; 12 | poll_dis->fds = malloc(sizeof(struct pollfd) * MAX_POLL_SIZE); 13 | 14 | pthread_cond_init(&poll_dis->cond, NULL); 15 | pthread_mutex_init(&poll_dis->mutex, NULL); 16 | 17 | if (socketpair(AF_UNIX, SOCK_STREAM, 0, poll_dis->pair) < 0) { 18 | perror("socketpair set fialed"); 19 | } 20 | 21 | poll_dis->fds[0].fd = poll_dis->pair[1]; 22 | poll_dis->fds[0].events = POLLRDNORM; 23 | 24 | int i; 25 | for (i = 1; i < MAX_POLL_SIZE; i++) { 26 | poll_dis->fds[i].fd = -1; 27 | } 28 | 29 | poll_dis->done = 0; 30 | poll_dis->buffer_map = new_buffer_map(); 31 | 32 | return poll_dis; 33 | } 34 | 35 | int poll_add(struct poll_dispatcher *poll_dis, int fd) { 36 | int i; 37 | for (i = 0; i < poll_dis->size; i++) { 38 | if (poll_dis->fds[i].fd == -1) { 39 | poll_dis->fds[i].fd = fd; 40 | poll_dis->fds[i].events = POLLRDNORM; 41 | 42 | char c = 'a'; 43 | ssize_t n= write(poll_dis->pair[0], &c, sizeof(c)); 44 | if (n != sizeof(c)) { 45 | perror("write error"); 46 | } 47 | 48 | printf("poll-add-fd: %d\n", fd); 49 | return 0; 50 | } 51 | } 52 | 53 | perror("too many clients"); 54 | 55 | return -1; 56 | } 57 | 58 | int poll_del(struct poll_dispatcher *poll_dis, int fd) { 59 | int i; 60 | for (i = 0; i < MAX_POLL_SIZE; i++) { 61 | if (poll_dis->fds[i].fd == fd) { 62 | poll_dis->fds[i].fd = -1; 63 | return 0; 64 | } 65 | } 66 | 67 | perror("can't find fd"); 68 | 69 | return -1; 70 | } 71 | 72 | int poll_dispatch(struct poll_dispatcher *poll_dis) { 73 | int ret, i; 74 | 75 | pthread_mutex_lock(&poll_dis->mutex); 76 | 77 | poll(poll_dis->fds, poll_dis->size, 0); 78 | poll_dis->done = 1; 79 | 80 | pthread_cond_signal(&poll_dis->cond); 81 | pthread_mutex_unlock(&poll_dis->mutex); 82 | 83 | while(1) { 84 | ret = poll(poll_dis->fds, poll_dis->size, -1); 85 | if (ret == -1) { 86 | perror("poll error"); 87 | return -1; 88 | } 89 | 90 | printf("poll-returned: %d\n", ret); 91 | 92 | for (i = 0; i < poll_dis->size; i++) { 93 | if (poll_dis->fds[i].fd == -1) { 94 | continue; 95 | } 96 | 97 | // wakeup 98 | if (poll_dis->fds[i].fd == poll_dis->pair[1] && poll_dis->fds[i].revents & POLLRDNORM) { 99 | char c; 100 | ssize_t n = read(poll_dis->pair[1], &c, sizeof(c)); 101 | if (n != sizeof(c)) { 102 | perror("read error"); 103 | } 104 | printf("wakeup\n"); 105 | break; 106 | } 107 | 108 | if (poll_dis->fds[i].revents & (POLLRDNORM | POLLERR)) { 109 | int client_fd = poll_dis->fds[i].fd; 110 | do_msg(poll_dis->buffer_map->s_buffer[client_fd], client_fd); 111 | } 112 | } 113 | } 114 | } 115 | 116 | void poll_free(struct poll_dispatcher *poll_dis) { 117 | free(poll_dis->fds); 118 | free_buffer_map(poll_dis->buffer_map); 119 | poll_dis->buffer_map = NULL; 120 | free(poll_dis); 121 | } -------------------------------------------------------------------------------- /c-plus-plus/thread/thread-pool.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by EDY on 2023/10/10. 3 | // 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class TPool { 10 | public: 11 | TPool(): m_thread_size(1), m_terminate(false) {}; 12 | ~TPool() { stop(); } 13 | bool init(size_t size) { 14 | std::unique_lock lock(m_mutex); 15 | if (!m_threads.empty()) { 16 | return false; 17 | } 18 | m_thread_size = size; 19 | return true; 20 | } 21 | void stop() { 22 | { 23 | std::unique_lock lock(m_mutex); 24 | m_terminate = true; 25 | m_cond.notify_all(); 26 | } 27 | 28 | for (auto & m_thread : m_threads) { 29 | if (m_thread->joinable()) { 30 | m_thread->join(); 31 | } 32 | delete m_thread; 33 | m_thread = nullptr; 34 | } 35 | 36 | std::unique_lock lock(m_mutex); 37 | m_threads.clear(); 38 | } 39 | bool start() { 40 | std::unique_lock lock(m_mutex); 41 | if (!m_threads.empty()) { 42 | return false; 43 | } 44 | 45 | for (size_t i = 0; i < m_thread_size; i++) { 46 | m_threads.push_back(new std::thread(&TPool::run, this)); 47 | } 48 | return true; 49 | } 50 | 51 | template 52 | auto exec(F&& f, A&&... args)->std::future { 53 | using retType = decltype(f(args...)); 54 | auto task = std::make_shared>(std::bind(std::forward(f), std::forward(args)...)); 55 | TaskFunc fPtr = std::make_shared(); 56 | fPtr->m_func = [task](){ 57 | (*task)(); 58 | }; 59 | 60 | std::unique_lock lock(m_mutex); 61 | m_tasks.push(fPtr); 62 | m_cond.notify_one(); 63 | 64 | return task->get_future(); 65 | } 66 | bool waitDone() { 67 | std::unique_lock lock(m_mutex); 68 | 69 | if (m_tasks.empty()) 70 | return false; 71 | 72 | m_cond.wait(lock, [this]{return m_tasks.empty();}); 73 | return true; 74 | } 75 | 76 | private: 77 | struct Task { 78 | Task() {} 79 | std::function m_func; 80 | }; 81 | 82 | typedef std::shared_ptr TaskFunc; 83 | 84 | private: 85 | bool get(TaskFunc &t) { 86 | std::unique_lock lock(m_mutex); 87 | if (m_tasks.empty()) { 88 | m_cond.wait(lock, [this]{return m_terminate || !m_tasks.empty();}); 89 | } 90 | 91 | if (m_terminate) 92 | return false; 93 | 94 | if (!m_tasks.empty()) { 95 | t = std::move(m_tasks.front()); 96 | m_tasks.pop(); 97 | return true; 98 | } 99 | 100 | return false; 101 | } 102 | bool run() { 103 | while(!m_terminate) { 104 | TaskFunc task; 105 | bool ok = get(task); 106 | if (ok) { 107 | ++m_atomic; 108 | 109 | task->m_func(); 110 | 111 | --m_atomic; 112 | 113 | std::unique_lock lock(m_mutex); 114 | if (m_atomic == 0 && m_tasks.empty()) { // 是否所有任务都执行完成 115 | m_cond.notify_all(); 116 | } 117 | } 118 | } 119 | } 120 | 121 | private: 122 | std::queue m_tasks; 123 | std::vector m_threads; 124 | std::mutex m_mutex; 125 | std::condition_variable m_cond; 126 | size_t m_thread_size; 127 | bool m_terminate; 128 | std::atomic m_atomic{0}; 129 | }; 130 | -------------------------------------------------------------------------------- /epoll/http-server/buffer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "buffer.h" 6 | 7 | 8 | struct buffer *new_buffer() { 9 | struct buffer *buf = malloc(sizeof(struct buffer)); 10 | if (!buf) { 11 | return NULL; 12 | } 13 | 14 | buf->data = malloc(BUFFER_SIZE); 15 | memset(buf->data, 0, BUFFER_SIZE); 16 | buf->size = BUFFER_SIZE; 17 | buf->r_idx = 0; 18 | buf->w_idx = 0; 19 | 20 | return buf; 21 | } 22 | 23 | void buffer_free(struct buffer *buf) { 24 | free(buf->data); 25 | free(buf); 26 | } 27 | 28 | char buffer_read_char(struct buffer *buf) { 29 | if (buf->size - buf->r_idx == buf->w_idx) { 30 | return '\0'; 31 | } 32 | 33 | char c = buf->data[buf->r_idx]; 34 | if (buf->r_idx + 1 < buf->size) { 35 | buf->r_idx++; 36 | } else { 37 | buf->r_idx = 0; 38 | } 39 | 40 | return c; 41 | } 42 | 43 | int buffer_append(struct buffer *buf, char *data, size_t len) { 44 | if (buf->size - buf->r_idx == buf->w_idx) { 45 | return 0; 46 | } 47 | 48 | size_t write_size = 0; 49 | size_t write_total = 0; 50 | 51 | while(1) { 52 | if (buf->size - buf->r_idx == buf->w_idx || write_total == len) { 53 | break; 54 | } 55 | 56 | if (buf->r_idx > buf->w_idx) { 57 | write_size = buf->r_idx - buf->w_idx; 58 | } else if (buf->size - buf->w_idx < len) { 59 | write_size = buf->size - buf->w_idx; 60 | } else { 61 | write_size = len; 62 | } 63 | 64 | memcpy(buf->data + buf->w_idx, data, write_size); 65 | 66 | if (buf->w_idx + write_size < buf->size) { 67 | buf->w_idx += write_size; 68 | } else { 69 | buf->w_idx = 0; 70 | } 71 | write_total += write_size; 72 | } 73 | 74 | return write_total; 75 | } 76 | 77 | // if return is -2, it means that the buffer is full 78 | int buffer_read_from_socket(struct buffer *buf, int sock_fd) { 79 | if (buf->size - buf->r_idx == buf->w_idx) { 80 | return -2; 81 | } 82 | 83 | int read_size = 0; 84 | if (buf->r_idx > buf->w_idx) { 85 | read_size = buf->r_idx - buf->w_idx; 86 | } else if (buf->size - buf->w_idx < BUFFER_SIZE) { 87 | read_size = buf->size - buf->w_idx; 88 | } else { 89 | read_size = BUFFER_SIZE; 90 | } 91 | 92 | int ret = recv(sock_fd, buf->data + buf->w_idx, read_size, 0); 93 | if (ret > 0) { 94 | if (buf->w_idx + ret < buf->size) { 95 | buf->w_idx += ret; 96 | } else { 97 | buf->w_idx = 0; 98 | } 99 | } 100 | 101 | return ret; 102 | } 103 | 104 | // if return is -2, it means that the buffer is empty 105 | int buffer_write_to_socket(struct buffer *buf, int sock_fd) { 106 | if (buf->size - buf->r_idx == buf->w_idx) { 107 | return -2; 108 | } 109 | 110 | int write_size = 0; 111 | int write_total = 0; 112 | while(1) { 113 | if (buf->size - buf->r_idx == buf->w_idx) { 114 | break; 115 | } 116 | 117 | write_size = buf->size - buf->r_idx; 118 | if (buf->r_idx < buf->w_idx) { 119 | write_size = buf->w_idx - buf->r_idx; 120 | } 121 | 122 | int ret = send(sock_fd, buf->data + buf->r_idx, write_size, 0); 123 | if (ret <= 0) { 124 | return ret; 125 | } 126 | write_total += ret; 127 | 128 | if (buf->r_idx < buf->size) { 129 | buf->r_idx += ret; 130 | } else { 131 | buf->r_idx = 0; 132 | } 133 | } 134 | 135 | return write_total; 136 | } -------------------------------------------------------------------------------- /poll/http-server/buffer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "buffer.h" 6 | 7 | 8 | struct buffer *new_buffer() { 9 | struct buffer *buf = malloc(sizeof(struct buffer)); 10 | if (!buf) { 11 | return NULL; 12 | } 13 | 14 | buf->data = malloc(BUFFER_SIZE); 15 | memset(buf->data, 0, BUFFER_SIZE); 16 | buf->size = BUFFER_SIZE; 17 | buf->r_idx = 0; 18 | buf->w_idx = 0; 19 | 20 | return buf; 21 | } 22 | 23 | void buffer_free(struct buffer *buf) { 24 | free(buf->data); 25 | free(buf); 26 | } 27 | 28 | char buffer_read_char(struct buffer *buf) { 29 | if (buf->size - buf->r_idx == buf->w_idx) { 30 | return '\0'; 31 | } 32 | 33 | char c = buf->data[buf->r_idx]; 34 | if (buf->r_idx + 1 < buf->size) { 35 | buf->r_idx++; 36 | } else { 37 | buf->r_idx = 0; 38 | } 39 | 40 | return c; 41 | } 42 | 43 | int buffer_append(struct buffer *buf, char *data, size_t len) { 44 | if (buf->size - buf->r_idx == buf->w_idx) { 45 | return 0; 46 | } 47 | 48 | size_t write_size = 0; 49 | size_t write_total = 0; 50 | 51 | while(1) { 52 | if (buf->size - buf->r_idx == buf->w_idx || write_total == len) { 53 | break; 54 | } 55 | 56 | if (buf->r_idx > buf->w_idx) { 57 | write_size = buf->r_idx - buf->w_idx; 58 | } else if (buf->size - buf->w_idx < len) { 59 | write_size = buf->size - buf->w_idx; 60 | } else { 61 | write_size = len; 62 | } 63 | 64 | memcpy(buf->data + buf->w_idx, data, write_size); 65 | 66 | if (buf->w_idx + write_size < buf->size) { 67 | buf->w_idx += write_size; 68 | } else { 69 | buf->w_idx = 0; 70 | } 71 | write_total += write_size; 72 | } 73 | 74 | return write_total; 75 | } 76 | 77 | // if return is -2, it means that the buffer is full 78 | int buffer_read_from_socket(struct buffer *buf, int sock_fd) { 79 | if (buf->size - buf->r_idx == buf->w_idx) { 80 | return -2; 81 | } 82 | 83 | int read_size = 0; 84 | if (buf->r_idx > buf->w_idx) { 85 | read_size = buf->r_idx - buf->w_idx; 86 | } else if (buf->size - buf->w_idx < BUFFER_SIZE) { 87 | read_size = buf->size - buf->w_idx; 88 | } else { 89 | read_size = BUFFER_SIZE; 90 | } 91 | 92 | int ret = recv(sock_fd, buf->data + buf->w_idx, read_size, 0); 93 | if (ret > 0) { 94 | if (buf->w_idx + ret < buf->size) { 95 | buf->w_idx += ret; 96 | } else { 97 | buf->w_idx = 0; 98 | } 99 | } 100 | 101 | return ret; 102 | } 103 | 104 | // if return is -2, it means that the buffer is empty 105 | int buffer_write_to_socket(struct buffer *buf, int sock_fd) { 106 | if (buf->size - buf->r_idx == buf->w_idx) { 107 | return -2; 108 | } 109 | 110 | int write_size = 0; 111 | int write_total = 0; 112 | while(1) { 113 | if (buf->size - buf->r_idx == buf->w_idx) { 114 | break; 115 | } 116 | 117 | write_size = buf->size - buf->r_idx; 118 | if (buf->r_idx < buf->w_idx) { 119 | write_size = buf->w_idx - buf->r_idx; 120 | } 121 | 122 | int ret = send(sock_fd, buf->data + buf->r_idx, write_size, 0); 123 | if (ret <= 0) { 124 | return ret; 125 | } 126 | write_total += ret; 127 | 128 | if (buf->r_idx < buf->size) { 129 | buf->r_idx += ret; 130 | } else { 131 | buf->r_idx = 0; 132 | } 133 | } 134 | 135 | return write_total; 136 | } -------------------------------------------------------------------------------- /non-blocking-socket/buffer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "buffer.h" 6 | 7 | 8 | struct buffer *new_buffer() { 9 | struct buffer *buf = malloc(sizeof(struct buffer)); 10 | if (!buf) { 11 | return NULL; 12 | } 13 | 14 | buf->data = malloc(BUFFER_SIZE); 15 | memset(buf->data, 0, BUFFER_SIZE); 16 | buf->size = BUFFER_SIZE; 17 | buf->r_idx = 0; 18 | buf->w_idx = 0; 19 | 20 | return buf; 21 | } 22 | 23 | void buffer_free(struct buffer *buf) { 24 | free(buf->data); 25 | free(buf); 26 | } 27 | 28 | char buffer_read_char(struct buffer *buf) { 29 | if (buf->size - buf->r_idx == buf->w_idx) { 30 | return '\0'; 31 | } 32 | 33 | char c = buf->data[buf->r_idx]; 34 | if (buf->r_idx + 1 < buf->size) { 35 | buf->r_idx++; 36 | } else { 37 | buf->r_idx = 0; 38 | } 39 | 40 | return c; 41 | } 42 | 43 | int buffer_append(struct buffer *buf, char *data, size_t len) { 44 | if (buf->size - buf->r_idx == buf->w_idx) { 45 | return 0; 46 | } 47 | 48 | size_t write_size = 0; 49 | size_t write_total = 0; 50 | 51 | while(1) { 52 | if (buf->size - buf->r_idx == buf->w_idx || write_total == len) { 53 | break; 54 | } 55 | 56 | if (buf->r_idx > buf->w_idx) { 57 | write_size = buf->r_idx - buf->w_idx; 58 | } else if (buf->size - buf->w_idx < len) { 59 | write_size = buf->size - buf->w_idx; 60 | } else { 61 | write_size = len; 62 | } 63 | 64 | memcpy(buf->data + buf->w_idx, data, write_size); 65 | 66 | if (buf->w_idx + write_size < buf->size) { 67 | buf->w_idx += write_size; 68 | } else { 69 | buf->w_idx = 0; 70 | } 71 | write_total += write_size; 72 | } 73 | 74 | return write_total; 75 | } 76 | 77 | // if return is -2, it means that the buffer is full 78 | int buffer_read_from_socket(struct buffer *buf, int sock_fd) { 79 | if (buf->size - buf->r_idx == buf->w_idx) { 80 | return -2; 81 | } 82 | 83 | int read_size = 0; 84 | if (buf->r_idx > buf->w_idx) { 85 | read_size = buf->r_idx - buf->w_idx; 86 | } else if (buf->size - buf->w_idx < BUFFER_SIZE) { 87 | read_size = buf->size - buf->w_idx; 88 | } else { 89 | read_size = BUFFER_SIZE; 90 | } 91 | 92 | int ret = recv(sock_fd, buf->data + buf->w_idx, read_size, 0); 93 | if (ret > 0) { 94 | if (buf->w_idx + ret < buf->size) { 95 | buf->w_idx += ret; 96 | } else { 97 | buf->w_idx = 0; 98 | } 99 | } 100 | 101 | return ret; 102 | } 103 | 104 | // if return is -2, it means that the buffer is empty 105 | int buffer_write_to_socket(struct buffer *buf, int sock_fd) { 106 | if (buf->size - buf->r_idx == buf->w_idx) { 107 | return -2; 108 | } 109 | 110 | int write_size = 0; 111 | int write_total = 0; 112 | while(1) { 113 | if (buf->size - buf->r_idx == buf->w_idx) { 114 | break; 115 | } 116 | 117 | write_size = buf->size - buf->r_idx; 118 | if (buf->r_idx < buf->w_idx) { 119 | write_size = buf->w_idx - buf->r_idx; 120 | } 121 | 122 | int ret = send(sock_fd, buf->data + buf->r_idx, write_size, 0); 123 | if (ret <= 0) { 124 | return ret; 125 | } 126 | write_total += ret; 127 | 128 | if (buf->r_idx < buf->size) { 129 | buf->r_idx += ret; 130 | } else { 131 | buf->r_idx = 0; 132 | } 133 | } 134 | 135 | return write_total; 136 | } -------------------------------------------------------------------------------- /c-plus-plus/operator-reload/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | class complex 6 | { 7 | public: 8 | complex() = default; 9 | complex(float c, float ci) 10 | { 11 | m_c = c; 12 | m_ci = ci; 13 | 14 | cout << "this is constructor" << endl; 15 | } 16 | // 拷贝构造 17 | complex(const complex &c) 18 | { 19 | m_c = c.m_c; 20 | m_ci = c.m_ci; 21 | 22 | cout << "this is copy constructor" << endl; 23 | } 24 | 25 | ~complex() = default; 26 | 27 | public: 28 | complex& operator= (const complex& c) 29 | { 30 | if (this != &c) 31 | { 32 | m_c = c.m_c; 33 | m_ci = c.m_ci; 34 | } 35 | return *this; 36 | } 37 | 38 | complex operator+(const complex& c) 39 | { 40 | complex tmp; 41 | tmp.m_c = m_c + c.m_c; 42 | tmp.m_ci = m_ci + c.m_ci; 43 | return tmp; 44 | } 45 | 46 | complex& operator+=(const complex &c) { 47 | m_c += c.m_c; 48 | m_ci += c.m_ci; 49 | 50 | return *this; 51 | } 52 | 53 | complex operator-(const complex &c) const { 54 | return complex(m_c - c.m_c, m_ci - c.m_ci); 55 | } 56 | 57 | complex& operator-=(const complex &c) { 58 | m_c -= c.m_c; 59 | m_ci -= c.m_ci; 60 | 61 | return *this; 62 | } 63 | 64 | complex operator*(const complex &c) const { 65 | return complex(m_c * c.m_c - m_ci*c.m_ci, m_c*c.m_ci + m_ci*c.m_c); 66 | } 67 | 68 | complex& operator*=(const complex &c) { 69 | complex tmp(*this); // 拷贝构造 70 | m_c = tmp.m_c*c.m_c - m_ci*c.m_ci; 71 | m_ci = tmp.m_c*c.m_ci + tmp.m_ci*c.m_c; 72 | return *this; 73 | } 74 | 75 | complex operator/(const complex &c) { 76 | double t = c.m_c*c.m_c + c.m_ci*c.m_ci; 77 | return complex((m_c*c.m_c - m_ci*(-c.m_ci)) / t, (m_c*(-c.m_ci) + m_ci*c.m_c) / t); 78 | } 79 | 80 | complex& operator/=(const complex &c) { 81 | complex tmp(*this); //拷贝构造函数 82 | double t = c.m_c*c.m_c + c.m_ci*c.m_ci; 83 | m_c = (tmp.m_c*c.m_c - tmp.m_ci*(-c.m_ci)) / t; 84 | m_ci = (tmp.m_c*(-c.m_c) + tmp.m_ci*c.m_c) / t; 85 | return *this; 86 | } 87 | 88 | bool operator==(const complex &c) { 89 | return (m_c == c.m_c) && (m_ci == c.m_ci); 90 | } 91 | 92 | bool operator!=(const complex &c) { 93 | return !((m_c == c.m_c) && (m_ci == c.m_ci)); 94 | } 95 | 96 | bool operator>(const complex &c) { 97 | return (m_c > c.m_c) && (m_ci > c.m_ci); 98 | } 99 | 100 | bool operator>=(const complex &c) { 101 | return (m_c >= c.m_c) && (m_ci >= c.m_ci); 102 | } 103 | 104 | bool operator<(const complex &c) { 105 | return (m_c < c.m_c) && (m_ci < c.m_ci); 106 | } 107 | 108 | bool operator<=(const complex &c) { 109 | return (m_c <= c.m_c) && (m_ci <= c.m_ci); 110 | } 111 | 112 | // 前置++ 113 | complex& operator++() { 114 | m_c++; 115 | m_ci++; 116 | return *this; 117 | } 118 | 119 | // 后置++ 120 | complex operator++(int) { 121 | return complex(m_c++, m_ci++); 122 | } 123 | 124 | // 前置-- 125 | complex& operator--() { 126 | m_c--; 127 | m_ci--; 128 | return *this; 129 | } 130 | 131 | // 后置-- 132 | complex operator--(int) { 133 | return complex(m_c--, m_ci--); 134 | } 135 | 136 | private: 137 | float m_c = 0; 138 | float m_ci = 0; 139 | }; 140 | 141 | int main() { 142 | complex c1(1, 2); 143 | complex c2(3, 4); 144 | 145 | complex c3; 146 | c3 = c1 + c2; 147 | 148 | return 0; 149 | } -------------------------------------------------------------------------------- /select/select.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | 13 | int create_sock(); 14 | 15 | void make_nonblocking(int sock_fd); 16 | 17 | 18 | int main(int argc, char *argv[]) { 19 | struct sockaddr_in client_addr; 20 | int conn_fd, serv_fd, max_fd; 21 | char recv_buf[1024], send_buf[1024]; 22 | 23 | serv_fd = create_sock(); 24 | make_nonblocking(serv_fd); 25 | 26 | fd_set read_mask; 27 | fd_set all_reads; 28 | 29 | FD_ZERO(&all_reads); 30 | FD_SET(0, &all_reads); 31 | FD_SET(serv_fd, &all_reads); 32 | 33 | memset(&client_addr, 0, sizeof(client_addr)); 34 | socklen_t cli_len = sizeof(client_addr); 35 | max_fd = serv_fd; 36 | 37 | while(1) { 38 | read_mask = all_reads; 39 | 40 | int rc = select(max_fd + 1, &read_mask, NULL, NULL, NULL); 41 | if (rc < 0) { 42 | perror("select failed."); 43 | exit(1); 44 | } 45 | 46 | if (FD_ISSET(serv_fd, &read_mask)) { 47 | memset(&client_addr, 0, sizeof(client_addr)); 48 | conn_fd = accept(serv_fd, (struct sockaddr *)&client_addr, &cli_len); 49 | if (conn_fd < 0) { 50 | perror("accept failed."); 51 | continue; 52 | } 53 | 54 | if (conn_fd > max_fd) { 55 | max_fd = conn_fd; 56 | } 57 | FD_SET(conn_fd, &all_reads); 58 | 59 | printf("have a new connection: %d.\n", conn_fd); 60 | } 61 | 62 | if (FD_ISSET(STDIN_FILENO, &read_mask)) { 63 | memset(send_buf, 0, sizeof(send_buf)); 64 | if (conn_fd <= 0) { 65 | fgets(send_buf, sizeof(send_buf), stdin); 66 | printf("please wait for a connection.\n"); 67 | continue; 68 | } 69 | 70 | if (fgets(send_buf, sizeof(send_buf), stdin) != NULL) { 71 | int i = strlen(send_buf); 72 | if (send_buf[i - 1] == '\n') { 73 | send_buf[i - 1] = '\0'; 74 | } 75 | 76 | printf("now send: %s\n", send_buf); 77 | 78 | size_t rt = write(conn_fd, send_buf, strlen(send_buf)); 79 | if (rt < 0) { 80 | perror("write failed."); 81 | } 82 | printf("send bytes: %zu\n", rt); 83 | } 84 | } 85 | 86 | if (FD_ISSET(conn_fd, &read_mask)) { 87 | memset(recv_buf, 0, sizeof(recv_buf)); 88 | size_t rt = read(conn_fd, recv_buf, sizeof(recv_buf)); 89 | if (rt < 0) { 90 | printf("read failed. conn-fd: %d\n", conn_fd); 91 | continue; 92 | } 93 | if (rt == 0) { 94 | printf("client closed, conn-fd: %d\n", conn_fd); 95 | FD_CLR(conn_fd, &all_reads); 96 | close(conn_fd); 97 | continue; 98 | } 99 | 100 | printf("from client msg: %s\n", recv_buf); 101 | 102 | send(conn_fd, recv_buf, strlen(recv_buf), 0); 103 | } 104 | } 105 | 106 | } 107 | 108 | void make_nonblocking(int sock_fd) { 109 | fcntl(sock_fd, F_SETFL, O_NONBLOCK); 110 | } 111 | 112 | int create_sock() { 113 | int sock_fd = socket(AF_INET, SOCK_STREAM, 0); 114 | 115 | struct sockaddr_in serv_addr; 116 | 117 | serv_addr.sin_family = AF_INET; 118 | serv_addr.sin_port = htons(3000); 119 | serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); 120 | 121 | int on = 1; 122 | setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); 123 | 124 | if (bind(sock_fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) { 125 | perror("bind failed."); 126 | return -1; 127 | } 128 | 129 | if (listen(sock_fd, 1024) < 0) { 130 | perror("listen failed."); 131 | return -1; 132 | } 133 | 134 | return sock_fd; 135 | } -------------------------------------------------------------------------------- /non-blocking-socket/thread_pool.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "thread_pool.h" 3 | #include "tcp_server.h" 4 | #include "buffer.h" 5 | #include "buffer_map.h" 6 | 7 | #define MSG_LEN 4 8 | 9 | void make_nonblocking(int fd) { 10 | fcntl(fd, F_SETFL, O_NONBLOCK); 11 | } 12 | 13 | void handle_msg(struct sock_buffer *s_buffer, int sock_fd) { 14 | if (s_buffer == NULL) { 15 | perror("invalid sock_buffer"); 16 | return; 17 | } 18 | 19 | int len = 0; // 0-表示还在读长度 >0表示已经读到长度 20 | char len_char[5]; // 消息长度 21 | int len_idx = 0; // 长度读到哪里了 22 | 23 | int msg_len_idx = 0; 24 | 25 | char msg[9999]; 26 | 27 | struct buffer *r_buffer = s_buffer->r_buffer; 28 | while(1) { 29 | int ret = buffer_read_from_socket(r_buffer, sock_fd); 30 | if (ret == -1) { 31 | if (errno == EAGAIN) { 32 | continue; 33 | } 34 | perror("read error"); 35 | break; 36 | } 37 | if (ret == 0) { 38 | close(sock_fd); 39 | break; 40 | } 41 | 42 | 43 | while(ret > 0) { 44 | while (len == 0 && len_idx < MSG_LEN) { 45 | char c = buffer_read_char(s_buffer->r_buffer); 46 | if (c != '\0') { 47 | len_char[len_idx++] = c; 48 | if (len_idx == MSG_LEN) { 49 | memset(msg, 0, sizeof(msg)); 50 | len_char[len_idx] = '\0'; 51 | len = atoi(len_char); 52 | len_idx = 0; 53 | } 54 | } else { 55 | ret = 0; 56 | break; 57 | } 58 | } 59 | 60 | while (1) { 61 | char c = buffer_read_char(s_buffer->r_buffer); 62 | if (c != '\0') { 63 | msg[msg_len_idx++] = c; 64 | if (msg_len_idx == len) { 65 | msg[msg_len_idx] = '\0'; 66 | printf("msg: %s\n", msg); 67 | msg_len_idx = 0; 68 | len = 0; 69 | 70 | buffer_append(s_buffer->w_buffer, msg, strlen(msg)); 71 | buffer_write_to_socket(s_buffer->w_buffer, sock_fd); 72 | break; 73 | } 74 | } else { 75 | ret = 0; 76 | break; 77 | } 78 | } 79 | } 80 | } 81 | } 82 | 83 | void *worker(void *arg) { 84 | struct worker_thread_context *ctx = (struct worker_thread_context *) arg; 85 | 86 | while (1) { 87 | pthread_mutex_lock(&ctx->mutex); 88 | 89 | pthread_cond_wait(&ctx->cond, &ctx->mutex); 90 | 91 | if (ctx->fd == -1) { 92 | perror("invalid fd"); 93 | break; 94 | } 95 | 96 | struct sock_buffer *s_buffer = ctx->buffer_map->s_buffer[ctx->fd]; 97 | 98 | handle_msg(s_buffer, ctx->fd); 99 | 100 | pthread_mutex_unlock(&ctx->mutex); 101 | } 102 | } 103 | 104 | void *accepter_thread(void *arg) { 105 | int fd = *(int *)arg; 106 | 107 | struct buffer_map *map = new_buffer_map(); 108 | if (map == NULL) { 109 | perror("new_buffer_map error"); 110 | exit(1); 111 | } 112 | 113 | struct worker_thread_context *ctx = malloc(WORKER_POOL_SIZE * sizeof(struct worker_thread_context)); 114 | ctx->buffer_map = map; 115 | 116 | for (int i = 0; i < WORKER_POOL_SIZE; i++) { 117 | pthread_mutex_init(&ctx[i].mutex, NULL); 118 | pthread_cond_init(&ctx[i].cond, NULL); 119 | ctx[i].fd = -1; 120 | 121 | pthread_create(&ctx[i].thread_id, NULL, worker, (void *)&ctx[i]); 122 | } 123 | 124 | struct sockaddr_in client_addr; 125 | 126 | int idx = 0; 127 | while(1) { 128 | bzero(&client_addr, sizeof(client_addr)); 129 | socklen_t len = sizeof(client_addr); 130 | int conn_fd = accept(fd, (struct sockaddr *)&client_addr, &len); 131 | if (conn_fd < 0) { 132 | perror("accept error"); 133 | break; 134 | } 135 | 136 | make_nonblocking(conn_fd); 137 | 138 | if (allocation_buffer_map(map, conn_fd) < 0) { 139 | perror("allocation_buffer_map error"); 140 | break; 141 | } 142 | 143 | 144 | if (idx + 1 == WORKER_POOL_SIZE) { 145 | idx = 0; 146 | } 147 | 148 | pthread_mutex_lock(&ctx[idx].mutex); 149 | 150 | ctx[idx].fd = conn_fd; 151 | 152 | pthread_mutex_unlock(&ctx[idx].mutex); 153 | pthread_cond_signal(&ctx[idx].cond); 154 | 155 | idx++; 156 | } 157 | } --------------------------------------------------------------------------------