├── .idea ├── NetworkProgramming.iml ├── encodings.xml ├── misc.xml ├── modules.xml └── vcs.xml ├── 01mqopen.cpp ├── 01shmopen.cpp ├── 02myunlink.cpp ├── 02shmunlink.cpp ├── 03mqgetattr.cpp ├── 03shmwrite.cpp ├── 04mqsend.cpp ├── 04shmreceive.cpp ├── 05mqreceive.cpp ├── 06mqnotify.cpp ├── CMakeLists.txt ├── README.md ├── condtest.cpp ├── conntest.cpp ├── echocli.cpp ├── echocli2.cpp ├── echocli3.cpp ├── echocli4.cpp ├── echocli5.cpp ├── echocli6.cpp ├── echocli7.cpp ├── echosrv.cpp ├── echosrv2.cpp ├── echosrv3.cpp ├── echosrv4.cpp ├── echosrv5.cpp ├── echosrv6.cpp ├── echosrv7.cpp ├── epollsrv.cpp ├── gethostbyname_test.cpp ├── main.cpp ├── mmap_recv.cpp ├── mmap_send.cpp ├── msg_recv.cpp ├── msg_send.cpp ├── msgcli.cpp ├── msgctl01.cpp ├── msgctl02.cpp ├── msgget.cpp ├── msgsrv.cpp ├── p2pcli.cpp ├── p2pserv.cpp ├── pctest.cpp ├── pollsrv.cpp ├── sem.cpp ├── sem02.cpp ├── sem03.cpp ├── shmfifo ├── CMakeLists.txt ├── shmfifo.cpp ├── shmfifo.h ├── shmfifo_destroy.cpp ├── shmfifo_recv.cpp └── shmfifo_send.cpp ├── shmread.cpp ├── shmwrite.cpp ├── sockpair.cpp ├── sockpair02.cpp ├── thread.cpp ├── thread_create.cpp ├── threadechosrv.cpp ├── threadpool ├── CMakeLists.txt ├── condition.cpp ├── condition.h ├── test.cpp ├── threadpool.cpp └── threadpool.h ├── udpchat ├── CMakeLists.txt ├── Pub.h ├── UdpChatCli.cpp └── UdpChatSrv.cpp ├── udpcli.cpp ├── udpmulclt.cpp ├── udpmulsrv.cpp ├── udpsrv.cpp ├── unixcli.cpp └── unixsrv.cpp /.idea/NetworkProgramming.iml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /01mqopen.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-14. 3 | // 4 | 5 | // p34 poxis消息队列 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include /* For O_* constants */ 14 | #include /* For mode constants */ 15 | #include 16 | 17 | using namespace std; 18 | 19 | #define ERR_EXIT(m) \ 20 | do \ 21 | { \ 22 | perror(m); \ 23 | exit(EXIT_FAILURE); \ 24 | } while (0); 25 | 26 | int main(int argc, char** argv) 27 | { 28 | // mq_overview 29 | mqd_t mqid = mq_open("/abc", O_CREAT | O_RDWR, 0666, NULL); 30 | if (mqid == ((mqd_t) -1)) 31 | { 32 | ERR_EXIT("mq_open"); 33 | } 34 | 35 | printf("mqopen success\n"); 36 | mq_close(mqid); 37 | printf("mqclose success\n"); 38 | return 0; 39 | } -------------------------------------------------------------------------------- /01shmopen.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-14. 3 | // 4 | 5 | // p35 poxis共享内存 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include /* For O_* constants */ 14 | #include /* For mode constants */ 15 | #include 16 | #include 17 | 18 | using namespace std; 19 | 20 | #define ERR_EXIT(m) \ 21 | do \ 22 | { \ 23 | perror(m); \ 24 | exit(EXIT_FAILURE); \ 25 | } while (0); 26 | 27 | struct student 28 | { 29 | char name[32]; 30 | int age; 31 | }; 32 | 33 | int main(int argc, char** argv) 34 | { 35 | int shmid; 36 | shmid = shm_open("/xyz", O_CREAT | O_RDWR, 0666); 37 | //shmid = shm_open("/xyz", O_RDWR, S_IRUSR); 38 | if (shmid == -1) 39 | { 40 | ERR_EXIT("shmid"); 41 | } 42 | printf("shmopen success\n"); 43 | 44 | student stu; 45 | strcpy(stu.name , "hello"); 46 | stu.age = 20; 47 | 48 | if (ftruncate(shmid, sizeof(stu)) == -1) 49 | { 50 | ERR_EXIT("ftruncate"); 51 | } 52 | printf("truncate succ\n"); 53 | 54 | struct stat buf; 55 | if (fstat(shmid, &buf) == -1) 56 | { 57 | ERR_EXIT("fstat"); 58 | } 59 | 60 | printf("mode: %o, size: %ld\n", buf.st_mode & 07777, buf.st_size); 61 | 62 | close(shmid); 63 | 64 | return 0; 65 | } -------------------------------------------------------------------------------- /02myunlink.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-14. 3 | // 4 | 5 | // p34 poxis消息队列 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include /* For O_* constants */ 14 | #include /* For mode constants */ 15 | #include 16 | 17 | using namespace std; 18 | 19 | #define ERR_EXIT(m) \ 20 | do \ 21 | { \ 22 | perror(m); \ 23 | exit(EXIT_FAILURE); \ 24 | } while (0); 25 | 26 | int main(int argc, char** argv) 27 | { 28 | // mq_overview 29 | mqd_t mqid = mq_open("/abc", O_RDWR); 30 | if (mqid == ((mqd_t) -1)) 31 | { 32 | ERR_EXIT("mq_open"); 33 | } 34 | 35 | printf("mqopen success\n"); 36 | 37 | if (mq_unlink("/abc") == -1) 38 | { 39 | ERR_EXIT("mq_unlink"); 40 | } 41 | 42 | printf("mqunlink success\n"); 43 | 44 | mq_close(mqid); 45 | 46 | return 0; 47 | } -------------------------------------------------------------------------------- /02shmunlink.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-14. 3 | // 4 | 5 | // p35 poxis共享内存 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include /* For O_* constants */ 14 | #include /* For mode constants */ 15 | #include 16 | #include 17 | 18 | using namespace std; 19 | 20 | #define ERR_EXIT(m) \ 21 | do \ 22 | { \ 23 | perror(m); \ 24 | exit(EXIT_FAILURE); \ 25 | } while (0); 26 | 27 | struct student 28 | { 29 | char name[32]; 30 | int age; 31 | }; 32 | 33 | int main(int argc, char** argv) 34 | { 35 | int shmid; 36 | shmid = shm_open("/xyz", O_CREAT | O_RDWR, 0666); 37 | //shmid = shm_open("/xyz", O_RDWR, S_IRUSR); 38 | if (shmid == -1) 39 | { 40 | ERR_EXIT("shmid"); 41 | } 42 | printf("shmopen success\n"); 43 | 44 | student stu; 45 | strcpy(stu.name , "hello"); 46 | stu.age = 20; 47 | 48 | if (ftruncate(shmid, sizeof(stu)) == -1) 49 | { 50 | ERR_EXIT("ftruncate"); 51 | } 52 | printf("truncate succ\n"); 53 | 54 | struct stat buf; 55 | if (fstat(shmid, &buf) == -1) 56 | { 57 | ERR_EXIT("fstat"); 58 | } 59 | 60 | printf("mode: %o, size: %ld\n", buf.st_mode & 07777, buf.st_size); 61 | 62 | close(shmid); 63 | if (shm_unlink("/xyz") == -1) 64 | { 65 | ERR_EXIT("shmunlink"); 66 | } 67 | printf("shm_unlink succ\n"); 68 | 69 | 70 | return 0; 71 | } -------------------------------------------------------------------------------- /03mqgetattr.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-14. 3 | // 4 | 5 | // p34 poxis消息队列 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include /* For O_* constants */ 14 | #include /* For mode constants */ 15 | #include 16 | 17 | using namespace std; 18 | 19 | #define ERR_EXIT(m) \ 20 | do \ 21 | { \ 22 | perror(m); \ 23 | exit(EXIT_FAILURE); \ 24 | } while (0); 25 | 26 | int main(int argc, char** argv) 27 | { 28 | // mq_overview 29 | mqd_t mqid = mq_open("/abc", O_RDONLY); 30 | if (mqid == ((mqd_t) -1)) 31 | { 32 | ERR_EXIT("mq_open"); 33 | } 34 | 35 | //printf("mqopen success\n"); 36 | 37 | struct mq_attr attr; 38 | 39 | if (mq_getattr(mqid, &attr) == -1) 40 | { 41 | ERR_EXIT("mq_getattr"); 42 | } 43 | printf("max #msg = %ld max #bytes/msg = %ld #currently on queue = %ld\n", attr.mq_maxmsg, attr.mq_msgsize, attr.mq_curmsgs); 44 | 45 | mq_close(mqid); 46 | 47 | return 0; 48 | } -------------------------------------------------------------------------------- /03shmwrite.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-14. 3 | // 4 | 5 | // p35 poxis共享内存 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include /* For O_* constants */ 14 | #include /* For mode constants */ 15 | #include 16 | #include 17 | 18 | using namespace std; 19 | 20 | #define ERR_EXIT(m) \ 21 | do \ 22 | { \ 23 | perror(m); \ 24 | exit(EXIT_FAILURE); \ 25 | } while (0); 26 | 27 | struct student 28 | { 29 | char name[32]; 30 | int age; 31 | }; 32 | 33 | int main(int argc, char** argv) 34 | { 35 | int shmid; 36 | shmid = shm_open("/xyz", O_CREAT | O_RDWR, 0666); 37 | //shmid = shm_open("/xyz", O_RDWR, S_IRUSR); 38 | if (shmid == -1) 39 | { 40 | ERR_EXIT("shmid"); 41 | } 42 | printf("shmopen success\n"); 43 | 44 | student* stu; 45 | 46 | 47 | if (ftruncate(shmid, sizeof(stu)) == -1) 48 | { 49 | ERR_EXIT("ftruncate"); 50 | } 51 | printf("truncate succ\n"); 52 | 53 | struct stat buf; 54 | if (fstat(shmid, &buf) == -1) 55 | { 56 | ERR_EXIT("fstat"); 57 | } 58 | 59 | printf("mode: %o, size: %ld\n", buf.st_mode & 07777, buf.st_size); 60 | 61 | stu = (student*)mmap(NULL, buf.st_size, PROT_WRITE, MAP_SHARED, shmid, 0); 62 | 63 | strcpy(stu->name , "hello"); 64 | stu->age = 20; 65 | 66 | close(shmid); 67 | 68 | return 0; 69 | } -------------------------------------------------------------------------------- /04mqsend.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-14. 3 | // 4 | 5 | // p34 poxis消息队列 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include /* For O_* constants */ 14 | #include /* For mode constants */ 15 | #include 16 | 17 | using namespace std; 18 | 19 | #define ERR_EXIT(m) \ 20 | do \ 21 | { \ 22 | perror(m); \ 23 | exit(EXIT_FAILURE); \ 24 | } while (0); 25 | 26 | struct student 27 | { 28 | char name[32]; 29 | int age; 30 | }; 31 | 32 | int main(int argc, char** argv) 33 | { 34 | if (argc != 2) 35 | { 36 | fprintf(stderr, "Usage: %s \n", argv[1]); 37 | } 38 | 39 | // mq_overview 40 | mqd_t mqid = mq_open("/abc", O_WRONLY); 41 | if (mqid == ((mqd_t) -1)) 42 | { 43 | ERR_EXIT("mq_open"); 44 | } 45 | 46 | //printf("mqopen success\n"); 47 | student stu; 48 | strcpy(stu.name, "hello"); 49 | stu.age = 20; 50 | 51 | if (mq_send(mqid, (const char*)&stu, sizeof(stu), atoi(argv[1])) == -1) 52 | { 53 | ERR_EXIT("mq_send"); 54 | } 55 | 56 | printf("send success\n"); 57 | mq_close(mqid); 58 | 59 | return 0; 60 | } -------------------------------------------------------------------------------- /04shmreceive.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-14. 3 | // 4 | 5 | // p35 poxis共享内存 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include /* For O_* constants */ 14 | #include /* For mode constants */ 15 | #include 16 | #include 17 | 18 | using namespace std; 19 | 20 | #define ERR_EXIT(m) \ 21 | do \ 22 | { \ 23 | perror(m); \ 24 | exit(EXIT_FAILURE); \ 25 | } while (0); 26 | 27 | struct student 28 | { 29 | char name[32]; 30 | int age; 31 | }; 32 | 33 | int main(int argc, char** argv) 34 | { 35 | int shmid; 36 | shmid = shm_open("/xyz", O_CREAT | O_RDWR, 0666); 37 | //shmid = shm_open("/xyz", O_RDWR, S_IRUSR); 38 | if (shmid == -1) 39 | { 40 | ERR_EXIT("shmid"); 41 | } 42 | printf("shmopen success\n"); 43 | 44 | student* stu; 45 | if (ftruncate(shmid, sizeof(stu)) == -1) 46 | { 47 | ERR_EXIT("ftruncate"); 48 | } 49 | printf("truncate succ\n"); 50 | 51 | struct stat buf; 52 | if (fstat(shmid, &buf) == -1) 53 | { 54 | ERR_EXIT("fstat"); 55 | } 56 | 57 | printf("mode: %o, size: %ld\n", buf.st_mode & 07777, buf.st_size); 58 | 59 | stu = (student*)mmap(NULL, buf.st_size, PROT_READ, MAP_SHARED, shmid, 0); 60 | printf("name: %s, age: %d\n", stu->name, stu->age); 61 | 62 | close(shmid); 63 | 64 | return 0; 65 | } -------------------------------------------------------------------------------- /05mqreceive.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-14. 3 | // 4 | 5 | // p34 poxis消息队列 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include /* For O_* constants */ 14 | #include /* For mode constants */ 15 | #include 16 | 17 | using namespace std; 18 | 19 | #define ERR_EXIT(m) \ 20 | do \ 21 | { \ 22 | perror(m); \ 23 | exit(EXIT_FAILURE); \ 24 | } while (0); 25 | 26 | struct student 27 | { 28 | char name[32]; 29 | int age; 30 | }; 31 | 32 | int main(int argc, char** argv) 33 | { 34 | // mq_overview 35 | mqd_t mqid = mq_open("/abc", O_RDONLY); 36 | if (mqid == ((mqd_t) -1)) 37 | { 38 | ERR_EXIT("mq_open"); 39 | } 40 | 41 | //printf("mqopen success\n"); 42 | 43 | struct mq_attr attr; 44 | 45 | if (mq_getattr(mqid, &attr) == -1) 46 | { 47 | ERR_EXIT("mq_getattr"); 48 | } 49 | 50 | size_t size = attr.mq_msgsize; 51 | student stu; 52 | 53 | if (mq_receive(mqid, (char*)&stu, size, NULL) == -1) 54 | { 55 | ERR_EXIT("mq_receive"); 56 | } 57 | 58 | printf("student name = %s, age = %d\n", stu.name, stu.age); 59 | mq_close(mqid); 60 | 61 | return 0; 62 | } -------------------------------------------------------------------------------- /06mqnotify.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-14. 3 | // 4 | 5 | // p34 poxis消息队列 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include /* For O_* constants */ 14 | #include /* For mode constants */ 15 | #include 16 | #include 17 | 18 | using namespace std; 19 | 20 | #define ERR_EXIT(m) \ 21 | do \ 22 | { \ 23 | perror(m); \ 24 | exit(EXIT_FAILURE); \ 25 | } while (0); 26 | 27 | struct student 28 | { 29 | char name[32]; 30 | int age; 31 | }; 32 | 33 | size_t size; 34 | mqd_t mqid; 35 | struct sigevent sigv; 36 | 37 | void handler(int s) 38 | { 39 | mq_notify(mqid, &sigv); 40 | student stu; 41 | 42 | if (mq_receive(mqid, (char*)&stu, size, NULL) == -1) 43 | { 44 | ERR_EXIT("mq_receive"); 45 | } 46 | 47 | printf("student name = %s, age = %d\n", stu.name, stu.age); 48 | } 49 | 50 | int main(int argc, char** argv) 51 | { 52 | // mq_overview 53 | mqid = mq_open("/abc", O_RDONLY); 54 | if (mqid == ((mqd_t) -1)) 55 | { 56 | ERR_EXIT("mq_open"); 57 | } 58 | 59 | //printf("mqopen success\n"); 60 | struct mq_attr attr; 61 | if (mq_getattr(mqid, &attr) == -1) 62 | { 63 | ERR_EXIT("mq_getattr"); 64 | } 65 | 66 | size = attr.mq_msgsize; 67 | 68 | 69 | signal(SIGUSR1, handler); //定义一个信号函数,当SIGALRM信号发过来时,执行handler函数 70 | 71 | sigv.sigev_notify = SIGEV_SIGNAL; 72 | sigv.sigev_signo = SIGUSR1; 73 | 74 | mq_notify(mqid, &sigv); 75 | 76 | while (true) 77 | { 78 | pause(); 79 | } 80 | 81 | mq_close(mqid); 82 | 83 | return 0; 84 | } -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5.1) 2 | project(NetworkProgramming) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | 6 | add_executable(NetworkProgramming main.cpp) 7 | add_executable(echosrv echosrv.cpp) 8 | add_executable(echocli echocli.cpp) 9 | add_executable(echosrv2 echosrv2.cpp) 10 | add_executable(echocli2 echocli2.cpp) 11 | add_executable(echosrv3 echosrv3.cpp) 12 | add_executable(echocli3 echocli3.cpp) 13 | add_executable(echosrv4 echosrv4.cpp) 14 | add_executable(echocli4 echocli4.cpp) 15 | add_executable(echosrv5 echosrv5.cpp) 16 | add_executable(echocli5 echocli5.cpp) 17 | add_executable(echosrv6 echosrv6.cpp) 18 | add_executable(echocli6 echocli6.cpp) 19 | add_executable(echosrv7 echosrv7.cpp) 20 | add_executable(echocli7 echocli7.cpp) 21 | add_executable(conntest conntest.cpp) 22 | add_executable(pollsrv pollsrv.cpp) 23 | add_executable(epollsrv epollsrv.cpp) 24 | add_executable(gethostbyname_test gethostbyname_test.cpp) 25 | add_executable(p2pcli p2pcli.cpp) 26 | add_executable(p2pserv p2pserv.cpp) 27 | add_executable(udpsrv udpsrv.cpp) 28 | add_executable(udpcli udpcli.cpp) 29 | add_executable(udpmulclt udpmulclt.cpp) 30 | add_executable(udpmulsrv udpmulsrv.cpp) 31 | add_executable(unixcli unixcli.cpp) 32 | add_executable(unixsrv unixsrv.cpp) 33 | add_executable(sockpair sockpair.cpp) 34 | add_executable(sockpair02 sockpair02.cpp) 35 | add_executable(msgget msgget.cpp) 36 | add_executable(msgctl01 msgctl01.cpp) 37 | add_executable(msgctl02 msgctl02.cpp) 38 | add_executable(msg_send msg_send.cpp) 39 | add_executable(msg_recv msg_recv.cpp) 40 | add_executable(msgcli msgcli.cpp) 41 | add_executable(msgsrv msgsrv.cpp) 42 | add_executable(mmap_recv mmap_recv.cpp) 43 | add_executable(mmap_send mmap_send.cpp) 44 | add_executable(shmread shmread.cpp) 45 | add_executable(shmwrite shmwrite.cpp) 46 | add_executable(sem sem.cpp) 47 | add_executable(sem02 sem02.cpp) 48 | add_executable(sem03 sem03.cpp) 49 | add_executable(01mqopen 01mqopen.cpp) 50 | add_executable(02myunlink 02myunlink.cpp) 51 | add_executable(03mqgetattr 03mqgetattr.cpp) 52 | add_executable(04mqsend 04mqsend.cpp) 53 | add_executable(05mqreceive 05mqreceive.cpp) 54 | add_executable(06mqnotify 06mqnotify.cpp) 55 | add_executable(01shmopen 01shmopen.cpp) 56 | add_executable(02shmunlink 02shmunlink.cpp) 57 | add_executable(03shmwrite 03shmwrite.cpp) 58 | add_executable(04shmreceive 04shmreceive.cpp) 59 | add_executable(thread_create thread_create.cpp) 60 | add_executable(threadechosrv threadechosrv.cpp) 61 | add_executable(thread thread.cpp) 62 | add_executable(pctest pctest.cpp) 63 | add_executable(condtest condtest.cpp) 64 | 65 | add_subdirectory(udpchat) 66 | add_subdirectory(shmfifo) 67 | add_subdirectory(threadpool) 68 | 69 | set(semsrc 70 | sem.cpp) 71 | 72 | add_library(semtool ${semsrc}) 73 | 74 | target_link_libraries(01mqopen rt) 75 | target_link_libraries(02myunlink rt) 76 | target_link_libraries(03mqgetattr rt) 77 | target_link_libraries(04mqsend rt) 78 | target_link_libraries(05mqreceive rt) 79 | target_link_libraries(06mqnotify rt) 80 | target_link_libraries(01shmopen rt) 81 | target_link_libraries(02shmunlink rt) 82 | target_link_libraries(03shmwrite rt) 83 | target_link_libraries(04shmreceive rt) 84 | target_link_libraries(thread_create pthread) 85 | target_link_libraries(threadechosrv pthread) 86 | target_link_libraries(thread pthread) 87 | target_link_libraries(pctest pthread rt) 88 | target_link_libraries(condtest pthread rt) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NetworkProgramming 2 | Linux网络编程视频教程 3 | 编译环境 Linux + CLion 4 | 5 | 视频地址 https://www.bilibili.com/video/av33813135/ 6 | 从p13 socket编程8开始在文件开头标注该代码属于哪个视频 7 | 8 | 前面章节 echocli* echosrv* 依次按顺序匹配 9 | 10 | ## linux编译 11 | >> cmake . 12 | >> make 13 | 14 | 个人体会:之前没看这个,[muduo](https://github.com/834810071/muduo_study)基本上看不懂,看过之后,[muduo](https://github.com/834810071/muduo_study)基本上就没啥难度了。 15 | -------------------------------------------------------------------------------- /condtest.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-15. 3 | // 4 | 5 | // p39 posix信号量与互斥锁 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include /* For O_* constants */ 12 | #include /* For mode constants */ 13 | #include 14 | #include 15 | 16 | using namespace std; 17 | 18 | #define ERR_EXIT(m) \ 19 | do \ 20 | { \ 21 | perror(m); \ 22 | exit(EXIT_FAILURE); \ 23 | } while(0); 24 | 25 | #define CONSUMERS_COUNT 1 26 | #define PRODUCERS_COUNT 1 27 | 28 | pthread_mutex_t g_mutex; 29 | pthread_cond_t g_cond; 30 | 31 | pthread_t g_thread[CONSUMERS_COUNT + PRODUCERS_COUNT]; 32 | 33 | int ready = 0; 34 | 35 | void *produce (void *arg) 36 | { 37 | int num = *((int *)arg); 38 | int i; 39 | while (1) 40 | { 41 | printf("%d produce is waiting\n", num); 42 | pthread_mutex_lock(&g_mutex); 43 | printf("%d produce begin produce product %d\n", num, ready); 44 | 45 | while (ready == 0) 46 | { 47 | pthread_cond_wait(&g_cond, &g_mutex); 48 | } 49 | 50 | printf("%d produce end produce product %d\n", num, ready++); 51 | pthread_mutex_unlock(&g_mutex); 52 | sleep(1); 53 | } 54 | return NULL; 55 | } 56 | 57 | void *consume (void *arg) 58 | { 59 | int num = *((int *)arg); 60 | int i; 61 | while (1) 62 | { 63 | printf("%d consume is waiting\n", num); 64 | pthread_mutex_lock(&g_mutex); 65 | printf("%d consume begin consume product %d\n", num, ready); 66 | 67 | ++ready; 68 | pthread_cond_signal(&g_cond); 69 | 70 | printf("%d consume end consume product %d\n", num, ready); 71 | pthread_mutex_unlock(&g_mutex); 72 | sleep(1); 73 | } 74 | return NULL; 75 | } 76 | 77 | int main(int argc, char** argv) 78 | { 79 | 80 | pthread_mutex_init(&g_mutex, NULL); 81 | pthread_cond_init(&g_cond, NULL); 82 | 83 | int i; 84 | for (i = 0; i < CONSUMERS_COUNT; ++i) 85 | { 86 | pthread_create(&g_thread[i], NULL, consume, &i); 87 | } 88 | sleep(1); 89 | for (i = 0; i < PRODUCERS_COUNT; ++i) 90 | { 91 | pthread_create(&g_thread[CONSUMERS_COUNT+i], NULL, produce, &i); 92 | } 93 | 94 | for (i = 0; i < CONSUMERS_COUNT + PRODUCERS_COUNT; ++i) 95 | { 96 | pthread_join(g_thread[i], NULL); 97 | } 98 | 99 | pthread_mutex_destroy(&g_mutex); 100 | pthread_cond_destroy(&g_cond); 101 | 102 | return 0; 103 | } -------------------------------------------------------------------------------- /conntest.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-7. 3 | // 4 | 5 | // socket 编程 12 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | 19 | using namespace std; 20 | 21 | struct packet 22 | { 23 | int len; 24 | char buf[1024]; 25 | }; 26 | 27 | #define ERR_EXIT(m) \ 28 | do \ 29 | { \ 30 | perror(m); \ 31 | exit(EXIT_FAILURE); \ 32 | } while(0); 33 | 34 | ssize_t readn(int fd, void *buf, size_t count) 35 | { 36 | size_t nleft = count; // 剩余字节数 37 | ssize_t nread; 38 | char *bufp = (char*) buf; 39 | 40 | while (nleft > 0) 41 | { 42 | nread = read(fd, bufp, nleft); 43 | if (nread < 0) 44 | { 45 | if (errno == EINTR) 46 | { 47 | continue; 48 | } 49 | return -1; 50 | } else if (nread == 0) 51 | { 52 | return count - nleft; 53 | } 54 | 55 | bufp += nread; 56 | nleft -= nread; 57 | } 58 | return count; 59 | } 60 | 61 | ssize_t writen(int fd, const void *buf, size_t count) 62 | { 63 | size_t nleft = count; 64 | ssize_t nwritten; 65 | char* bufp = (char*)buf; 66 | 67 | while (nleft > 0) 68 | { 69 | if ((nwritten = write(fd, bufp, nleft)) < 0) 70 | { 71 | if (errno == EINTR) 72 | { 73 | continue; 74 | } 75 | return -1; 76 | } 77 | else if (nwritten == 0) 78 | { 79 | continue; 80 | } 81 | bufp += nwritten; 82 | nleft -= nwritten; 83 | } 84 | return count; 85 | } 86 | 87 | 88 | ssize_t recv_peek(int sockfd, void *buf, size_t len) 89 | { 90 | while (1) 91 | { 92 | int ret = recv(sockfd, buf, len, MSG_PEEK); // 查看传入消息 93 | if (ret == -1 && errno == EINTR) 94 | { 95 | continue; 96 | } 97 | return ret; 98 | } 99 | } 100 | 101 | ssize_t readline(int sockfd, void *buf, size_t maxline) 102 | { 103 | int ret; 104 | int nread; 105 | char *bufp = (char*)buf; // 当前指针位置 106 | int nleft = maxline; 107 | while (1) 108 | { 109 | ret = recv_peek(sockfd, buf, nleft); 110 | if (ret < 0) 111 | { 112 | return ret; 113 | } 114 | else if (ret == 0) 115 | { 116 | return ret; 117 | } 118 | nread = ret; 119 | int i; 120 | for (i = 0; i < nread; i++) 121 | { 122 | if (bufp[i] == '\n') 123 | { 124 | ret = readn(sockfd, bufp, i+1); 125 | if (ret != i+1) 126 | { 127 | exit(EXIT_FAILURE); 128 | } 129 | return ret; 130 | } 131 | } 132 | if (nread > nleft) 133 | { 134 | exit(EXIT_FAILURE); 135 | } 136 | nleft -= nread; 137 | ret = readn(sockfd, bufp, nread); 138 | if (ret != nread) 139 | { 140 | exit(EXIT_FAILURE); 141 | } 142 | bufp += nread; 143 | } 144 | return -1; 145 | } 146 | 147 | void ehco_cli(int sockfd) 148 | { 149 | // char recvbuf[1024]; 150 | // char sendbuf[1024]; 151 | // // struct packet recvbuf; 152 | // // struct packet sendbuf; 153 | // memset(recvbuf, 0, sizeof recvbuf); 154 | // memset(sendbuf, 0, sizeof sendbuf); 155 | // int n = 0; 156 | // while (fgets(sendbuf, sizeof sendbuf, stdin) != NULL) // 键盘输入获取 157 | // { 158 | // writen(sockfd, sendbuf, strlen(sendbuf)); // 写入服务器 159 | // 160 | // int ret = readline(sockfd, recvbuf, sizeof recvbuf); // 服务器读取 161 | // if (ret == -1) 162 | // { 163 | // ERR_EXIT("readline"); 164 | // } 165 | // if (ret == 0) 166 | // { 167 | // printf("server close\n"); 168 | // break; 169 | // } 170 | // 171 | // fputs(recvbuf, stdout); // 服务器返回数据输出 172 | // 173 | // // 清空 174 | // memset(recvbuf, 0, sizeof recvbuf); 175 | // memset(sendbuf, 0, sizeof sendbuf); 176 | // } 177 | fd_set rset; 178 | FD_ZERO(&rset); 179 | 180 | int nready; 181 | int maxfd; 182 | int fd_stdin = fileno(stdin); 183 | if (fd_stdin > sockfd) 184 | { 185 | maxfd = fd_stdin; 186 | } else { 187 | maxfd = sockfd; 188 | } 189 | 190 | char sendbuf[1024] = {0}; 191 | char recvbuf[1024] = {0}; 192 | 193 | while (1) 194 | { 195 | FD_SET(fd_stdin, &rset); 196 | FD_SET(sockfd, &rset); 197 | nready = select(maxfd+1, &rset, NULL, NULL, NULL); 198 | if (nready == -1) 199 | { 200 | ERR_EXIT("select"); 201 | } 202 | if (nready == 0) 203 | { 204 | continue; 205 | } 206 | 207 | if (FD_ISSET(sockfd, &rset)) // sock数据 读取 208 | { 209 | int ret = readline(sockfd, recvbuf, sizeof recvbuf); // 服务器读取 210 | if (ret == -1) 211 | { 212 | ERR_EXIT("readline"); 213 | } 214 | if (ret == 0) 215 | { 216 | printf("server close\n"); 217 | break; 218 | } 219 | 220 | fputs(recvbuf, stdout); // 服务器返回数据输出 221 | memset(recvbuf, 0, sizeof(recvbuf)); 222 | } 223 | 224 | if (FD_ISSET(fd_stdin, &rset)) 225 | { 226 | if (fgets(sendbuf, sizeof sendbuf, stdin) == NULL) // 键盘输入获取 227 | { 228 | // shutdown(sockfd, SHUT_WR); 229 | //close(sockfd); 230 | break; 231 | } else { 232 | writen(sockfd, sendbuf, strlen(sendbuf)); // 写入服务器 233 | } 234 | } 235 | } 236 | close(sockfd); 237 | }; 238 | 239 | void handle_sigchld(int sig) 240 | { 241 | // wait(NULL); 242 | while (waitpid(-1, NULL, WNOHANG) > 0); 243 | } 244 | 245 | int main(int argc, char** argv) { 246 | int count = 0; 247 | while (1) { 248 | // signal(SIGCHLD, SIG_IGN); 249 | signal(SIGCHLD, handle_sigchld); 250 | // 1. 创建套接字 251 | int sockfd; 252 | if ((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { 253 | ERR_EXIT("socket"); 254 | } 255 | 256 | // 2. 分配套接字地址 257 | struct sockaddr_in servaddr; 258 | memset(&servaddr, 0, sizeof servaddr); 259 | servaddr.sin_family = AF_INET; 260 | servaddr.sin_port = htons(6666); 261 | // servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 262 | servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); 263 | // inet_aton("127.0.0.1", &servaddr.sin_addr); 264 | 265 | // 3. 请求链接 266 | if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof servaddr) < 0) { 267 | ERR_EXIT("connect"); 268 | } 269 | 270 | struct sockaddr_in localaddr; 271 | socklen_t addrlen = sizeof localaddr; 272 | if (getsockname(sockfd, (struct sockaddr *) &localaddr, &addrlen) < 0) { 273 | ERR_EXIT("getsockname"); 274 | } 275 | printf("id = %s, ", inet_ntoa(localaddr.sin_addr)); 276 | printf("port = %d\n", ntohs(localaddr.sin_port)); 277 | printf("count = %d\n", ++count); 278 | // 4. 数据交换 279 | //ehco_cli(sockfd); 280 | 281 | // 5. 断开连接 282 | //close(sockfd); 283 | } 284 | 285 | return 0; 286 | } 287 | -------------------------------------------------------------------------------- /echocli.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-7-17. 3 | // 4 | 5 | // 视频 1 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | 17 | using namespace std; 18 | 19 | #define ERR_EXIT(m) \ 20 | do \ 21 | { \ 22 | perror(m); \ 23 | exit(EXIT_FAILURE); \ 24 | } while(0); 25 | 26 | int main(int argc, char** argv) { 27 | // 1. 创建套接字 28 | int sockfd; 29 | if ((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { 30 | ERR_EXIT("socket"); 31 | } 32 | 33 | // 2. 分配套接字地址 34 | struct sockaddr_in servaddr; 35 | memset(&servaddr, 0, sizeof servaddr); 36 | servaddr.sin_family = AF_INET; 37 | servaddr.sin_port = htons(6666); 38 | // servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 39 | servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); 40 | // inet_aton("127.0.0.1", &servaddr.sin_addr); 41 | 42 | // 3. 请求链接 43 | if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof servaddr) < 0) { 44 | ERR_EXIT("connect"); 45 | } 46 | 47 | // 4. 数据交换 48 | char recvbuf[1024]; 49 | char sendbuf[1024]; 50 | while (fgets(sendbuf, sizeof sendbuf, stdin) != NULL) // 键盘输入获取 51 | { 52 | // memset(recvbuf, 0, sizeof recvbuf); 53 | // memset(sendbuf, 0, sizeof sendbuf); 54 | write(sockfd, sendbuf, sizeof sendbuf); // 写入服务器 55 | int ret = read(sockfd, recvbuf, sizeof recvbuf); // 服务器读取 56 | if (ret == 0) 57 | { 58 | 59 | } else 60 | { 61 | 62 | } 63 | fputs(recvbuf, stdout); // 服务器返回数据输出 64 | 65 | // 清空 66 | memset(recvbuf, 0, sizeof recvbuf); 67 | memset(sendbuf, 0, sizeof sendbuf); 68 | } 69 | 70 | // 5. 断开连接 71 | close(sockfd); 72 | 73 | 74 | 75 | return 0; 76 | } 77 | -------------------------------------------------------------------------------- /echocli2.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-7-17. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | 15 | using namespace std; 16 | 17 | #define ERR_EXIT(m) \ 18 | do \ 19 | { \ 20 | perror(m); \ 21 | exit(EXIT_FAILURE); \ 22 | } while(0); 23 | 24 | int main(int argc, char** argv) { 25 | // 1. 创建套接字 26 | int sockfd; 27 | if ((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { 28 | ERR_EXIT("socket"); 29 | } 30 | 31 | // 2. 分配套接字地址 32 | struct sockaddr_in servaddr; 33 | memset(&servaddr, 0, sizeof servaddr); 34 | servaddr.sin_family = AF_INET; 35 | servaddr.sin_port = htons(6666); 36 | // servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 37 | servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); 38 | // inet_aton("127.0.0.1", &servaddr.sin_addr); 39 | 40 | // 3. 请求链接 41 | if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof servaddr) < 0) { 42 | ERR_EXIT("connect"); 43 | } 44 | 45 | // 4. 数据交换 46 | char recvbuf[1024]; 47 | char sendbuf[1024]; 48 | while (fgets(sendbuf, sizeof sendbuf, stdin) != NULL) // 键盘输入获取 49 | { 50 | // memset(recvbuf, 0, sizeof recvbuf); 51 | // memset(sendbuf, 0, sizeof sendbuf); 52 | write(sockfd, sendbuf, sizeof sendbuf); // 写入服务器 53 | int ret = read(sockfd, recvbuf, sizeof recvbuf); // 服务器读取 54 | if (ret == 0) 55 | { 56 | printf("server close\n"); 57 | break; 58 | } else if (ret == -1) 59 | { 60 | ERR_EXIT("read"); 61 | } 62 | fputs(recvbuf, stdout); // 服务器返回数据输出 63 | 64 | // 清空 65 | memset(recvbuf, 0, sizeof recvbuf); 66 | memset(sendbuf, 0, sizeof sendbuf); 67 | } 68 | 69 | // 5. 断开连接 70 | close(sockfd); 71 | 72 | 73 | 74 | return 0; 75 | } -------------------------------------------------------------------------------- /echocli3.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-7-21. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | 15 | using namespace std; 16 | 17 | struct packet 18 | { 19 | int len; 20 | char buf[1024]; 21 | }; 22 | 23 | #define ERR_EXIT(m) \ 24 | do \ 25 | { \ 26 | perror(m); \ 27 | exit(EXIT_FAILURE); \ 28 | } while(0); 29 | 30 | ssize_t readn(int fd, void *buf, size_t count) 31 | { 32 | size_t nleft = count; // 剩余字节数 33 | ssize_t nread; 34 | char *bufp = (char*) buf; 35 | 36 | while (nleft > 0) 37 | { 38 | nread = read(fd, bufp, nleft); 39 | if (nread < 0) 40 | { 41 | if (errno == EINTR) 42 | { 43 | continue; 44 | } 45 | return -1; 46 | } else if (nread == 0) 47 | { 48 | return count - nleft; 49 | } 50 | 51 | bufp += nread; 52 | nleft -= nread; 53 | } 54 | return count; 55 | } 56 | 57 | ssize_t writen(int fd, const void *buf, size_t count) 58 | { 59 | size_t nleft = count; 60 | ssize_t nwritten; 61 | char* bufp = (char*)buf; 62 | 63 | while (nleft > 0) 64 | { 65 | if ((nwritten = write(fd, bufp, nleft)) < 0) 66 | { 67 | if (errno == EINTR) 68 | { 69 | continue; 70 | } 71 | return -1; 72 | } 73 | else if (nwritten == 0) 74 | { 75 | continue; 76 | } 77 | bufp += nwritten; 78 | nleft -= nwritten; 79 | } 80 | return count; 81 | } 82 | 83 | int main(int argc, char** argv) { 84 | // 1. 创建套接字 85 | int sockfd; 86 | if ((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { 87 | ERR_EXIT("socket"); 88 | } 89 | 90 | // 2. 分配套接字地址 91 | struct sockaddr_in servaddr; 92 | memset(&servaddr, 0, sizeof servaddr); 93 | servaddr.sin_family = AF_INET; 94 | servaddr.sin_port = htons(6666); 95 | // servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 96 | servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); 97 | // inet_aton("127.0.0.1", &servaddr.sin_addr); 98 | 99 | // 3. 请求链接 100 | if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof servaddr) < 0) { 101 | ERR_EXIT("connect"); 102 | } 103 | 104 | // 4. 数据交换 105 | // char recvbuf[1024]; 106 | // char sendbuf[1024]; 107 | struct packet recvbuf; 108 | struct packet sendbuf; 109 | memset(&recvbuf, 0, sizeof recvbuf); 110 | memset(&sendbuf, 0, sizeof sendbuf); 111 | int n = 0; 112 | while (fgets(sendbuf.buf, sizeof sendbuf.buf, stdin) != NULL) // 键盘输入获取 113 | { 114 | n = strlen(sendbuf.buf); 115 | sendbuf.len = htonl(n); // 主机字节序转换为网络字节序 116 | writen(sockfd, &sendbuf, 4+n); // 写入服务器 117 | 118 | int ret = readn(sockfd, &recvbuf.len, 4); // 服务器读取 119 | if (ret == -1) 120 | { 121 | ERR_EXIT("read"); 122 | } 123 | else if (ret < 4) 124 | { 125 | printf("server close\n"); 126 | break; 127 | } 128 | 129 | n = ntohl(recvbuf.len); 130 | ret = readn(sockfd, &recvbuf.buf, n); 131 | if (ret == -1) 132 | { 133 | ERR_EXIT("read"); 134 | } 135 | else if (ret < n) 136 | { 137 | printf("server close\n"); 138 | break; 139 | } 140 | 141 | fputs(recvbuf.buf, stdout); // 服务器返回数据输出 142 | 143 | // 清空 144 | memset(&recvbuf, 0, sizeof recvbuf); 145 | memset(&sendbuf, 0, sizeof sendbuf); 146 | } 147 | 148 | // 5. 断开连接 149 | close(sockfd); 150 | 151 | 152 | return 0; 153 | } -------------------------------------------------------------------------------- /echocli4.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-6. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | 15 | using namespace std; 16 | 17 | struct packet 18 | { 19 | int len; 20 | char buf[1024]; 21 | }; 22 | 23 | #define ERR_EXIT(m) \ 24 | do \ 25 | { \ 26 | perror(m); \ 27 | exit(EXIT_FAILURE); \ 28 | } while(0); 29 | 30 | ssize_t readn(int fd, void *buf, size_t count) 31 | { 32 | size_t nleft = count; // 剩余字节数 33 | ssize_t nread; 34 | char *bufp = (char*) buf; 35 | 36 | while (nleft > 0) 37 | { 38 | nread = read(fd, bufp, nleft); 39 | if (nread < 0) 40 | { 41 | if (errno == EINTR) 42 | { 43 | continue; 44 | } 45 | return -1; 46 | } else if (nread == 0) 47 | { 48 | return count - nleft; 49 | } 50 | 51 | bufp += nread; 52 | nleft -= nread; 53 | } 54 | return count; 55 | } 56 | 57 | ssize_t writen(int fd, const void *buf, size_t count) 58 | { 59 | size_t nleft = count; 60 | ssize_t nwritten; 61 | char* bufp = (char*)buf; 62 | 63 | while (nleft > 0) 64 | { 65 | if ((nwritten = write(fd, bufp, nleft)) < 0) 66 | { 67 | if (errno == EINTR) 68 | { 69 | continue; 70 | } 71 | return -1; 72 | } 73 | else if (nwritten == 0) 74 | { 75 | continue; 76 | } 77 | bufp += nwritten; 78 | nleft -= nwritten; 79 | } 80 | return count; 81 | } 82 | 83 | 84 | ssize_t recv_peek(int sockfd, void *buf, size_t len) 85 | { 86 | while (1) 87 | { 88 | int ret = recv(sockfd, buf, len, MSG_PEEK); // 查看传入消息 89 | if (ret == -1 && errno == EINTR) 90 | { 91 | continue; 92 | } 93 | return ret; 94 | } 95 | } 96 | 97 | ssize_t readline(int sockfd, void *buf, size_t maxline) 98 | { 99 | int ret; 100 | int nread; 101 | char *bufp = (char*)buf; // 当前指针位置 102 | int nleft = maxline; 103 | while (1) 104 | { 105 | ret = recv_peek(sockfd, buf, nleft); 106 | if (ret < 0) 107 | { 108 | return ret; 109 | } 110 | else if (ret == 0) 111 | { 112 | return ret; 113 | } 114 | nread = ret; 115 | int i; 116 | for (i = 0; i < nread; i++) 117 | { 118 | if (bufp[i] == '\n') 119 | { 120 | ret = readn(sockfd, bufp, i+1); 121 | if (ret != i+1) 122 | { 123 | exit(EXIT_FAILURE); 124 | } 125 | return ret; 126 | } 127 | } 128 | if (nread > nleft) 129 | { 130 | exit(EXIT_FAILURE); 131 | } 132 | nleft -= nread; 133 | ret = readn(sockfd, bufp, nread); 134 | if (ret != nread) 135 | { 136 | exit(EXIT_FAILURE); 137 | } 138 | bufp += nread; 139 | } 140 | return -1; 141 | } 142 | 143 | int main(int argc, char** argv) { 144 | // 1. 创建套接字 145 | int sockfd; 146 | if ((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { 147 | ERR_EXIT("socket"); 148 | } 149 | 150 | // 2. 分配套接字地址 151 | struct sockaddr_in servaddr; 152 | memset(&servaddr, 0, sizeof servaddr); 153 | servaddr.sin_family = AF_INET; 154 | servaddr.sin_port = htons(6666); 155 | // servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 156 | servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); 157 | // inet_aton("127.0.0.1", &servaddr.sin_addr); 158 | 159 | // 3. 请求链接 160 | if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof servaddr) < 0) { 161 | ERR_EXIT("connect"); 162 | } 163 | 164 | struct sockaddr_in localaddr; 165 | socklen_t addrlen = sizeof localaddr; 166 | if (getsockname(sockfd, (struct sockaddr*)&localaddr, &addrlen) < 0) 167 | { 168 | ERR_EXIT("getsockname"); 169 | } 170 | printf("id = %s, ", inet_ntoa(localaddr.sin_addr)); 171 | printf("port = %d\n", ntohs(localaddr.sin_port)); 172 | 173 | // 4. 数据交换 174 | char recvbuf[1024]; 175 | char sendbuf[1024]; 176 | // struct packet recvbuf; 177 | // struct packet sendbuf; 178 | memset(recvbuf, 0, sizeof recvbuf); 179 | memset(sendbuf, 0, sizeof sendbuf); 180 | int n = 0; 181 | while (fgets(sendbuf, sizeof sendbuf, stdin) != NULL) // 键盘输入获取 182 | { 183 | writen(sockfd, sendbuf, strlen(sendbuf)); // 写入服务器 184 | 185 | int ret = readline(sockfd, recvbuf, sizeof recvbuf); // 服务器读取 186 | if (ret == -1) 187 | { 188 | ERR_EXIT("readline"); 189 | } 190 | if (ret == 0) 191 | { 192 | printf("server close\n"); 193 | break; 194 | } 195 | 196 | fputs(recvbuf, stdout); // 服务器返回数据输出 197 | 198 | // 清空 199 | memset(recvbuf, 0, sizeof recvbuf); 200 | memset(sendbuf, 0, sizeof sendbuf); 201 | } 202 | 203 | // 5. 断开连接 204 | close(sockfd); 205 | 206 | 207 | return 0; 208 | } -------------------------------------------------------------------------------- /echocli5.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-6. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | 17 | using namespace std; 18 | 19 | struct packet 20 | { 21 | int len; 22 | char buf[1024]; 23 | }; 24 | 25 | #define ERR_EXIT(m) \ 26 | do \ 27 | { \ 28 | perror(m); \ 29 | exit(EXIT_FAILURE); \ 30 | } while(0); 31 | 32 | ssize_t readn(int fd, void *buf, size_t count) 33 | { 34 | size_t nleft = count; // 剩余字节数 35 | ssize_t nread; 36 | char *bufp = (char*) buf; 37 | 38 | while (nleft > 0) 39 | { 40 | nread = read(fd, bufp, nleft); 41 | if (nread < 0) 42 | { 43 | if (errno == EINTR) 44 | { 45 | continue; 46 | } 47 | return -1; 48 | } else if (nread == 0) 49 | { 50 | return count - nleft; 51 | } 52 | 53 | bufp += nread; 54 | nleft -= nread; 55 | } 56 | return count; 57 | } 58 | 59 | ssize_t writen(int fd, const void *buf, size_t count) 60 | { 61 | size_t nleft = count; 62 | ssize_t nwritten; 63 | char* bufp = (char*)buf; 64 | 65 | while (nleft > 0) 66 | { 67 | if ((nwritten = write(fd, bufp, nleft)) < 0) 68 | { 69 | if (errno == EINTR) 70 | { 71 | continue; 72 | } 73 | return -1; 74 | } 75 | else if (nwritten == 0) 76 | { 77 | continue; 78 | } 79 | bufp += nwritten; 80 | nleft -= nwritten; 81 | } 82 | return count; 83 | } 84 | 85 | 86 | ssize_t recv_peek(int sockfd, void *buf, size_t len) 87 | { 88 | while (1) 89 | { 90 | int ret = recv(sockfd, buf, len, MSG_PEEK); // 查看传入消息 91 | if (ret == -1 && errno == EINTR) 92 | { 93 | continue; 94 | } 95 | return ret; 96 | } 97 | } 98 | 99 | ssize_t readline(int sockfd, void *buf, size_t maxline) 100 | { 101 | int ret; 102 | int nread; 103 | char *bufp = (char*)buf; // 当前指针位置 104 | int nleft = maxline; 105 | while (1) 106 | { 107 | ret = recv_peek(sockfd, buf, nleft); 108 | if (ret < 0) 109 | { 110 | return ret; 111 | } 112 | else if (ret == 0) 113 | { 114 | return ret; 115 | } 116 | nread = ret; 117 | int i; 118 | for (i = 0; i < nread; i++) 119 | { 120 | if (bufp[i] == '\n') 121 | { 122 | ret = readn(sockfd, bufp, i+1); 123 | if (ret != i+1) 124 | { 125 | exit(EXIT_FAILURE); 126 | } 127 | return ret; 128 | } 129 | } 130 | if (nread > nleft) 131 | { 132 | exit(EXIT_FAILURE); 133 | } 134 | nleft -= nread; 135 | ret = readn(sockfd, bufp, nread); 136 | if (ret != nread) 137 | { 138 | exit(EXIT_FAILURE); 139 | } 140 | bufp += nread; 141 | } 142 | return -1; 143 | } 144 | 145 | void ehco_cli(int sockfd) 146 | { 147 | char recvbuf[1024]; 148 | char sendbuf[1024]; 149 | // struct packet recvbuf; 150 | // struct packet sendbuf; 151 | memset(recvbuf, 0, sizeof recvbuf); 152 | memset(sendbuf, 0, sizeof sendbuf); 153 | int n = 0; 154 | while (fgets(sendbuf, sizeof sendbuf, stdin) != NULL) // 键盘输入获取 155 | { 156 | writen(sockfd, sendbuf, strlen(sendbuf)); // 写入服务器 157 | 158 | int ret = readline(sockfd, recvbuf, sizeof recvbuf); // 服务器读取 159 | if (ret == -1) 160 | { 161 | ERR_EXIT("readline"); 162 | } 163 | if (ret == 0) 164 | { 165 | printf("server close\n"); 166 | break; 167 | } 168 | 169 | fputs(recvbuf, stdout); // 服务器返回数据输出 170 | 171 | // 清空 172 | memset(recvbuf, 0, sizeof recvbuf); 173 | memset(sendbuf, 0, sizeof sendbuf); 174 | } 175 | } 176 | 177 | void handle_sigchld(int sig) 178 | { 179 | // wait(NULL); 180 | while (waitpid(-1, NULL, WNOHANG) > 0); 181 | } 182 | 183 | int main(int argc, char** argv) { 184 | // signal(SIGCHLD, SIG_IGN); 185 | signal(SIGCHLD, handle_sigchld); 186 | // 1. 创建套接字 187 | int sockfd[5]; 188 | int i; 189 | for (i = 0; i < 5; ++i) 190 | { 191 | if ((sockfd[i] = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { 192 | ERR_EXIT("socket"); 193 | } 194 | 195 | // 2. 分配套接字地址 196 | struct sockaddr_in servaddr; 197 | memset(&servaddr, 0, sizeof servaddr); 198 | servaddr.sin_family = AF_INET; 199 | servaddr.sin_port = htons(6666); 200 | // servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 201 | servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); 202 | // inet_aton("127.0.0.1", &servaddr.sin_addr); 203 | 204 | // 3. 请求链接 205 | if (connect(sockfd[i], (struct sockaddr *) &servaddr, sizeof servaddr) < 0) { 206 | ERR_EXIT("connect"); 207 | } 208 | 209 | struct sockaddr_in localaddr; 210 | socklen_t addrlen = sizeof localaddr; 211 | if (getsockname(sockfd[i], (struct sockaddr*)&localaddr, &addrlen) < 0) 212 | { 213 | ERR_EXIT("getsockname"); 214 | } 215 | printf("id = %s, ", inet_ntoa(localaddr.sin_addr)); 216 | printf("port = %d\n", ntohs(localaddr.sin_port)); 217 | 218 | } 219 | // 4. 数据交换 220 | ehco_cli(sockfd[0]); 221 | 222 | // 5. 断开连接 223 | close(sockfd[0]); 224 | 225 | 226 | return 0; 227 | } -------------------------------------------------------------------------------- /echocli6.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-6. 3 | // 4 | 5 | // socket编程 8 select模型 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | 19 | using namespace std; 20 | 21 | struct packet 22 | { 23 | int len; 24 | char buf[1024]; 25 | }; 26 | 27 | #define ERR_EXIT(m) \ 28 | do \ 29 | { \ 30 | perror(m); \ 31 | exit(EXIT_FAILURE); \ 32 | } while(0); 33 | 34 | ssize_t readn(int fd, void *buf, size_t count) 35 | { 36 | size_t nleft = count; // 剩余字节数 37 | ssize_t nread; 38 | char *bufp = (char*) buf; 39 | 40 | while (nleft > 0) 41 | { 42 | nread = read(fd, bufp, nleft); 43 | if (nread < 0) 44 | { 45 | if (errno == EINTR) 46 | { 47 | continue; 48 | } 49 | return -1; 50 | } else if (nread == 0) 51 | { 52 | return count - nleft; 53 | } 54 | 55 | bufp += nread; 56 | nleft -= nread; 57 | } 58 | return count; 59 | } 60 | 61 | ssize_t writen(int fd, const void *buf, size_t count) 62 | { 63 | size_t nleft = count; 64 | ssize_t nwritten; 65 | char* bufp = (char*)buf; 66 | 67 | while (nleft > 0) 68 | { 69 | if ((nwritten = write(fd, bufp, nleft)) < 0) 70 | { 71 | if (errno == EINTR) 72 | { 73 | continue; 74 | } 75 | return -1; 76 | } 77 | else if (nwritten == 0) 78 | { 79 | continue; 80 | } 81 | bufp += nwritten; 82 | nleft -= nwritten; 83 | } 84 | return count; 85 | } 86 | 87 | 88 | ssize_t recv_peek(int sockfd, void *buf, size_t len) 89 | { 90 | while (1) 91 | { 92 | int ret = recv(sockfd, buf, len, MSG_PEEK); // 查看传入消息 93 | if (ret == -1 && errno == EINTR) 94 | { 95 | continue; 96 | } 97 | return ret; 98 | } 99 | } 100 | 101 | ssize_t readline(int sockfd, void *buf, size_t maxline) 102 | { 103 | int ret; 104 | int nread; 105 | char *bufp = (char*)buf; // 当前指针位置 106 | int nleft = maxline; 107 | while (1) 108 | { 109 | ret = recv_peek(sockfd, buf, nleft); 110 | if (ret < 0) 111 | { 112 | return ret; 113 | } 114 | else if (ret == 0) 115 | { 116 | return ret; 117 | } 118 | nread = ret; 119 | int i; 120 | for (i = 0; i < nread; i++) 121 | { 122 | if (bufp[i] == '\n') 123 | { 124 | ret = readn(sockfd, bufp, i+1); 125 | if (ret != i+1) 126 | { 127 | exit(EXIT_FAILURE); 128 | } 129 | return ret; 130 | } 131 | } 132 | if (nread > nleft) 133 | { 134 | exit(EXIT_FAILURE); 135 | } 136 | nleft -= nread; 137 | ret = readn(sockfd, bufp, nread); 138 | if (ret != nread) 139 | { 140 | exit(EXIT_FAILURE); 141 | } 142 | bufp += nread; 143 | } 144 | return -1; 145 | } 146 | 147 | void ehco_cli(int sockfd) 148 | { 149 | // char recvbuf[1024]; 150 | // char sendbuf[1024]; 151 | // // struct packet recvbuf; 152 | // // struct packet sendbuf; 153 | // memset(recvbuf, 0, sizeof recvbuf); 154 | // memset(sendbuf, 0, sizeof sendbuf); 155 | // int n = 0; 156 | // while (fgets(sendbuf, sizeof sendbuf, stdin) != NULL) // 键盘输入获取 157 | // { 158 | // writen(sockfd, sendbuf, strlen(sendbuf)); // 写入服务器 159 | // 160 | // int ret = readline(sockfd, recvbuf, sizeof recvbuf); // 服务器读取 161 | // if (ret == -1) 162 | // { 163 | // ERR_EXIT("readline"); 164 | // } 165 | // if (ret == 0) 166 | // { 167 | // printf("server close\n"); 168 | // break; 169 | // } 170 | // 171 | // fputs(recvbuf, stdout); // 服务器返回数据输出 172 | // 173 | // // 清空 174 | // memset(recvbuf, 0, sizeof recvbuf); 175 | // memset(sendbuf, 0, sizeof sendbuf); 176 | // } 177 | fd_set rset; 178 | FD_ZERO(&rset); 179 | 180 | int nready; 181 | int maxfd; 182 | int fd_stdin = fileno(stdin); 183 | if (fd_stdin > sockfd) 184 | { 185 | maxfd = fd_stdin; 186 | } else { 187 | maxfd = sockfd; 188 | } 189 | 190 | char sendbuf[1024] = {0}; 191 | char recvbuf[1024] = {0}; 192 | 193 | while (1) 194 | { 195 | FD_SET(fd_stdin, &rset); 196 | FD_SET(sockfd, &rset); 197 | nready = select(maxfd+1, &rset, NULL, NULL, NULL); 198 | if (nready == -1) 199 | { 200 | ERR_EXIT("select"); 201 | } 202 | if (nready == 0) 203 | { 204 | continue; 205 | } 206 | 207 | if (FD_ISSET(sockfd, &rset)) // sock数据 读取 208 | { 209 | int ret = readline(sockfd, recvbuf, sizeof recvbuf); // 服务器读取 210 | if (ret == -1) 211 | { 212 | ERR_EXIT("readline"); 213 | } 214 | if (ret == 0) 215 | { 216 | printf("server close\n"); 217 | break; 218 | } 219 | 220 | fputs(recvbuf, stdout); // 服务器返回数据输出 221 | memset(recvbuf, 0, sizeof(recvbuf)); 222 | } 223 | 224 | if (FD_ISSET(fd_stdin, &rset)) 225 | { 226 | if (fgets(sendbuf, sizeof sendbuf, stdin) == NULL) // 键盘输入获取 227 | { 228 | break; 229 | } 230 | writen(sockfd, sendbuf, strlen(sendbuf)); // 写入服务器 231 | } 232 | } 233 | close(sockfd); 234 | }; 235 | 236 | void handle_sigchld(int sig) 237 | { 238 | // wait(NULL); 239 | while (waitpid(-1, NULL, WNOHANG) > 0); 240 | } 241 | 242 | int main(int argc, char** argv) { 243 | // signal(SIGCHLD, SIG_IGN); 244 | signal(SIGCHLD, handle_sigchld); 245 | // 1. 创建套接字 246 | int sockfd; 247 | if ((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { 248 | ERR_EXIT("socket"); 249 | } 250 | 251 | // 2. 分配套接字地址 252 | struct sockaddr_in servaddr; 253 | memset(&servaddr, 0, sizeof servaddr); 254 | servaddr.sin_family = AF_INET; 255 | servaddr.sin_port = htons(6666); 256 | // servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 257 | servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); 258 | // inet_aton("127.0.0.1", &servaddr.sin_addr); 259 | 260 | // 3. 请求链接 261 | if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof servaddr) < 0) { 262 | ERR_EXIT("connect"); 263 | } 264 | 265 | struct sockaddr_in localaddr; 266 | socklen_t addrlen = sizeof localaddr; 267 | if (getsockname(sockfd, (struct sockaddr*)&localaddr, &addrlen) < 0) 268 | { 269 | ERR_EXIT("getsockname"); 270 | } 271 | printf("id = %s, ", inet_ntoa(localaddr.sin_addr)); 272 | printf("port = %d\n", ntohs(localaddr.sin_port)); 273 | 274 | // 4. 数据交换 275 | ehco_cli(sockfd); 276 | 277 | // 5. 断开连接 278 | close(sockfd); 279 | 280 | 281 | return 0; 282 | } -------------------------------------------------------------------------------- /echocli7.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-7. 3 | // 4 | 5 | // socket编程 9 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | 19 | using namespace std; 20 | 21 | struct packet 22 | { 23 | int len; 24 | char buf[1024]; 25 | }; 26 | 27 | #define ERR_EXIT(m) \ 28 | do \ 29 | { \ 30 | perror(m); \ 31 | exit(EXIT_FAILURE); \ 32 | } while(0); 33 | 34 | ssize_t readn(int fd, void *buf, size_t count) 35 | { 36 | size_t nleft = count; // 剩余字节数 37 | ssize_t nread; 38 | char *bufp = (char*) buf; 39 | 40 | while (nleft > 0) 41 | { 42 | nread = read(fd, bufp, nleft); 43 | if (nread < 0) 44 | { 45 | if (errno == EINTR) 46 | { 47 | continue; 48 | } 49 | return -1; 50 | } else if (nread == 0) 51 | { 52 | return count - nleft; 53 | } 54 | 55 | bufp += nread; 56 | nleft -= nread; 57 | } 58 | return count; 59 | } 60 | 61 | ssize_t writen(int fd, const void *buf, size_t count) 62 | { 63 | size_t nleft = count; 64 | ssize_t nwritten; 65 | char* bufp = (char*)buf; 66 | 67 | while (nleft > 0) 68 | { 69 | if ((nwritten = write(fd, bufp, nleft)) < 0) 70 | { 71 | if (errno == EINTR) 72 | { 73 | continue; 74 | } 75 | return -1; 76 | } 77 | else if (nwritten == 0) 78 | { 79 | continue; 80 | } 81 | bufp += nwritten; 82 | nleft -= nwritten; 83 | } 84 | return count; 85 | } 86 | 87 | 88 | ssize_t recv_peek(int sockfd, void *buf, size_t len) 89 | { 90 | while (1) 91 | { 92 | int ret = recv(sockfd, buf, len, MSG_PEEK); // 查看传入消息 93 | if (ret == -1 && errno == EINTR) 94 | { 95 | continue; 96 | } 97 | return ret; 98 | } 99 | } 100 | 101 | ssize_t readline(int sockfd, void *buf, size_t maxline) 102 | { 103 | int ret; 104 | int nread; 105 | char *bufp = (char*)buf; // 当前指针位置 106 | int nleft = maxline; 107 | while (1) 108 | { 109 | ret = recv_peek(sockfd, buf, nleft); 110 | if (ret < 0) 111 | { 112 | return ret; 113 | } 114 | else if (ret == 0) 115 | { 116 | return ret; 117 | } 118 | nread = ret; 119 | int i; 120 | for (i = 0; i < nread; i++) 121 | { 122 | if (bufp[i] == '\n') 123 | { 124 | ret = readn(sockfd, bufp, i+1); 125 | if (ret != i+1) 126 | { 127 | exit(EXIT_FAILURE); 128 | } 129 | return ret; 130 | } 131 | } 132 | if (nread > nleft) 133 | { 134 | exit(EXIT_FAILURE); 135 | } 136 | nleft -= nread; 137 | ret = readn(sockfd, bufp, nread); 138 | if (ret != nread) 139 | { 140 | exit(EXIT_FAILURE); 141 | } 142 | bufp += nread; 143 | } 144 | return -1; 145 | } 146 | 147 | void ehco_cli(int sockfd) 148 | { 149 | // char recvbuf[1024]; 150 | // char sendbuf[1024]; 151 | // // struct packet recvbuf; 152 | // // struct packet sendbuf; 153 | // memset(recvbuf, 0, sizeof recvbuf); 154 | // memset(sendbuf, 0, sizeof sendbuf); 155 | // int n = 0; 156 | // while (fgets(sendbuf, sizeof sendbuf, stdin) != NULL) // 键盘输入获取 157 | // { 158 | // writen(sockfd, sendbuf, strlen(sendbuf)); // 写入服务器 159 | // 160 | // int ret = readline(sockfd, recvbuf, sizeof recvbuf); // 服务器读取 161 | // if (ret == -1) 162 | // { 163 | // ERR_EXIT("readline"); 164 | // } 165 | // if (ret == 0) 166 | // { 167 | // printf("server close\n"); 168 | // break; 169 | // } 170 | // 171 | // fputs(recvbuf, stdout); // 服务器返回数据输出 172 | // 173 | // // 清空 174 | // memset(recvbuf, 0, sizeof recvbuf); 175 | // memset(sendbuf, 0, sizeof sendbuf); 176 | // } 177 | fd_set rset; 178 | FD_ZERO(&rset); 179 | 180 | int nready; 181 | int maxfd; 182 | int fd_stdin = fileno(stdin); 183 | if (fd_stdin > sockfd) 184 | { 185 | maxfd = fd_stdin; 186 | } else { 187 | maxfd = sockfd; 188 | } 189 | 190 | char sendbuf[1024] = {0}; 191 | char recvbuf[1024] = {0}; 192 | 193 | while (1) 194 | { 195 | FD_SET(fd_stdin, &rset); 196 | FD_SET(sockfd, &rset); 197 | nready = select(maxfd+1, &rset, NULL, NULL, NULL); 198 | if (nready == -1) 199 | { 200 | ERR_EXIT("select"); 201 | } 202 | if (nready == 0) 203 | { 204 | continue; 205 | } 206 | 207 | if (FD_ISSET(sockfd, &rset)) // sock数据 读取 208 | { 209 | int ret = readline(sockfd, recvbuf, sizeof recvbuf); // 服务器读取 210 | if (ret == -1) 211 | { 212 | ERR_EXIT("readline"); 213 | } 214 | if (ret == 0) 215 | { 216 | printf("server close\n"); 217 | break; 218 | } 219 | 220 | fputs(recvbuf, stdout); // 服务器返回数据输出 221 | memset(recvbuf, 0, sizeof(recvbuf)); 222 | } 223 | 224 | if (FD_ISSET(fd_stdin, &rset)) 225 | { 226 | if (fgets(sendbuf, sizeof sendbuf, stdin) == NULL) // 键盘输入获取 227 | { 228 | // shutdown(sockfd, SHUT_WR); 229 | //close(sockfd); 230 | break; 231 | } else { 232 | writen(sockfd, sendbuf, strlen(sendbuf)); // 写入服务器 233 | } 234 | } 235 | } 236 | close(sockfd); 237 | }; 238 | 239 | void handle_sigchld(int sig) 240 | { 241 | // wait(NULL); 242 | while (waitpid(-1, NULL, WNOHANG) > 0); 243 | } 244 | 245 | int main(int argc, char** argv) { 246 | // signal(SIGCHLD, SIG_IGN); 247 | signal(SIGCHLD, handle_sigchld); 248 | // 1. 创建套接字 249 | int sockfd; 250 | if ((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { 251 | ERR_EXIT("socket"); 252 | } 253 | 254 | // 2. 分配套接字地址 255 | struct sockaddr_in servaddr; 256 | memset(&servaddr, 0, sizeof servaddr); 257 | servaddr.sin_family = AF_INET; 258 | servaddr.sin_port = htons(6666); 259 | // servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 260 | servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); 261 | // inet_aton("127.0.0.1", &servaddr.sin_addr); 262 | 263 | // 3. 请求链接 264 | if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof servaddr) < 0) { 265 | ERR_EXIT("connect"); 266 | } 267 | 268 | struct sockaddr_in localaddr; 269 | socklen_t addrlen = sizeof localaddr; 270 | if (getsockname(sockfd, (struct sockaddr *) &localaddr, &addrlen) < 0) { 271 | ERR_EXIT("getsockname"); 272 | } 273 | printf("id = %s, ", inet_ntoa(localaddr.sin_addr)); 274 | printf("port = %d\n", ntohs(localaddr.sin_port)); 275 | 276 | // 4. 数据交换 277 | ehco_cli(sockfd); 278 | 279 | // 5. 断开连接 280 | close(sockfd); 281 | 282 | 283 | return 0; 284 | } -------------------------------------------------------------------------------- /echosrv.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-7-17. 3 | // 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | 14 | using namespace std; 15 | 16 | #define ERR_EXIT(m) \ 17 | do \ 18 | { \ 19 | perror(m); \ 20 | exit(EXIT_FAILURE); \ 21 | } while(0); 22 | 23 | int main(int argc, char** argv) { 24 | // 1. 创建套接字 25 | int listenfd; 26 | if ((listenfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { 27 | ERR_EXIT("socket"); 28 | } 29 | 30 | // 2. 分配套接字地址 31 | struct sockaddr_in servaddr; 32 | memset(&servaddr, 0, sizeof servaddr); 33 | servaddr.sin_family = AF_INET; 34 | servaddr.sin_port = htons(6666); 35 | servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 36 | // servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); 37 | // inet_aton("127.0.0.1", &servaddr.sin_addr); 38 | 39 | int on = 1; 40 | // 确保time_wait状态下同一端口仍可使用 41 | if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on) < 0) 42 | { 43 | ERR_EXIT("setsockopt"); 44 | } 45 | 46 | // 3. 绑定套接字地址 47 | if (bind(listenfd, (struct sockaddr*) &servaddr, sizeof servaddr) < 0) { 48 | ERR_EXIT("bind"); 49 | } 50 | // 4. 等待连接请求状态 51 | if (listen(listenfd, SOMAXCONN) < 0) { 52 | ERR_EXIT("listen"); 53 | } 54 | // 5. 允许连接 55 | struct sockaddr_in peeraddr; 56 | socklen_t peerlen = sizeof peeraddr; 57 | int connfd; 58 | if ((connfd = accept(listenfd, (struct sockaddr *) &peeraddr, &peerlen)) < 0) { 59 | ERR_EXIT("accept"); 60 | } 61 | 62 | printf("id = %s, ", inet_ntoa(peeraddr.sin_addr)); 63 | printf("port = %d\n", ntohs(peeraddr.sin_port)); 64 | 65 | // 6. 数据交换 66 | char recvbuf[1024]; 67 | while (1) 68 | { 69 | memset(recvbuf, 0, sizeof recvbuf); 70 | int ret = read(connfd, recvbuf, sizeof recvbuf); 71 | if (ret == 0) 72 | { 73 | 74 | } else 75 | { 76 | 77 | } 78 | fputs(recvbuf, stdout); 79 | write(connfd, recvbuf, ret); 80 | } 81 | 82 | // 7. 断开连接 83 | close(connfd); 84 | close(listenfd); 85 | 86 | 87 | 88 | return 0; 89 | } 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /echosrv2.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-7-17. 3 | // 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | 14 | using namespace std; 15 | 16 | 17 | #define ERR_EXIT(m) \ 18 | do \ 19 | { \ 20 | perror(m); \ 21 | exit(EXIT_FAILURE); \ 22 | } while(0); 23 | 24 | void do_service(int connfd) 25 | { 26 | char recvbuf[1024]; 27 | while (1) 28 | { 29 | memset(recvbuf, 0, sizeof recvbuf); 30 | int ret = read(connfd, recvbuf, sizeof recvbuf); 31 | if (ret == 0) 32 | { 33 | printf("client close\n"); 34 | break; 35 | } else if (ret == -1) 36 | { 37 | ERR_EXIT("read"); 38 | } 39 | fputs(recvbuf, stdout); 40 | write(connfd, recvbuf, ret); 41 | } 42 | 43 | } 44 | 45 | int main(int argc, char** argv) { 46 | // 1. 创建套接字 47 | int listenfd; 48 | if ((listenfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { 49 | ERR_EXIT("socket"); 50 | } 51 | 52 | // 2. 分配套接字地址 53 | struct sockaddr_in servaddr; 54 | memset(&servaddr, 0, sizeof servaddr); 55 | servaddr.sin_family = AF_INET; 56 | servaddr.sin_port = htons(6666); 57 | servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 58 | // servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); 59 | // inet_aton("127.0.0.1", &servaddr.sin_addr); 60 | 61 | int on = 1; 62 | // 确保time_wait状态下同一端口仍可使用 63 | if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on) < 0) 64 | { 65 | ERR_EXIT("setsockopt"); 66 | } 67 | 68 | // 3. 绑定套接字地址 69 | if (bind(listenfd, (struct sockaddr*) &servaddr, sizeof servaddr) < 0) { 70 | ERR_EXIT("bind"); 71 | } 72 | // 4. 等待连接请求状态 73 | if (listen(listenfd, SOMAXCONN) < 0) { 74 | ERR_EXIT("listen"); 75 | } 76 | // 5. 允许连接 77 | struct sockaddr_in peeraddr; 78 | socklen_t peerlen = sizeof peeraddr; 79 | 80 | 81 | // 6. 数据交换 82 | pid_t pid; 83 | while (1) 84 | { 85 | int connfd; 86 | if ((connfd = accept(listenfd, (struct sockaddr *) &peeraddr, &peerlen)) < 0) { 87 | ERR_EXIT("accept"); 88 | } 89 | 90 | printf("id = %s, ", inet_ntoa(peeraddr.sin_addr)); 91 | printf("port = %d\n", ntohs(peeraddr.sin_port)); 92 | 93 | pid = fork(); 94 | 95 | if (pid == -1) 96 | { 97 | ERR_EXIT("fork"); 98 | } 99 | if (pid == 0) // 子进程 100 | { 101 | close(listenfd); 102 | do_service(connfd); 103 | //printf("child exit\n"); 104 | exit(EXIT_SUCCESS); 105 | } 106 | else 107 | { 108 | //printf("parent exit\n"); 109 | close(connfd); 110 | } 111 | 112 | 113 | } 114 | // 7. 断开连接 115 | close(listenfd); 116 | 117 | 118 | 119 | return 0; 120 | } 121 | 122 | -------------------------------------------------------------------------------- /echosrv3.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-7-21. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | 15 | using namespace std; 16 | 17 | struct packet 18 | { 19 | int len; 20 | char buf[1024]; 21 | }; 22 | 23 | #define ERR_EXIT(m) \ 24 | do \ 25 | { \ 26 | perror(m); \ 27 | exit(EXIT_FAILURE); \ 28 | } while(0); 29 | 30 | ssize_t readn(int fd, void *buf, size_t count) 31 | { 32 | size_t nleft = count; // 剩余字节数 33 | ssize_t nread; 34 | char *bufp = (char*) buf; 35 | 36 | while (nleft > 0) 37 | { 38 | nread = read(fd, bufp, nleft); 39 | if (nread < 0) 40 | { 41 | if (errno == EINTR) 42 | { 43 | continue; 44 | } 45 | return -1; 46 | } else if (nread == 0) 47 | { 48 | return count - nleft; 49 | } 50 | 51 | bufp += nread; 52 | nleft -= nread; 53 | } 54 | return count; 55 | } 56 | 57 | ssize_t writen(int fd, const void *buf, size_t count) 58 | { 59 | size_t nleft = count; 60 | ssize_t nwritten; 61 | char* bufp = (char*)buf; 62 | 63 | while (nleft > 0) 64 | { 65 | if ((nwritten = write(fd, bufp, nleft)) < 0) 66 | { 67 | if (errno == EINTR) 68 | { 69 | continue; 70 | } 71 | return -1; 72 | } 73 | else if (nwritten == 0) 74 | { 75 | continue; 76 | } 77 | bufp += nwritten; 78 | nleft -= nwritten; 79 | } 80 | return count; 81 | } 82 | 83 | void do_service(int connfd) 84 | { 85 | // char recvbuf[1024]; 86 | struct packet recvbuf; 87 | int n; 88 | while (1) 89 | { 90 | memset(&recvbuf, 0, sizeof recvbuf); 91 | int ret = readn(connfd, &recvbuf.len, 4); 92 | if (ret == -1) 93 | { 94 | ERR_EXIT("read"); 95 | } 96 | else if (ret < 4) 97 | { 98 | printf("client close\n"); 99 | break; 100 | } 101 | 102 | n = ntohl(recvbuf.len); 103 | ret = readn(connfd, recvbuf.buf, n); 104 | if (ret == -1) 105 | { 106 | ERR_EXIT("read"); 107 | } 108 | else if (ret < n) 109 | { 110 | printf("client close\n"); 111 | break; 112 | } 113 | fputs(recvbuf.buf, stdout); 114 | writen(connfd, &recvbuf, 4+n); 115 | } 116 | 117 | } 118 | 119 | int main(int argc, char** argv) { 120 | // 1. 创建套接字 121 | int listenfd; 122 | if ((listenfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { 123 | ERR_EXIT("socket"); 124 | } 125 | 126 | // 2. 分配套接字地址 127 | struct sockaddr_in servaddr; 128 | memset(&servaddr, 0, sizeof servaddr); 129 | servaddr.sin_family = AF_INET; 130 | servaddr.sin_port = htons(6666); 131 | servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 132 | // servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); 133 | // inet_aton("127.0.0.1", &servaddr.sin_addr); 134 | 135 | int on = 1; 136 | // 确保time_wait状态下同一端口仍可使用 137 | if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on) < 0) 138 | { 139 | ERR_EXIT("setsockopt"); 140 | } 141 | 142 | // 3. 绑定套接字地址 143 | if (bind(listenfd, (struct sockaddr*) &servaddr, sizeof servaddr) < 0) { 144 | ERR_EXIT("bind"); 145 | } 146 | // 4. 等待连接请求状态 147 | if (listen(listenfd, SOMAXCONN) < 0) { 148 | ERR_EXIT("listen"); 149 | } 150 | // 5. 允许连接 151 | struct sockaddr_in peeraddr; 152 | socklen_t peerlen = sizeof peeraddr; 153 | 154 | 155 | // 6. 数据交换 156 | pid_t pid; 157 | while (1) 158 | { 159 | int connfd; 160 | if ((connfd = accept(listenfd, (struct sockaddr *) &peeraddr, &peerlen)) < 0) { 161 | ERR_EXIT("accept"); 162 | } 163 | 164 | printf("id = %s, ", inet_ntoa(peeraddr.sin_addr)); 165 | printf("port = %d\n", ntohs(peeraddr.sin_port)); 166 | 167 | pid = fork(); 168 | 169 | if (pid == -1) 170 | { 171 | ERR_EXIT("fork"); 172 | } 173 | if (pid == 0) // 子进程 174 | { 175 | close(listenfd); 176 | do_service(connfd); 177 | //printf("child exit\n"); 178 | exit(EXIT_SUCCESS); 179 | } 180 | else 181 | { 182 | //printf("parent exit\n"); 183 | close(connfd); 184 | } 185 | 186 | 187 | } 188 | // 7. 断开连接 189 | close(listenfd); 190 | 191 | 192 | 193 | return 0; 194 | } -------------------------------------------------------------------------------- /echosrv4.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-6. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | 15 | using namespace std; 16 | 17 | struct packet 18 | { 19 | int len; 20 | char buf[1024]; 21 | }; 22 | 23 | #define ERR_EXIT(m) \ 24 | do \ 25 | { \ 26 | perror(m); \ 27 | exit(EXIT_FAILURE); \ 28 | } while(0); 29 | 30 | ssize_t readn(int fd, void *buf, size_t count) 31 | { 32 | size_t nleft = count; // 剩余字节数 33 | ssize_t nread; 34 | char *bufp = (char*) buf; 35 | 36 | while (nleft > 0) 37 | { 38 | nread = read(fd, bufp, nleft); 39 | if (nread < 0) 40 | { 41 | if (errno == EINTR) 42 | { 43 | continue; 44 | } 45 | return -1; 46 | } else if (nread == 0) 47 | { 48 | return count - nleft; 49 | } 50 | 51 | bufp += nread; 52 | nleft -= nread; 53 | } 54 | return count; 55 | } 56 | 57 | ssize_t writen(int fd, const void *buf, size_t count) 58 | { 59 | size_t nleft = count; 60 | ssize_t nwritten; 61 | char* bufp = (char*)buf; 62 | 63 | while (nleft > 0) 64 | { 65 | if ((nwritten = write(fd, bufp, nleft)) < 0) 66 | { 67 | if (errno == EINTR) 68 | { 69 | continue; 70 | } 71 | return -1; 72 | } 73 | else if (nwritten == 0) 74 | { 75 | continue; 76 | } 77 | bufp += nwritten; 78 | nleft -= nwritten; 79 | } 80 | return count; 81 | } 82 | 83 | ssize_t recv_peek(int sockfd, void *buf, size_t len) 84 | { 85 | while (1) 86 | { 87 | int ret = recv(sockfd, buf, len, MSG_PEEK); // 查看传入消息 88 | if (ret == -1 && errno == EINTR) 89 | { 90 | continue; 91 | } 92 | return ret; 93 | } 94 | } 95 | 96 | ssize_t readline(int sockfd, void *buf, size_t maxline) 97 | { 98 | int ret; 99 | int nread; 100 | char *bufp = (char*)buf; // 当前指针位置 101 | int nleft = maxline; 102 | while (1) 103 | { 104 | ret = recv_peek(sockfd, buf, nleft); 105 | if (ret < 0) 106 | { 107 | return ret; 108 | } 109 | else if (ret == 0) 110 | { 111 | return ret; 112 | } 113 | nread = ret; 114 | int i; 115 | for (i = 0; i < nread; i++) 116 | { 117 | if (bufp[i] == '\n') 118 | { 119 | ret = readn(sockfd, bufp, i+1); 120 | if (ret != i+1) 121 | { 122 | exit(EXIT_FAILURE); 123 | } 124 | return ret; 125 | } 126 | } 127 | if (nread > nleft) 128 | { 129 | exit(EXIT_FAILURE); 130 | } 131 | nleft -= nread; 132 | ret = readn(sockfd, bufp, nread); 133 | if (ret != nread) 134 | { 135 | exit(EXIT_FAILURE); 136 | } 137 | bufp += nread; 138 | } 139 | return -1; 140 | } 141 | 142 | void do_service(int connfd) 143 | { 144 | char recvbuf[1024]; 145 | // struct packet recvbuf; 146 | int n; 147 | while (1) 148 | { 149 | memset(recvbuf, 0, sizeof recvbuf); 150 | int ret = readline(connfd, recvbuf, 1024); 151 | if (ret == -1) 152 | { 153 | ERR_EXIT("readline"); 154 | } 155 | if (ret == 0) 156 | { 157 | printf("client close\n"); 158 | break; 159 | } 160 | 161 | fputs(recvbuf, stdout); 162 | writen(connfd, recvbuf, strlen(recvbuf)); 163 | } 164 | 165 | } 166 | 167 | int main(int argc, char** argv) { 168 | // 1. 创建套接字 169 | int listenfd; 170 | if ((listenfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { 171 | ERR_EXIT("socket"); 172 | } 173 | 174 | // 2. 分配套接字地址 175 | struct sockaddr_in servaddr; 176 | memset(&servaddr, 0, sizeof servaddr); 177 | servaddr.sin_family = AF_INET; 178 | servaddr.sin_port = htons(6666); 179 | servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 180 | // servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); 181 | // inet_aton("127.0.0.1", &servaddr.sin_addr); 182 | 183 | int on = 1; 184 | // 确保time_wait状态下同一端口仍可使用 185 | if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on) < 0) 186 | { 187 | ERR_EXIT("setsockopt"); 188 | } 189 | 190 | // 3. 绑定套接字地址 191 | if (bind(listenfd, (struct sockaddr*) &servaddr, sizeof servaddr) < 0) { 192 | ERR_EXIT("bind"); 193 | } 194 | // 4. 等待连接请求状态 195 | if (listen(listenfd, SOMAXCONN) < 0) { 196 | ERR_EXIT("listen"); 197 | } 198 | // 5. 允许连接 199 | struct sockaddr_in peeraddr; 200 | socklen_t peerlen = sizeof peeraddr; 201 | 202 | 203 | // 6. 数据交换 204 | pid_t pid; 205 | while (1) 206 | { 207 | int connfd; 208 | if ((connfd = accept(listenfd, (struct sockaddr *) &peeraddr, &peerlen)) < 0) { 209 | ERR_EXIT("accept"); 210 | } 211 | 212 | printf("id = %s, ", inet_ntoa(peeraddr.sin_addr)); 213 | printf("port = %d\n", ntohs(peeraddr.sin_port)); 214 | 215 | pid = fork(); 216 | 217 | if (pid == -1) 218 | { 219 | ERR_EXIT("fork"); 220 | } 221 | if (pid == 0) // 子进程 222 | { 223 | close(listenfd); 224 | do_service(connfd); 225 | //printf("child exit\n"); 226 | exit(EXIT_SUCCESS); 227 | } 228 | else 229 | { 230 | //printf("parent exit\n"); 231 | close(connfd); 232 | } 233 | 234 | 235 | } 236 | // 7. 断开连接 237 | close(listenfd); 238 | 239 | 240 | 241 | return 0; 242 | } -------------------------------------------------------------------------------- /echosrv5.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-6. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | 15 | using namespace std; 16 | 17 | struct packet 18 | { 19 | int len; 20 | char buf[1024]; 21 | }; 22 | 23 | #define ERR_EXIT(m) \ 24 | do \ 25 | { \ 26 | perror(m); \ 27 | exit(EXIT_FAILURE); \ 28 | } while(0); 29 | 30 | ssize_t readn(int fd, void *buf, size_t count) 31 | { 32 | size_t nleft = count; // 剩余字节数 33 | ssize_t nread; 34 | char *bufp = (char*) buf; 35 | 36 | while (nleft > 0) 37 | { 38 | nread = read(fd, bufp, nleft); 39 | if (nread < 0) 40 | { 41 | if (errno == EINTR) 42 | { 43 | continue; 44 | } 45 | return -1; 46 | } else if (nread == 0) 47 | { 48 | return count - nleft; 49 | } 50 | 51 | bufp += nread; 52 | nleft -= nread; 53 | } 54 | return count; 55 | } 56 | 57 | ssize_t writen(int fd, const void *buf, size_t count) 58 | { 59 | size_t nleft = count; 60 | ssize_t nwritten; 61 | char* bufp = (char*)buf; 62 | 63 | while (nleft > 0) 64 | { 65 | if ((nwritten = write(fd, bufp, nleft)) < 0) 66 | { 67 | if (errno == EINTR) 68 | { 69 | continue; 70 | } 71 | return -1; 72 | } 73 | else if (nwritten == 0) 74 | { 75 | continue; 76 | } 77 | bufp += nwritten; 78 | nleft -= nwritten; 79 | } 80 | return count; 81 | } 82 | 83 | ssize_t recv_peek(int sockfd, void *buf, size_t len) 84 | { 85 | while (1) 86 | { 87 | int ret = recv(sockfd, buf, len, MSG_PEEK); // 查看传入消息 88 | if (ret == -1 && errno == EINTR) 89 | { 90 | continue; 91 | } 92 | return ret; 93 | } 94 | } 95 | 96 | ssize_t readline(int sockfd, void *buf, size_t maxline) 97 | { 98 | int ret; 99 | int nread; 100 | char *bufp = (char*)buf; // 当前指针位置 101 | int nleft = maxline; 102 | while (1) 103 | { 104 | ret = recv_peek(sockfd, buf, nleft); 105 | if (ret < 0) 106 | { 107 | return ret; 108 | } 109 | else if (ret == 0) 110 | { 111 | return ret; 112 | } 113 | nread = ret; 114 | int i; 115 | for (i = 0; i < nread; i++) 116 | { 117 | if (bufp[i] == '\n') 118 | { 119 | ret = readn(sockfd, bufp, i+1); 120 | if (ret != i+1) 121 | { 122 | exit(EXIT_FAILURE); 123 | } 124 | return ret; 125 | } 126 | } 127 | if (nread > nleft) 128 | { 129 | exit(EXIT_FAILURE); 130 | } 131 | nleft -= nread; 132 | ret = readn(sockfd, bufp, nread); 133 | if (ret != nread) 134 | { 135 | exit(EXIT_FAILURE); 136 | } 137 | bufp += nread; 138 | } 139 | return -1; 140 | } 141 | 142 | void echo_srv(int connfd) 143 | { 144 | char recvbuf[1024]; 145 | // struct packet recvbuf; 146 | int n; 147 | while (1) 148 | { 149 | memset(recvbuf, 0, sizeof recvbuf); 150 | int ret = readline(connfd, recvbuf, 1024); 151 | if (ret == -1) 152 | { 153 | ERR_EXIT("readline"); 154 | } 155 | if (ret == 0) 156 | { 157 | printf("client close\n"); 158 | break; 159 | } 160 | 161 | fputs(recvbuf, stdout); 162 | writen(connfd, recvbuf, strlen(recvbuf)); 163 | } 164 | 165 | } 166 | 167 | int main(int argc, char** argv) { 168 | // 1. 创建套接字 169 | int listenfd; 170 | if ((listenfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { 171 | ERR_EXIT("socket"); 172 | } 173 | 174 | // 2. 分配套接字地址 175 | struct sockaddr_in servaddr; 176 | memset(&servaddr, 0, sizeof servaddr); 177 | servaddr.sin_family = AF_INET; 178 | servaddr.sin_port = htons(6666); 179 | servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 180 | // servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); 181 | // inet_aton("127.0.0.1", &servaddr.sin_addr); 182 | 183 | int on = 1; 184 | // 确保time_wait状态下同一端口仍可使用 185 | if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on) < 0) { 186 | ERR_EXIT("setsockopt"); 187 | } 188 | 189 | // 3. 绑定套接字地址 190 | if (bind(listenfd, (struct sockaddr *) &servaddr, sizeof servaddr) < 0) { 191 | ERR_EXIT("bind"); 192 | } 193 | // 4. 等待连接请求状态 194 | if (listen(listenfd, SOMAXCONN) < 0) { 195 | ERR_EXIT("listen"); 196 | } 197 | // 5. 允许连接 198 | struct sockaddr_in peeraddr; 199 | socklen_t peerlen = sizeof peeraddr; 200 | 201 | 202 | // 6. 数据交换 203 | pid_t pid; 204 | while (1) { 205 | int connfd; 206 | if ((connfd = accept(listenfd, (struct sockaddr *) &peeraddr, &peerlen)) < 0) { 207 | ERR_EXIT("accept"); 208 | } 209 | 210 | printf("id = %s, ", inet_ntoa(peeraddr.sin_addr)); 211 | printf("port = %d\n", ntohs(peeraddr.sin_port)); 212 | 213 | pid = fork(); 214 | 215 | if (pid == -1) { 216 | ERR_EXIT("fork"); 217 | } 218 | if (pid == 0) // 子进程 219 | { 220 | close(listenfd); 221 | echo_srv(connfd); 222 | //printf("child exit\n"); 223 | exit(EXIT_SUCCESS); 224 | } else { 225 | //printf("parent exit\n"); 226 | close(connfd); 227 | } 228 | 229 | 230 | } 231 | // 7. 断开连接 232 | close(listenfd); 233 | 234 | 235 | return 0; 236 | } -------------------------------------------------------------------------------- /echosrv6.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-6. 3 | // 4 | 5 | // socket编程 8 select模型 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | 17 | using namespace std; 18 | 19 | struct packet 20 | { 21 | int len; 22 | char buf[1024]; 23 | }; 24 | 25 | #define ERR_EXIT(m) \ 26 | do \ 27 | { \ 28 | perror(m); \ 29 | exit(EXIT_FAILURE); \ 30 | } while(0); 31 | 32 | ssize_t readn(int fd, void *buf, size_t count) 33 | { 34 | size_t nleft = count; // 剩余字节数 35 | ssize_t nread; 36 | char *bufp = (char*) buf; 37 | 38 | while (nleft > 0) 39 | { 40 | nread = read(fd, bufp, nleft); 41 | if (nread < 0) 42 | { 43 | if (errno == EINTR) 44 | { 45 | continue; 46 | } 47 | return -1; 48 | } else if (nread == 0) 49 | { 50 | return count - nleft; 51 | } 52 | 53 | bufp += nread; 54 | nleft -= nread; 55 | } 56 | return count; 57 | } 58 | 59 | ssize_t writen(int fd, const void *buf, size_t count) 60 | { 61 | size_t nleft = count; 62 | ssize_t nwritten; 63 | char* bufp = (char*)buf; 64 | 65 | while (nleft > 0) 66 | { 67 | if ((nwritten = write(fd, bufp, nleft)) < 0) 68 | { 69 | if (errno == EINTR) 70 | { 71 | continue; 72 | } 73 | return -1; 74 | } 75 | else if (nwritten == 0) 76 | { 77 | continue; 78 | } 79 | bufp += nwritten; 80 | nleft -= nwritten; 81 | } 82 | return count; 83 | } 84 | 85 | ssize_t recv_peek(int sockfd, void *buf, size_t len) 86 | { 87 | while (1) 88 | { 89 | int ret = recv(sockfd, buf, len, MSG_PEEK); // 查看传入消息 90 | if (ret == -1 && errno == EINTR) 91 | { 92 | continue; 93 | } 94 | return ret; 95 | } 96 | } 97 | 98 | ssize_t readline(int sockfd, void *buf, size_t maxline) 99 | { 100 | int ret; 101 | int nread; 102 | char *bufp = (char*)buf; // 当前指针位置 103 | int nleft = maxline; 104 | while (1) 105 | { 106 | ret = recv_peek(sockfd, buf, nleft); 107 | if (ret < 0) 108 | { 109 | return ret; 110 | } 111 | else if (ret == 0) 112 | { 113 | return ret; 114 | } 115 | nread = ret; 116 | int i; 117 | for (i = 0; i < nread; i++) 118 | { 119 | if (bufp[i] == '\n') 120 | { 121 | ret = readn(sockfd, bufp, i+1); 122 | if (ret != i+1) 123 | { 124 | exit(EXIT_FAILURE); 125 | } 126 | return ret; 127 | } 128 | } 129 | if (nread > nleft) 130 | { 131 | exit(EXIT_FAILURE); 132 | } 133 | nleft -= nread; 134 | ret = readn(sockfd, bufp, nread); 135 | if (ret != nread) 136 | { 137 | exit(EXIT_FAILURE); 138 | } 139 | bufp += nread; 140 | } 141 | return -1; 142 | } 143 | 144 | void echo_srv(int connfd) 145 | { 146 | char recvbuf[1024]; 147 | // struct packet recvbuf; 148 | int n; 149 | while (1) 150 | { 151 | memset(recvbuf, 0, sizeof recvbuf); 152 | int ret = readline(connfd, recvbuf, 1024); 153 | if (ret == -1) 154 | { 155 | ERR_EXIT("readline"); 156 | } 157 | if (ret == 0) 158 | { 159 | printf("client close\n"); 160 | break; 161 | } 162 | 163 | fputs(recvbuf, stdout); 164 | writen(connfd, recvbuf, strlen(recvbuf)); 165 | } 166 | 167 | } 168 | 169 | int main(int argc, char** argv) { 170 | // 1. 创建套接字 171 | int listenfd; 172 | if ((listenfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { 173 | ERR_EXIT("socket"); 174 | } 175 | 176 | // 2. 分配套接字地址 177 | struct sockaddr_in servaddr; 178 | memset(&servaddr, 0, sizeof servaddr); 179 | servaddr.sin_family = AF_INET; 180 | servaddr.sin_port = htons(6666); 181 | servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 182 | // servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); 183 | // inet_aton("127.0.0.1", &servaddr.sin_addr); 184 | 185 | int on = 1; 186 | // 确保time_wait状态下同一端口仍可使用 187 | if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on) < 0) { 188 | ERR_EXIT("setsockopt"); 189 | } 190 | 191 | // 3. 绑定套接字地址 192 | if (bind(listenfd, (struct sockaddr *) &servaddr, sizeof servaddr) < 0) { 193 | ERR_EXIT("bind"); 194 | } 195 | // 4. 等待连接请求状态 196 | if (listen(listenfd, SOMAXCONN) < 0) { 197 | ERR_EXIT("listen"); 198 | } 199 | // 5. 允许连接 200 | struct sockaddr_in peeraddr; 201 | socklen_t peerlen = sizeof peeraddr; 202 | 203 | 204 | // 6. 数据交换 205 | pid_t pid; 206 | while (1) { 207 | int connfd; 208 | if ((connfd = accept(listenfd, (struct sockaddr *) &peeraddr, &peerlen)) < 0) { 209 | ERR_EXIT("accept"); 210 | } 211 | 212 | printf("id = %s, ", inet_ntoa(peeraddr.sin_addr)); 213 | printf("port = %d\n", ntohs(peeraddr.sin_port)); 214 | 215 | pid = fork(); 216 | 217 | if (pid == -1) { 218 | ERR_EXIT("fork"); 219 | } 220 | if (pid == 0) // 子进程 221 | { 222 | close(listenfd); 223 | echo_srv(connfd); 224 | //printf("child exit\n"); 225 | exit(EXIT_SUCCESS); 226 | } else { 227 | //printf("parent exit\n"); 228 | close(connfd); 229 | } 230 | 231 | 232 | } 233 | // 7. 断开连接 234 | close(listenfd); 235 | 236 | 237 | return 0; 238 | } -------------------------------------------------------------------------------- /echosrv7.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-7. 3 | // 4 | 5 | // socket编程 9 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | 17 | using namespace std; 18 | 19 | struct packet 20 | { 21 | int len; 22 | char buf[1024]; 23 | }; 24 | 25 | #define ERR_EXIT(m) \ 26 | do \ 27 | { \ 28 | perror(m); \ 29 | exit(EXIT_FAILURE); \ 30 | } while(0); 31 | 32 | ssize_t readn(int fd, void *buf, size_t count) 33 | { 34 | size_t nleft = count; // 剩余字节数 35 | ssize_t nread; 36 | char *bufp = (char*) buf; 37 | 38 | while (nleft > 0) 39 | { 40 | nread = read(fd, bufp, nleft); 41 | if (nread < 0) 42 | { 43 | if (errno == EINTR) 44 | { 45 | continue; 46 | } 47 | return -1; 48 | } else if (nread == 0) 49 | { 50 | return count - nleft; 51 | } 52 | 53 | bufp += nread; 54 | nleft -= nread; 55 | } 56 | return count; 57 | } 58 | 59 | ssize_t writen(int fd, const void *buf, size_t count) 60 | { 61 | size_t nleft = count; 62 | ssize_t nwritten; 63 | char* bufp = (char*)buf; 64 | 65 | while (nleft > 0) 66 | { 67 | if ((nwritten = write(fd, bufp, nleft)) < 0) 68 | { 69 | if (errno == EINTR) 70 | { 71 | continue; 72 | } 73 | return -1; 74 | } 75 | else if (nwritten == 0) 76 | { 77 | continue; 78 | } 79 | bufp += nwritten; 80 | nleft -= nwritten; 81 | } 82 | return count; 83 | } 84 | 85 | ssize_t recv_peek(int sockfd, void *buf, size_t len) 86 | { 87 | while (1) 88 | { 89 | int ret = recv(sockfd, buf, len, MSG_PEEK); // 查看传入消息 90 | if (ret == -1 && errno == EINTR) 91 | { 92 | continue; 93 | } 94 | return ret; 95 | } 96 | } 97 | 98 | ssize_t readline(int sockfd, void *buf, size_t maxline) 99 | { 100 | int ret; 101 | int nread; 102 | char *bufp = (char*)buf; // 当前指针位置 103 | int nleft = maxline; 104 | while (1) 105 | { 106 | ret = recv_peek(sockfd, buf, nleft); 107 | if (ret < 0) 108 | { 109 | return ret; 110 | } 111 | else if (ret == 0) 112 | { 113 | return ret; 114 | } 115 | nread = ret; 116 | int i; 117 | for (i = 0; i < nread; i++) 118 | { 119 | if (bufp[i] == '\n') 120 | { 121 | ret = readn(sockfd, bufp, i+1); 122 | if (ret != i+1) 123 | { 124 | exit(EXIT_FAILURE); 125 | } 126 | return ret; 127 | } 128 | } 129 | if (nread > nleft) 130 | { 131 | exit(EXIT_FAILURE); 132 | } 133 | nleft -= nread; 134 | ret = readn(sockfd, bufp, nread); 135 | if (ret != nread) 136 | { 137 | exit(EXIT_FAILURE); 138 | } 139 | bufp += nread; 140 | } 141 | return -1; 142 | } 143 | 144 | void echo_srv(int connfd) 145 | { 146 | char recvbuf[1024]; 147 | // struct packet recvbuf; 148 | int n; 149 | while (1) 150 | { 151 | memset(recvbuf, 0, sizeof recvbuf); 152 | int ret = readline(connfd, recvbuf, 1024); 153 | if (ret == -1) 154 | { 155 | ERR_EXIT("readline"); 156 | } 157 | if (ret == 0) 158 | { 159 | printf("client close\n"); 160 | break; 161 | } 162 | 163 | fputs(recvbuf, stdout); 164 | writen(connfd, recvbuf, strlen(recvbuf)); 165 | } 166 | 167 | } 168 | 169 | int main(int argc, char** argv) { 170 | // 1. 创建套接字 171 | int listenfd; 172 | if ((listenfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { 173 | ERR_EXIT("socket"); 174 | } 175 | 176 | // 2. 分配套接字地址 177 | struct sockaddr_in servaddr; 178 | memset(&servaddr, 0, sizeof servaddr); 179 | servaddr.sin_family = AF_INET; 180 | servaddr.sin_port = htons(6666); 181 | servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 182 | // servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); 183 | // inet_aton("127.0.0.1", &servaddr.sin_addr); 184 | 185 | int on = 1; 186 | // 确保time_wait状态下同一端口仍可使用 187 | if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on) < 0) { 188 | ERR_EXIT("setsockopt"); 189 | } 190 | 191 | // 3. 绑定套接字地址 192 | if (bind(listenfd, (struct sockaddr *) &servaddr, sizeof servaddr) < 0) { 193 | ERR_EXIT("bind"); 194 | } 195 | // 4. 等待连接请求状态 196 | if (listen(listenfd, SOMAXCONN) < 0) { 197 | ERR_EXIT("listen"); 198 | } 199 | // 5. 允许连接 200 | struct sockaddr_in peeraddr; 201 | socklen_t peerlen; 202 | 203 | 204 | // 6. 数据交换 205 | int nready; 206 | int maxfd = listenfd; 207 | fd_set rset; 208 | fd_set allset; 209 | FD_ZERO(&rset); 210 | FD_ZERO(&allset); 211 | FD_SET(listenfd, &allset); 212 | int connfd; 213 | int i; 214 | int client[FD_SETSIZE]; 215 | int ret; 216 | int Max = 0; 217 | memset(client, -1, sizeof(client)); 218 | while (1) 219 | { 220 | rset = allset; 221 | nready = select(maxfd + 1, &rset, NULL, NULL, NULL); 222 | if (nready == -1) 223 | { 224 | if (errno == EINTR) 225 | { 226 | continue; 227 | } 228 | ERR_EXIT("select"); 229 | } 230 | 231 | if (nready == 0) 232 | { 233 | continue; 234 | } 235 | 236 | if (FD_ISSET(listenfd, &rset)) 237 | { 238 | peerlen = sizeof(peeraddr); 239 | connfd = accept(listenfd, (struct sockaddr *)&peeraddr, &peerlen); 240 | if (connfd == -1) 241 | { 242 | ERR_EXIT("accept"); 243 | } 244 | for (i = 0; i < FD_SETSIZE; i++) 245 | { 246 | if (client[i] < 0) 247 | { 248 | client[i] = connfd; 249 | break; 250 | } 251 | } 252 | if (i == FD_SETSIZE) 253 | { 254 | fprintf(stderr, "too many clients\n"); 255 | exit(EXIT_FAILURE); 256 | } 257 | printf("id = %s, ", inet_ntoa(peeraddr.sin_addr)); 258 | printf("port = %d\n", ntohs(peeraddr.sin_port)); 259 | FD_SET(connfd, &allset); 260 | Max++; 261 | maxfd = max(maxfd, connfd); 262 | if (--nready <= 0) 263 | { 264 | continue; 265 | } 266 | } 267 | for (i = 0; i < Max; ++i) 268 | { 269 | connfd = client[i]; 270 | if (connfd == -1) 271 | { 272 | continue; 273 | } 274 | if (FD_ISSET(connfd, &rset)) 275 | { 276 | char recvbuf[1024] = {0}; 277 | ret = readline(connfd, recvbuf, 1024); 278 | if (ret == -1) 279 | { 280 | ERR_EXIT("readline"); 281 | } 282 | if (ret == 0) 283 | { 284 | printf("client close\n"); 285 | client[i] = -1; 286 | FD_CLR(connfd, &allset); 287 | Max--; 288 | } 289 | fputs(recvbuf, stdout); 290 | //sleep(4); 291 | writen(connfd, recvbuf, strlen(recvbuf)); 292 | if (--nready <= 0) 293 | { 294 | break; 295 | } 296 | }; 297 | } 298 | } 299 | // pid_t pid; 300 | // while (1) { 301 | // int connfd; 302 | // if ((connfd = accept(listenfd, (struct sockaddr *) &peeraddr, &peerlen)) < 0) { 303 | // ERR_EXIT("accept"); 304 | // } 305 | // 306 | // printf("id = %s, ", inet_ntoa(peeraddr.sin_addr)); 307 | // printf("port = %d\n", ntohs(peeraddr.sin_port)); 308 | // 309 | // pid = fork(); 310 | // 311 | // if (pid == -1) { 312 | // ERR_EXIT("fork"); 313 | // } 314 | // if (pid == 0) // 子进程 315 | // { 316 | // close(listenfd); 317 | // echo_srv(connfd); 318 | // //printf("child exit\n"); 319 | // exit(EXIT_SUCCESS); 320 | // } else { 321 | // //printf("parent exit\n"); 322 | // close(connfd); 323 | // } 324 | // 325 | // 326 | // } 327 | // 7. 断开连接 328 | close(listenfd); 329 | 330 | 331 | return 0; 332 | } -------------------------------------------------------------------------------- /epollsrv.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-7. 3 | // 4 | 5 | // socket编程 13 epoll 模型 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | 23 | using namespace std; 24 | 25 | typedef vector EventList; 26 | 27 | struct packet 28 | { 29 | int len; 30 | char buf[1024]; 31 | }; 32 | 33 | #define ERR_EXIT(m) \ 34 | do \ 35 | { \ 36 | perror(m); \ 37 | exit(EXIT_FAILURE); \ 38 | } while(0); 39 | 40 | ssize_t readn(int fd, void *buf, size_t count) 41 | { 42 | size_t nleft = count; // 剩余字节数 43 | ssize_t nread; 44 | char *bufp = (char*) buf; 45 | 46 | while (nleft > 0) 47 | { 48 | nread = read(fd, bufp, nleft); 49 | if (nread < 0) 50 | { 51 | if (errno == EINTR) 52 | { 53 | continue; 54 | } 55 | return -1; 56 | } else if (nread == 0) 57 | { 58 | return count - nleft; 59 | } 60 | 61 | bufp += nread; 62 | nleft -= nread; 63 | } 64 | return count; 65 | } 66 | 67 | ssize_t writen(int fd, const void *buf, size_t count) 68 | { 69 | size_t nleft = count; 70 | ssize_t nwritten; 71 | char* bufp = (char*)buf; 72 | 73 | while (nleft > 0) 74 | { 75 | if ((nwritten = write(fd, bufp, nleft)) < 0) 76 | { 77 | if (errno == EINTR) 78 | { 79 | continue; 80 | } 81 | return -1; 82 | } 83 | else if (nwritten == 0) 84 | { 85 | continue; 86 | } 87 | bufp += nwritten; 88 | nleft -= nwritten; 89 | } 90 | return count; 91 | } 92 | 93 | ssize_t recv_peek(int sockfd, void *buf, size_t len) 94 | { 95 | while (1) 96 | { 97 | int ret = recv(sockfd, buf, len, MSG_PEEK); // 查看传入消息 98 | if (ret == -1 && errno == EINTR) 99 | { 100 | continue; 101 | } 102 | return ret; 103 | } 104 | } 105 | 106 | ssize_t readline(int sockfd, void *buf, size_t maxline) 107 | { 108 | int ret; 109 | int nread; 110 | char *bufp = (char*)buf; // 当前指针位置 111 | int nleft = maxline; 112 | while (1) 113 | { 114 | ret = recv_peek(sockfd, buf, nleft); 115 | if (ret < 0) 116 | { 117 | return ret; 118 | } 119 | else if (ret == 0) 120 | { 121 | return ret; 122 | } 123 | nread = ret; 124 | int i; 125 | for (i = 0; i < nread; i++) 126 | { 127 | if (bufp[i] == '\n') 128 | { 129 | ret = readn(sockfd, bufp, i+1); 130 | if (ret != i+1) 131 | { 132 | exit(EXIT_FAILURE); 133 | } 134 | return ret; 135 | } 136 | } 137 | if (nread > nleft) 138 | { 139 | exit(EXIT_FAILURE); 140 | } 141 | nleft -= nread; 142 | ret = readn(sockfd, bufp, nread); 143 | if (ret != nread) 144 | { 145 | exit(EXIT_FAILURE); 146 | } 147 | bufp += nread; 148 | } 149 | return -1; 150 | } 151 | 152 | void echo_srv(int connfd) 153 | { 154 | char recvbuf[1024]; 155 | // struct packet recvbuf; 156 | int n; 157 | while (1) 158 | { 159 | memset(recvbuf, 0, sizeof recvbuf); 160 | int ret = readline(connfd, recvbuf, 1024); 161 | if (ret == -1) 162 | { 163 | ERR_EXIT("readline"); 164 | } 165 | if (ret == 0) 166 | { 167 | printf("client close\n"); 168 | break; 169 | } 170 | 171 | fputs(recvbuf, stdout); 172 | writen(connfd, recvbuf, strlen(recvbuf)); 173 | } 174 | 175 | } 176 | 177 | void activate_nonblock(int fd) 178 | { 179 | int ret; 180 | int flags = fcntl(fd, F_GETFL); 181 | if(flags == -1) 182 | ERR_EXIT("fcntl"); 183 | flags |= O_NONBLOCK; 184 | ret = fcntl(fd, F_SETFL, flags); 185 | if(ret == -1) 186 | ERR_EXIT("fcntl"); 187 | } 188 | 189 | int main(int argc, char** argv) { 190 | // 1. 创建套接字 191 | int listenfd; 192 | if ((listenfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { 193 | ERR_EXIT("socket"); 194 | } 195 | 196 | // 2. 分配套接字地址 197 | struct sockaddr_in servaddr; 198 | memset(&servaddr, 0, sizeof servaddr); 199 | servaddr.sin_family = AF_INET; 200 | servaddr.sin_port = htons(6666); 201 | servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 202 | // servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); 203 | // inet_aton("127.0.0.1", &servaddr.sin_addr); 204 | 205 | int on = 1; 206 | // 确保time_wait状态下同一端口仍可使用 207 | if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on) < 0) { 208 | ERR_EXIT("setsockopt"); 209 | } 210 | 211 | // 3. 绑定套接字地址 212 | if (bind(listenfd, (struct sockaddr *) &servaddr, sizeof servaddr) < 0) { 213 | ERR_EXIT("bind"); 214 | } 215 | // 4. 等待连接请求状态 216 | if (listen(listenfd, SOMAXCONN) < 0) { 217 | ERR_EXIT("listen"); 218 | } 219 | // 5. 允许连接 220 | struct sockaddr_in peeraddr; 221 | socklen_t peerlen; 222 | 223 | 224 | // 6. 数据交换 225 | int nready; 226 | int connfd; 227 | int i; 228 | vector clients; 229 | int epollfd; 230 | epollfd = epoll_create1(EPOLL_CLOEXEC); // 创建一个多路复用的实例 231 | 232 | struct epoll_event event; 233 | event.data.fd = listenfd; 234 | event.events = EPOLLIN | EPOLLET; 235 | epoll_ctl(epollfd, EPOLL_CTL_ADD, listenfd, &event); 236 | 237 | EventList events(16); 238 | 239 | while (1) 240 | { 241 | // 等侍注册在epfd上的socket fd的事件的发生,如果发生则将发生的sokct fd和事件类型放入到events数组中 242 | nready = epoll_wait(epollfd, &*events.begin(), static_cast(events.size()), -1); // 用于轮询I/O事件的发生 243 | if (nready == -1) 244 | { 245 | if (errno == EINTR) 246 | { 247 | continue; 248 | } 249 | ERR_EXIT("epoll_wait"); 250 | } 251 | 252 | if (nready == 0) 253 | { 254 | continue; 255 | } 256 | 257 | if ((size_t)nready == events.size()) 258 | { 259 | events.resize(events.size()*2); 260 | } 261 | 262 | for (i = 0; i < nready; ++i) 263 | { 264 | if (events[i].data.fd == listenfd) 265 | { 266 | peerlen = sizeof(peeraddr); 267 | connfd = accept(listenfd, (struct sockaddr*)&peeraddr, &peerlen); 268 | if (connfd == -1) 269 | { 270 | ERR_EXIT("accept"); 271 | } 272 | printf("id = %s, ", inet_ntoa(peeraddr.sin_addr)); 273 | printf("port = %d\n", ntohs(peeraddr.sin_port)); 274 | clients.push_back(connfd); 275 | activate_nonblock(connfd); 276 | 277 | event.data.fd = connfd; 278 | event.events = EPOLLIN | EPOLLET; 279 | epoll_ctl(epollfd, EPOLL_CTL_ADD, connfd, &event); 280 | 281 | } else if (events[i].events & EPOLLIN) 282 | { 283 | connfd = events[i].data.fd; 284 | if (connfd < 0) 285 | { 286 | continue; 287 | } 288 | char recvbuf[1024]; 289 | int ret = readline(connfd, recvbuf, sizeof(recvbuf)); 290 | if (ret == -1) 291 | { 292 | ERR_EXIT("readline"); 293 | } 294 | if (ret == 0) 295 | { 296 | printf("client close\n"); 297 | close(connfd); 298 | 299 | event = events[i]; 300 | epoll_ctl(epollfd, EPOLL_CTL_DEL, connfd, &event); 301 | clients.erase( 302 | remove_if(clients.begin(), clients.end(), [connfd](int n){return n == connfd;}), 303 | clients.end()); 304 | } 305 | fputs(recvbuf, stdout); 306 | writen(connfd, recvbuf, strlen(recvbuf)); 307 | memset(recvbuf, 0, sizeof recvbuf); 308 | } 309 | } 310 | 311 | } 312 | // 7. 断开连接 313 | close(listenfd); 314 | return 0; 315 | } 316 | -------------------------------------------------------------------------------- /gethostbyname_test.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-6. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #define ERR_EXIT(m) \ 16 | do \ 17 | { \ 18 | perror(m); \ 19 | exit(EXIT_FAILURE); \ 20 | } while (0); 21 | 22 | int getlocalip(char *ip) 23 | { 24 | char host[100] = {0}; 25 | if (gethostname(host, sizeof host) < 0) 26 | { 27 | ERR_EXIT("gethostname"); 28 | } 29 | 30 | struct hostent *hp; 31 | if ((hp = gethostbyname(host)) == NULL) 32 | { 33 | ERR_EXIT("gethostbyname"); 34 | } 35 | strcpy(ip, inet_ntoa(*(struct in_addr*)hp->h_addr_list[0])); 36 | return 0; 37 | } 38 | 39 | int main(void) 40 | { 41 | // char host[100] = {0}; 42 | // if (gethostname(host, sizeof host) < 0) 43 | // { 44 | // ERR_EXIT("gethostname"); 45 | // } 46 | // 47 | // struct hostent *hp; 48 | // if ((hp = gethostbyname(host)) == NULL) 49 | // { 50 | // ERR_EXIT("gethostbyname"); 51 | // } 52 | // int i = 0; 53 | // while (hp->h_addr_list[i] != NULL) 54 | // { 55 | // printf("%s\n", inet_ntoa(*(struct in_addr*)hp->h_addr_list[i])); 56 | // ++i; 57 | // } 58 | 59 | char ip[16] = {0}; 60 | getlocalip(ip); 61 | printf("localip = %s\n", ip); 62 | 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | // 该文件为原始文件 具体实现在各个文件中 9 | 10 | #define ERR_EXIF(m) \ 11 | do \ 12 | { \ 13 | perror(m); \ 14 | exit(EXIT_FAILURE); \ 15 | } while(0); 16 | 17 | char* trim(char* cmdline) 18 | { 19 | char* s = cmdline; 20 | while (*s == ' ') 21 | { 22 | s++; 23 | } 24 | 25 | char* e = s; 26 | int len = 0; 27 | while ((strcmp(e, "") != 0) && *e != ' ') 28 | { 29 | len++; 30 | e++; 31 | } 32 | char* res = new char[len]; 33 | memcpy(res, s, len); 34 | return res; 35 | } 36 | 37 | vector getcmd(char* cmdline) { 38 | vector res; 39 | char *s = trim(cmdline); 40 | if (strcmp(s, "") == 0) { 41 | return res; 42 | } 43 | int len = 0; 44 | char *temp; 45 | char *tmp ; 46 | int count = 3; 47 | while (count--) { 48 | s = trim(cmdline); 49 | if (strcmp(s, "") == 0) { 50 | return res; 51 | } 52 | len = 0; 53 | temp = s; 54 | tmp = new char[100]; 55 | while ((strcmp(temp, "") != 0) && *temp != ' ') { 56 | len++; 57 | temp++; 58 | } 59 | memcpy(tmp, s, len); 60 | res.push_back(tmp); 61 | cmdline = cmdline + len; 62 | while ((strcmp(cmdline, "") != 0) && *cmdline == ' ') 63 | { 64 | cmdline++; 65 | } 66 | } 67 | return res; 68 | } 69 | 70 | int main() { 71 | char* p; 72 | char* cmdline = new char[100]; 73 | while (cin.getline(cmdline, 100)) 74 | { 75 | vector res = getcmd(cmdline); 76 | if (res.size() == 0 || res.size() == 2) 77 | { 78 | cout << "err" << endl; 79 | } 80 | else if (strcmp(res[0], "exit") == 0) 81 | { 82 | cout << "exit" << endl; 83 | } 84 | else if (strcmp(res[0], "send") == 0 && res.size() == 3) 85 | { 86 | cout << "send" << endl; 87 | cout << "username:\t" << res[1] << endl; 88 | cout << "msg:\t" << res[2] << endl; 89 | } 90 | else 91 | { 92 | cout << "err" << endl; 93 | } 94 | } 95 | 96 | return 0; 97 | } -------------------------------------------------------------------------------- /mmap_recv.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-12. 3 | // 4 | 5 | // p28 共享内存介绍(一) 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #define ERR_EXIT(m) \ 20 | do \ 21 | { \ 22 | perror(m); \ 23 | exit(EXIT_FAILURE); \ 24 | } while (0); 25 | 26 | typedef struct stu 27 | { 28 | char name[4]; 29 | int age; 30 | } STU; 31 | 32 | int main(int argc, char** argv) 33 | { 34 | int fd; 35 | fd = open(argv[1], O_RDWR); 36 | if (fd == -1) 37 | { 38 | ERR_EXIT("open"); 39 | } 40 | 41 | 42 | STU *p; 43 | p = (STU*)mmap(NULL, sizeof(STU) * 6, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);; 44 | if (p == NULL) 45 | { 46 | ERR_EXIT("mmap"); 47 | } 48 | char ch = 'a'; 49 | int i; 50 | for (int i = 0; i < 6; ++i) 51 | { 52 | printf("student's name = %s, age = %d\n", (p+i)->name, (p+i)->age); 53 | // memcpy((p+i)->name, &ch, 1); 54 | // (p+i)->age = 20 + i; 55 | // ++ch; 56 | } 57 | 58 | munmap(p, sizeof(STU)*6); 59 | printf("exit...\n"); 60 | 61 | return 0; 62 | } -------------------------------------------------------------------------------- /mmap_send.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-12. 3 | // 4 | 5 | // p28 共享内存介绍(一) 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #define ERR_EXIT(m) \ 20 | do \ 21 | { \ 22 | perror(m); \ 23 | exit(EXIT_FAILURE); \ 24 | } while (0); 25 | 26 | typedef struct stu 27 | { 28 | char name[4]; 29 | int age; 30 | } STU; 31 | 32 | int main(int argc, char** argv) 33 | { 34 | if (argc != 2) 35 | { 36 | fprintf(stderr, "Usage: %s \n", argv[1]); 37 | exit(EXIT_FAILURE); 38 | } 39 | 40 | int fd; 41 | // O_CREAT │若文件存在,此标志无用;若不存在,建新文件 42 | // O_RDWR │即读也写 43 | // O_TRUNC │若文件存在,则长度被截为0,属性不变 44 | fd = open(argv[1], O_CREAT | O_RDWR | O_TRUNC, 0666); 45 | if (fd == -1) 46 | { 47 | ERR_EXIT("open"); 48 | } 49 | 50 | // SEEK_SET 参数 offset 即为新的读写位置 51 | // solve the bus error problem: 52 | // we should allocate space for the file first. 53 | lseek(fd, sizeof(STU) * 6 - 1, SEEK_SET); 54 | write(fd, "", 1); 55 | 56 | STU *p; 57 | p = (STU*)mmap(NULL, sizeof(STU) * 6, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);; 58 | if (p == NULL) 59 | { 60 | ERR_EXIT("mmap"); 61 | } 62 | char ch = 'a'; 63 | for (int i = 0; i < 6; ++i) 64 | { 65 | memcpy((p+i)->name, &ch, 1); 66 | (p+i)->age = 10 + i; 67 | 68 | ++ch; 69 | } 70 | 71 | printf("initialize over\n"); 72 | munmap(p, sizeof(STU)*6); 73 | printf("exit...\n"); 74 | 75 | return 0; 76 | } -------------------------------------------------------------------------------- /msg_recv.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-12. 3 | // 4 | 5 | // p25 system v消息队列(二) 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #define ERR_EXIT(m) \ 17 | do \ 18 | { \ 19 | perror(m); \ 20 | exit(EXIT_FAILURE); \ 21 | } while (0); 22 | 23 | int main(int argc, char** argv) 24 | { 25 | int flag = 0; 26 | int type = 0; 27 | int opt; 28 | 29 | while (1) 30 | { 31 | opt = getopt(argc, argv, "nt:"); 32 | if (opt == '?') 33 | { 34 | exit(EXIT_FAILURE); 35 | } 36 | if (opt == -1) 37 | { 38 | break; 39 | } 40 | 41 | switch (opt) 42 | { 43 | case 'n': 44 | flag |= IPC_NOWAIT; 45 | break; 46 | case 't': 47 | type = atoi(optarg); 48 | break; 49 | } 50 | } 51 | 52 | 53 | int msgid; 54 | msgid = msgget(1234, 0); 55 | if (msgid == -1) 56 | { 57 | ERR_EXIT("msgget"); 58 | } 59 | 60 | struct msgbuf *ptr; 61 | ptr = (struct msgbuf*) malloc(sizeof(long) + 8192); 62 | ptr->mtype = type; 63 | //msgrcv( msqid, &buf1, recvlength ,3,0 ) ; 64 | int n; 65 | if ((n = msgrcv(msgid, ptr, 8192, type, flag)) < 0) 66 | { 67 | ERR_EXIT("msgsnd"); 68 | } 69 | printf("type=%d, bytes=%d\n", ptr->mtype, (int)n) ; 70 | return 0; 71 | } 72 | -------------------------------------------------------------------------------- /msg_send.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-12. 3 | // 4 | 5 | // p25 system v消息队列(二) 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #define ERR_EXIT(m) \ 17 | do \ 18 | { \ 19 | perror(m); \ 20 | exit(EXIT_FAILURE); \ 21 | } while (0); 22 | 23 | 24 | int main(int argc, char** argv) 25 | { 26 | if (argc != 3) 27 | { 28 | fprintf(stderr, "Usage: %s \n", argv[1]); 29 | exit(EXIT_FAILURE); 30 | } 31 | 32 | int len = atoi(argv[1]); 33 | int type = atoi(argv[2]); 34 | int msgid; 35 | msgid = msgget(1234, 0); 36 | if (msgid == -1) 37 | { 38 | ERR_EXIT("msgget"); 39 | } 40 | 41 | struct msgbuf *ptr; 42 | ptr = (struct msgbuf*) malloc(sizeof(long) + len); 43 | ptr->mtype = type; 44 | if (msgsnd(msgid, ptr, len, 0) < 0) 45 | { 46 | ERR_EXIT("msgsnd"); 47 | } 48 | 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /msgcli.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-12. 3 | // 4 | 5 | // p25 system v消息队列(三) 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #define ERR_EXIT(m) \ 18 | do \ 19 | { \ 20 | perror(m); \ 21 | exit(EXIT_FAILURE); \ 22 | } while (0); 23 | 24 | #define MSGMAX 8192 25 | 26 | int echocli(int msgid) 27 | { 28 | struct msgbuf msg; 29 | memset(&msg, 0, sizeof(msgbuf)); 30 | int pid = getpid(); 31 | msg.mtype = 1; 32 | *((int*)msg.mtext) = pid; 33 | int n; 34 | while (fgets(msg.mtext + 4, MSGMAX, stdin) != NULL) 35 | { 36 | if (msgsnd(msgid, &msg, sizeof(long) + strlen(msg.mtext), 0) < 0) 37 | { 38 | ERR_EXIT("msgsnd"); 39 | } 40 | 41 | memset(msg.mtext+4, 0, sizeof(msg.mtext + 4)); 42 | 43 | if ((n = msgrcv(msgid, &msg, MSGMAX, pid, 0)) < 0) 44 | { 45 | ERR_EXIT("msgsnd"); 46 | } 47 | fputs(msg.mtext + 4, stdout); 48 | memset(msg.mtext + 4, 0, sizeof(msg.mtext + 4)); 49 | } 50 | 51 | 52 | } 53 | 54 | int main(int argc, char** argv) 55 | { 56 | int msgid; 57 | msgid = msgget(1234, 0); 58 | if (msgid == -1) 59 | { 60 | ERR_EXIT("msgget"); 61 | } 62 | 63 | echocli(msgid); 64 | 65 | 66 | 67 | return 0; 68 | } 69 | -------------------------------------------------------------------------------- /msgctl01.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-12. 3 | // 4 | 5 | // p25 system v消息队列(一) 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #define ERR_EXIT(m) \ 17 | do \ 18 | { \ 19 | perror(m); \ 20 | exit(EXIT_FAILURE); \ 21 | } while (0); 22 | 23 | int main(void) 24 | { 25 | int msgid; 26 | msgid = msgget(1234, 0); 27 | if (msgid == -1) 28 | { 29 | ERR_EXIT("msgget"); 30 | } 31 | 32 | printf("msgget succ\n"); 33 | printf("msgid = %d\n", msgid); 34 | 35 | struct msqid_ds buf; 36 | msgctl(msgid, IPC_STAT, &buf); 37 | printf("mode = %o\n", buf.msg_perm.mode); 38 | printf("bytes = %ld\n", buf.__msg_cbytes); 39 | printf("number=%d\n", (int)buf.msg_qnum); 40 | printf("msgmnb=%d\n", (int)buf.msg_qbytes); 41 | 42 | return 0; 43 | } -------------------------------------------------------------------------------- /msgctl02.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-12. 3 | // 4 | 5 | // p25 system v消息队列(一) 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #define ERR_EXIT(m) \ 17 | do \ 18 | { \ 19 | perror(m); \ 20 | exit(EXIT_FAILURE); \ 21 | } while (0); 22 | 23 | int main(int argc, char** argv) 24 | { 25 | int msgid; 26 | msgid = msgget(1234, 0); 27 | if (msgid == -1) 28 | { 29 | ERR_EXIT("msgget"); 30 | } 31 | 32 | printf("msgget succ\n"); 33 | printf("msgid = %d\n", msgid); 34 | 35 | struct msqid_ds buf; 36 | msgctl(msgid, IPC_STAT, &buf); 37 | sscanf("600", "%o", (unsigned int*)&buf.msg_perm.mode); 38 | msgctl(msgid, IPC_SET, &buf); 39 | 40 | return 0; 41 | } -------------------------------------------------------------------------------- /msgget.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-12. 3 | // 4 | 5 | // p25 system v消息队列(一) 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #define ERR_EXIT(m) \ 17 | do \ 18 | { \ 19 | perror(m); \ 20 | exit(EXIT_FAILURE); \ 21 | } while (0); 22 | 23 | int main(void) 24 | { 25 | int msgid; 26 | // 当只有IPC_EXCL选项打开时,不管有没有该快共享内存,shmget()都返回-1 27 | 28 | // 当只有IPC_CREAT选项打开时,不管是否已存在该块共享内存,则都返回该共享内存的ID,若不存在则创建共享内存 29 | msgid = msgget(1234, 0666 | IPC_CREAT); 30 | // 当IPC_CREAT | IPC_EXCL时, 如果没有该块共享内存,则创建,并返回共享内存ID。若已有该块共享内存,则返回-1; 31 | 32 | //msgid = msgget(1234, 0666 | IPC_CREAT | IPC_EXCL); 33 | //msgid = msgget(IPC_PRIVATE, 0666 | IPC_CREAT | IPC_EXCL); 34 | /*msgid = msgget(IPC_PRIVATE, 0666); 35 | msgid = msgget(1234, 0666 | IPC_CREAT);*/ 36 | //msgid = msgget(1234, 0); // flags = 0 表示按原来权限打开 37 | 38 | if (msgid == -1) 39 | { 40 | ERR_EXIT("msgget"); 41 | } 42 | 43 | printf("msgget successful\n"); 44 | printf("msgid = %d\n", msgid); 45 | 46 | return 0; 47 | } -------------------------------------------------------------------------------- /msgsrv.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-12. 3 | // 4 | 5 | // p25 system v消息队列(三) 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #define ERR_EXIT(m) \ 18 | do \ 19 | { \ 20 | perror(m); \ 21 | exit(EXIT_FAILURE); \ 22 | } while (0); 23 | 24 | 25 | #define MSGMAX 8192 26 | 27 | void echo_srv(int msgid) 28 | { 29 | struct msgbuf msg; 30 | int n; 31 | int type; 32 | memset(&msg, 0, sizeof(msgbuf)); 33 | while (1) 34 | { 35 | if ((n = msgrcv(msgid, &msg, MSGMAX, 1, 0)) < 0) 36 | { 37 | ERR_EXIT("msgsnd"); 38 | } 39 | 40 | type = *((int*)msg.mtext); 41 | msg.mtype = type; 42 | 43 | fputs(msg.mtext+4, stdout); 44 | 45 | if (msgsnd(msgid, &msg, n, 0) < 0) 46 | { 47 | ERR_EXIT("msgsnd"); 48 | } 49 | //memset(&msg, 0, sizeof(msgbuf)); 50 | } 51 | 52 | } 53 | 54 | int main(int argc, char** argv) 55 | { 56 | int msgid; 57 | msgid = msgget(1234, 0); 58 | if (msgid == -1) 59 | { 60 | ERR_EXIT("msgget"); 61 | } 62 | 63 | echo_srv(msgid); 64 | 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /p2pcli.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-7-17. 3 | // 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | 15 | using namespace std; 16 | 17 | #define ERR_EXIT(m) \ 18 | do \ 19 | { \ 20 | perror(m); \ 21 | exit(EXIT_FAILURE); \ 22 | } while(0); 23 | 24 | void handler(int sig) 25 | { 26 | printf("recv a sig = %d\n", sig); 27 | exit(EXIT_SUCCESS); 28 | } 29 | 30 | int main(int argc, char** argv) { 31 | // 1. 创建套接字 32 | int sockfd; 33 | if ((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { 34 | ERR_EXIT("socket"); 35 | } 36 | 37 | // 2. 分配套接字地址 38 | struct sockaddr_in servaddr; 39 | memset(&servaddr, 0, sizeof servaddr); 40 | servaddr.sin_family = AF_INET; 41 | servaddr.sin_port = htons(6666); 42 | // servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 43 | servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); 44 | // inet_aton("127.0.0.1", &servaddr.sin_addr); 45 | 46 | // 3. 请求链接 47 | if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof servaddr) < 0) { 48 | ERR_EXIT("connect"); 49 | } 50 | 51 | // 4. 数据交换 52 | char recvbuf[1024]; 53 | char sendbuf[1024]; 54 | pid_t pid; 55 | pid = fork(); 56 | if (pid == -1) 57 | { 58 | ERR_EXIT("fork"); 59 | } 60 | if (pid == 0) 61 | { 62 | 63 | while (1) 64 | { 65 | int ret = read(sockfd, recvbuf, sizeof recvbuf); // 服务器读取 66 | if (ret == 0) 67 | { 68 | printf("server close\n"); 69 | break; 70 | } else if (ret == -1) 71 | { 72 | ERR_EXIT("read"); 73 | } 74 | fputs(recvbuf, stdout); // 服务器返回数据输出 75 | } 76 | printf("child exit\n"); 77 | kill(getppid(), SIGUSR1); 78 | //exit(EXIT_SUCCESS); 79 | close(sockfd); 80 | } else{ 81 | signal(SIGUSR1, handler); 82 | while (fgets(sendbuf, sizeof sendbuf, stdin) != NULL) // 键盘输入获取 83 | { 84 | write(sockfd, sendbuf, sizeof sendbuf); // 写入服务器 85 | // 清空 86 | memset(sendbuf, 0, sizeof sendbuf); 87 | } 88 | printf("parent exit\n"); 89 | // exit(EXIT_SUCCESS); 90 | close(sockfd); 91 | 92 | } 93 | 94 | // 5. 断开连接 95 | close(sockfd); 96 | 97 | 98 | 99 | return 0; 100 | } 101 | -------------------------------------------------------------------------------- /p2pserv.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-7-17. 3 | // 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | 15 | using namespace std; 16 | 17 | #define ERR_EXIT(m) \ 18 | do \ 19 | { \ 20 | perror(m); \ 21 | exit(EXIT_FAILURE); \ 22 | } while(0); 23 | 24 | void do_service(int connfd) 25 | { 26 | char recvbuf[1024]; 27 | while (1) 28 | { 29 | memset(recvbuf, 0, sizeof recvbuf); 30 | int ret = read(connfd, recvbuf, sizeof recvbuf); 31 | if (ret == 0) 32 | { 33 | printf("client close\n"); 34 | break; 35 | } else if (ret == -1) 36 | { 37 | ERR_EXIT("read"); 38 | } 39 | fputs(recvbuf, stdout); 40 | write(connfd, recvbuf, ret); 41 | } 42 | 43 | } 44 | 45 | void handler(int sig) 46 | { 47 | printf("recv a sig = %d\n", sig); 48 | exit(EXIT_SUCCESS); 49 | } 50 | 51 | int main(int argc, char** argv) { 52 | // 1. 创建套接字 53 | int listenfd; 54 | if ((listenfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { 55 | ERR_EXIT("socket"); 56 | } 57 | 58 | // 2. 分配套接字地址 59 | struct sockaddr_in servaddr; 60 | memset(&servaddr, 0, sizeof servaddr); 61 | servaddr.sin_family = AF_INET; 62 | servaddr.sin_port = htons(6666); 63 | servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 64 | // servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); 65 | // inet_aton("127.0.0.1", &servaddr.sin_addr); 66 | 67 | int on = 1; 68 | // 确保time_wait状态下同一端口仍可使用 69 | if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on) < 0) 70 | { 71 | ERR_EXIT("setsockopt"); 72 | } 73 | 74 | // 3. 绑定套接字地址 75 | if (bind(listenfd, (struct sockaddr*) &servaddr, sizeof servaddr) < 0) { 76 | ERR_EXIT("bind"); 77 | } 78 | // 4. 等待连接请求状态 79 | if (listen(listenfd, SOMAXCONN) < 0) { 80 | ERR_EXIT("listen"); 81 | } 82 | // 5. 允许连接 83 | struct sockaddr_in peeraddr; 84 | socklen_t peerlen = sizeof peeraddr; 85 | int connfd; 86 | if ((connfd = accept(listenfd, (struct sockaddr *) &peeraddr, &peerlen)) < 0) { 87 | ERR_EXIT("accept"); 88 | } 89 | 90 | // 6. 数据交换 91 | pid_t pid; 92 | pid = fork(); 93 | 94 | if (pid == -1) 95 | { 96 | ERR_EXIT("fork"); 97 | } 98 | if (pid == 0) // 子进程 99 | { 100 | signal(SIGUSR1, handler); 101 | char sendbuf[1024]; 102 | while (fgets(sendbuf, sizeof sendbuf, stdin) != NULL) 103 | { 104 | write(connfd, sendbuf, sizeof sendbuf); 105 | memset(sendbuf, 0, sizeof(sendbuf)); 106 | } 107 | printf("child exit\n"); 108 | exit(EXIT_SUCCESS); 109 | } 110 | else 111 | { 112 | char recvbuf[1024]; 113 | while (1) 114 | { 115 | memset(recvbuf, 0, sizeof recvbuf); 116 | int ret = read(connfd, recvbuf, sizeof recvbuf); 117 | if (ret == -1) 118 | { 119 | ERR_EXIT("read"); 120 | } 121 | else if (ret == 0) 122 | { 123 | printf("peer close\n"); 124 | break; 125 | } 126 | fputs(recvbuf, stdout); 127 | } 128 | printf("parent exit\n"); 129 | kill(pid, SIGUSR1); 130 | exit(EXIT_SUCCESS); 131 | } 132 | 133 | // 7. 断开连接 134 | close(connfd); 135 | close(listenfd); 136 | 137 | 138 | 139 | return 0; 140 | } 141 | -------------------------------------------------------------------------------- /pctest.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-15. 3 | // 4 | 5 | // p39 posix信号量与互斥锁 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include /* For O_* constants */ 12 | #include /* For mode constants */ 13 | #include 14 | #include 15 | 16 | using namespace std; 17 | 18 | #define ERR_EXIT(m) \ 19 | do \ 20 | { \ 21 | perror(m); \ 22 | exit(EXIT_FAILURE); \ 23 | } while(0); 24 | 25 | #define CONSUMERS_COUNT 1 26 | #define PRODUCERS_COUNT 5 27 | #define BUFFSIZE 10 28 | 29 | int g_buffer[BUFFSIZE]; 30 | 31 | unsigned short in = 0; 32 | unsigned short out = 0; 33 | unsigned short produce_id = 0; 34 | unsigned short consume_id = 0; 35 | 36 | sem_t g_sem_full; 37 | sem_t g_sem_empth; 38 | pthread_mutex_t g_mutex; 39 | 40 | pthread_t g_thread[CONSUMERS_COUNT + PRODUCERS_COUNT]; 41 | 42 | void *produce (void *arg) 43 | { 44 | int num = *((int *)arg); 45 | int i; 46 | while (1) 47 | { 48 | printf("%d produce is waiting\n", num); 49 | sem_wait(&g_sem_full); 50 | pthread_mutex_lock(&g_mutex); 51 | 52 | for (i = 0; i < BUFFSIZE; ++i) 53 | { 54 | printf("%02d ", i); 55 | if (g_buffer[i] == -1) 56 | { 57 | printf("%s ", "null"); 58 | } 59 | else 60 | { 61 | printf("%d ", g_buffer[i]); 62 | } 63 | if (i == in) 64 | { 65 | printf("\t<--produce"); 66 | } 67 | printf("\n"); 68 | } 69 | printf("%d produce begin produce product %d\n", num, produce_id); 70 | g_buffer[in] = produce_id; 71 | cout << g_buffer[in] << endl; 72 | in = (in + 1) % BUFFSIZE; 73 | printf("%d produce end produce product %d\n", num, produce_id++); 74 | pthread_mutex_unlock(&g_mutex); 75 | sem_post(&g_sem_empth); 76 | sleep(5); 77 | } 78 | return NULL; 79 | } 80 | 81 | void *consume (void *arg) 82 | { 83 | int num = *((int *)arg); 84 | int i; 85 | while (1) 86 | { 87 | printf("%d consume is waiting\n", num); 88 | sem_wait(&g_sem_empth); 89 | pthread_mutex_lock(&g_mutex); 90 | 91 | for (i = 0; i < BUFFSIZE; ++i) 92 | { 93 | printf("%02d ", i); 94 | if (g_buffer[i] == -1) 95 | { 96 | printf("%s", "null"); 97 | } 98 | else 99 | { 100 | printf("%d", g_buffer[i]); 101 | } 102 | if (i == out) 103 | { 104 | printf("\t<--consume"); 105 | } 106 | printf("\n"); 107 | } 108 | consume_id = g_buffer[out]; 109 | printf("%d consume begin consume product %d\n", num, consume_id); 110 | g_buffer[out] = -1; 111 | out = (out + 1) % BUFFSIZE; 112 | printf("%d consume end consume product %d\n", num, consume_id); 113 | pthread_mutex_unlock(&g_mutex); 114 | sem_post(&g_sem_full); 115 | sleep(1); 116 | } 117 | return NULL; 118 | } 119 | 120 | int main(int argc, char** argv) 121 | { 122 | for (int i = 0; i < BUFFSIZE; ++i) 123 | { 124 | g_buffer[i] = -1; 125 | } 126 | 127 | sem_init(&g_sem_full, NULL, BUFFSIZE); 128 | sem_init(&g_sem_empth, NULL, 0); 129 | 130 | pthread_mutex_init(&g_mutex, NULL); 131 | 132 | int i; 133 | for (i = 0; i < CONSUMERS_COUNT; ++i) 134 | { 135 | pthread_create(&g_thread[i], NULL, consume, &i); 136 | } 137 | 138 | for (i = 0; i < PRODUCERS_COUNT; ++i) 139 | { 140 | pthread_create(&g_thread[CONSUMERS_COUNT+i], NULL, produce, &i); 141 | } 142 | 143 | for (i = 0; i < CONSUMERS_COUNT + PRODUCERS_COUNT; ++i) 144 | { 145 | pthread_join(g_thread[i], NULL); 146 | } 147 | 148 | sem_destroy(&g_sem_full); 149 | sem_destroy(&g_sem_empth); 150 | pthread_mutex_destroy(&g_mutex); 151 | 152 | return 0; 153 | } -------------------------------------------------------------------------------- /pollsrv.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-7. 3 | // 4 | 5 | // socket编程 12 poll模型 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | 18 | using namespace std; 19 | 20 | struct packet 21 | { 22 | int len; 23 | char buf[1024]; 24 | }; 25 | 26 | #define ERR_EXIT(m) \ 27 | do \ 28 | { \ 29 | perror(m); \ 30 | exit(EXIT_FAILURE); \ 31 | } while(0); 32 | 33 | ssize_t readn(int fd, void *buf, size_t count) 34 | { 35 | size_t nleft = count; // 剩余字节数 36 | ssize_t nread; 37 | char *bufp = (char*) buf; 38 | 39 | while (nleft > 0) 40 | { 41 | nread = read(fd, bufp, nleft); 42 | if (nread < 0) 43 | { 44 | if (errno == EINTR) 45 | { 46 | continue; 47 | } 48 | return -1; 49 | } else if (nread == 0) 50 | { 51 | return count - nleft; 52 | } 53 | 54 | bufp += nread; 55 | nleft -= nread; 56 | } 57 | return count; 58 | } 59 | 60 | ssize_t writen(int fd, const void *buf, size_t count) 61 | { 62 | size_t nleft = count; 63 | ssize_t nwritten; 64 | char* bufp = (char*)buf; 65 | 66 | while (nleft > 0) 67 | { 68 | if ((nwritten = write(fd, bufp, nleft)) < 0) 69 | { 70 | if (errno == EINTR) 71 | { 72 | continue; 73 | } 74 | return -1; 75 | } 76 | else if (nwritten == 0) 77 | { 78 | continue; 79 | } 80 | bufp += nwritten; 81 | nleft -= nwritten; 82 | } 83 | return count; 84 | } 85 | 86 | ssize_t recv_peek(int sockfd, void *buf, size_t len) 87 | { 88 | while (1) 89 | { 90 | int ret = recv(sockfd, buf, len, MSG_PEEK); // 查看传入消息 91 | if (ret == -1 && errno == EINTR) 92 | { 93 | continue; 94 | } 95 | return ret; 96 | } 97 | } 98 | 99 | ssize_t readline(int sockfd, void *buf, size_t maxline) 100 | { 101 | int ret; 102 | int nread; 103 | char *bufp = (char*)buf; // 当前指针位置 104 | int nleft = maxline; 105 | while (1) 106 | { 107 | ret = recv_peek(sockfd, buf, nleft); 108 | if (ret < 0) 109 | { 110 | return ret; 111 | } 112 | else if (ret == 0) 113 | { 114 | return ret; 115 | } 116 | nread = ret; 117 | int i; 118 | for (i = 0; i < nread; i++) 119 | { 120 | if (bufp[i] == '\n') 121 | { 122 | ret = readn(sockfd, bufp, i+1); 123 | if (ret != i+1) 124 | { 125 | exit(EXIT_FAILURE); 126 | } 127 | return ret; 128 | } 129 | } 130 | if (nread > nleft) 131 | { 132 | exit(EXIT_FAILURE); 133 | } 134 | nleft -= nread; 135 | ret = readn(sockfd, bufp, nread); 136 | if (ret != nread) 137 | { 138 | exit(EXIT_FAILURE); 139 | } 140 | bufp += nread; 141 | } 142 | return -1; 143 | } 144 | 145 | void echo_srv(int connfd) 146 | { 147 | char recvbuf[1024]; 148 | // struct packet recvbuf; 149 | int n; 150 | while (1) 151 | { 152 | memset(recvbuf, 0, sizeof recvbuf); 153 | int ret = readline(connfd, recvbuf, 1024); 154 | if (ret == -1) 155 | { 156 | ERR_EXIT("readline"); 157 | } 158 | if (ret == 0) 159 | { 160 | printf("client close\n"); 161 | break; 162 | } 163 | 164 | fputs(recvbuf, stdout); 165 | writen(connfd, recvbuf, strlen(recvbuf)); 166 | } 167 | 168 | } 169 | 170 | int main(int argc, char** argv) { 171 | // 1. 创建套接字 172 | int listenfd; 173 | if ((listenfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { 174 | ERR_EXIT("socket"); 175 | } 176 | 177 | // 2. 分配套接字地址 178 | struct sockaddr_in servaddr; 179 | memset(&servaddr, 0, sizeof servaddr); 180 | servaddr.sin_family = AF_INET; 181 | servaddr.sin_port = htons(6666); 182 | servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 183 | // servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); 184 | // inet_aton("127.0.0.1", &servaddr.sin_addr); 185 | 186 | int on = 1; 187 | // 确保time_wait状态下同一端口仍可使用 188 | if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on) < 0) { 189 | ERR_EXIT("setsockopt"); 190 | } 191 | 192 | // 3. 绑定套接字地址 193 | if (bind(listenfd, (struct sockaddr *) &servaddr, sizeof servaddr) < 0) { 194 | ERR_EXIT("bind"); 195 | } 196 | // 4. 等待连接请求状态 197 | if (listen(listenfd, SOMAXCONN) < 0) { 198 | ERR_EXIT("listen"); 199 | } 200 | // 5. 允许连接 201 | struct sockaddr_in peeraddr; 202 | socklen_t peerlen; 203 | 204 | 205 | // 6. 数据交换 206 | int nready; 207 | int maxfd = listenfd; 208 | //fd_set rset; 209 | //fd_set allset; 210 | //FD_ZERO(&rset); 211 | //FD_ZERO(&allset); 212 | //FD_SET(listenfd, &allset); 213 | int connfd; 214 | int i; 215 | struct pollfd client[2048]; 216 | int ret; 217 | int Max = 0; 218 | // memset(client, -1, sizeof(client)); 219 | for (i = 0; i < 2048; ++i) 220 | { 221 | client[i].fd = -1; 222 | } 223 | client[0].events = POLLIN; 224 | client[0].fd = listenfd; 225 | while (1) 226 | { 227 | //rset = allset; 228 | nready = poll(client, maxfd+1, -1); 229 | //nready = select(maxfd + 1, &rset, NULL, NULL, NULL); 230 | if (nready == -1) 231 | { 232 | if (errno == EINTR) 233 | { 234 | continue; 235 | } 236 | ERR_EXIT("select"); 237 | } 238 | 239 | if (nready == 0) 240 | { 241 | continue; 242 | } 243 | 244 | //if (FD_ISSET(listenfd, &rset)) 245 | if (client[0].revents & POLLIN) 246 | { 247 | peerlen = sizeof(peeraddr); 248 | connfd = accept(listenfd, (struct sockaddr *)&peeraddr, &peerlen); 249 | if (connfd == -1) 250 | { 251 | ERR_EXIT("accept"); 252 | } 253 | for (i = 0; i < 2048; i++) 254 | { 255 | if (client[i].fd < 0) 256 | { 257 | client[i].fd = connfd; 258 | break; 259 | } 260 | } 261 | if (i == 2048) 262 | { 263 | fprintf(stderr, "too many clients\n"); 264 | exit(EXIT_FAILURE); 265 | } 266 | printf("id = %s, ", inet_ntoa(peeraddr.sin_addr)); 267 | printf("port = %d\n", ntohs(peeraddr.sin_port)); 268 | // FD_SET(connfd, &allset); 269 | client[i].events = POLLIN; 270 | Max++; 271 | maxfd = max(maxfd, connfd); 272 | if (--nready <= 0) 273 | { 274 | continue; 275 | } 276 | } 277 | for (i = 0; i < Max; ++i) 278 | { 279 | connfd = client[i].fd; 280 | if (connfd == -1) 281 | { 282 | continue; 283 | } 284 | //if (FD_ISSET(connfd, &rset)) 285 | if (client[0].fd & POLLIN) 286 | { 287 | char recvbuf[1024] = {0}; 288 | ret = readline(connfd, recvbuf, 1024); 289 | if (ret == -1) 290 | { 291 | ERR_EXIT("readline"); 292 | } 293 | if (ret == 0) 294 | { 295 | printf("client close\n"); 296 | client[i].fd = -1; 297 | //FD_CLR(connfd, &allset); 298 | Max--; 299 | } 300 | fputs(recvbuf, stdout); 301 | //sleep(4); 302 | writen(connfd, recvbuf, strlen(recvbuf)); 303 | if (--nready <= 0) 304 | { 305 | break; 306 | } 307 | }; 308 | } 309 | } 310 | // pid_t pid; 311 | // while (1) { 312 | // int connfd; 313 | // if ((connfd = accept(listenfd, (struct sockaddr *) &peeraddr, &peerlen)) < 0) { 314 | // ERR_EXIT("accept"); 315 | // } 316 | // 317 | // printf("id = %s, ", inet_ntoa(peeraddr.sin_addr)); 318 | // printf("port = %d\n", ntohs(peeraddr.sin_port)); 319 | // 320 | // pid = fork(); 321 | // 322 | // if (pid == -1) { 323 | // ERR_EXIT("fork"); 324 | // } 325 | // if (pid == 0) // 子进程 326 | // { 327 | // close(listenfd); 328 | // echo_srv(connfd); 329 | // //printf("child exit\n"); 330 | // exit(EXIT_SUCCESS); 331 | // } else { 332 | // //printf("parent exit\n"); 333 | // close(connfd); 334 | // } 335 | // 336 | // 337 | // } 338 | // 7. 断开连接 339 | close(listenfd); 340 | 341 | 342 | return 0; 343 | } -------------------------------------------------------------------------------- /sem.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-13. 3 | // 4 | 5 | // p30 system v信号量(一) 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | // https://blog.csdn.net/a1414345/article/details/64513946 19 | 20 | #define ERR_EXIT(m) \ 21 | do \ 22 | { \ 23 | perror(m); \ 24 | exit(EXIT_FAILURE); \ 25 | } while (0); 26 | 27 | union semun { 28 | int val; /* Value for SETVAL */ 29 | struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */ 30 | unsigned short *array; /* Array for GETALL, SETALL */ 31 | struct seminfo *__buf; /* Buffer for IPC_INFO 32 | (Linux-specific) */ 33 | }; 34 | 35 | // -c 36 | int sem_creat(key_t key) 37 | { 38 | int semid; 39 | semid = semget(key, 1, IPC_CREAT | IPC_EXCL | 0666); 40 | if (semid == -1) 41 | { 42 | ERR_EXIT("semget"); 43 | } 44 | return semid; 45 | } 46 | 47 | 48 | int sem_open(key_t key) 49 | { 50 | int semid; 51 | semid = semget(key, 0, 0); 52 | if (semid == -1) 53 | { 54 | ERR_EXIT("semget"); 55 | } 56 | return semid; 57 | } 58 | 59 | // -s 60 | int sem_setval(int semid, int val) 61 | { 62 | union semun su; 63 | su.val = val; 64 | int ret; 65 | ret = semctl(semid, 0, SETVAL, su); 66 | if (ret == -1) 67 | { 68 | ERR_EXIT("setval") 69 | } 70 | return 0; 71 | } 72 | 73 | // -g 74 | int sem_getval(int semid) 75 | { 76 | int ret; 77 | ret = semctl(semid, 0, GETVAL); 78 | if (ret == -1) 79 | { 80 | ERR_EXIT("getval") 81 | } 82 | printf("sem.val = %d\n", ret); 83 | return ret; 84 | } 85 | 86 | // -d 87 | int sem_d(int semid) 88 | { 89 | int ret; 90 | ret = semctl(semid, 0, IPC_RMID, NULL); 91 | if (ret == -1) 92 | { 93 | ERR_EXIT("rm_sem") 94 | } 95 | return 0; 96 | } 97 | 98 | // -p 99 | int sem_p(int semid) 100 | { 101 | struct sembuf sembuf; 102 | sembuf.sem_num = 0; 103 | sembuf.sem_op = -1; 104 | sembuf.sem_flg = 0; 105 | int ret; 106 | ret = semop(semid, &sembuf, 1); 107 | if (ret == -1) 108 | { 109 | ERR_EXIT("sem_p") 110 | } 111 | return ret; 112 | } 113 | 114 | // -v 115 | int sem_v(int semid) 116 | { 117 | struct sembuf sembuf; 118 | sembuf.sem_num = 0; 119 | sembuf.sem_op = 1; 120 | sembuf.sem_flg = 0; 121 | int ret; 122 | ret = semop(semid, &sembuf, 1); 123 | if (ret == -1) 124 | { 125 | ERR_EXIT("sem_v") 126 | } 127 | return ret; 128 | } 129 | 130 | // -f 131 | int sem_getmode(int semid) 132 | { 133 | union semun su; 134 | struct semid_ds sem; 135 | su.buf = &sem; 136 | int ret =semctl(semid, 0, IPC_STAT, su); 137 | if (ret == -1) 138 | { 139 | ERR_EXIT("semctl"); 140 | } 141 | printf("current permissions is %o\n", su.buf->sem_perm.mode); 142 | 143 | return ret; 144 | } 145 | 146 | 147 | // -m 148 | int sem_setmode(int semid, char* mode) 149 | { 150 | union semun su; 151 | struct semid_ds sem; 152 | su.buf = &sem; 153 | 154 | int ret =semctl(semid, 0, IPC_STAT, su); 155 | if (ret == -1) 156 | { 157 | ERR_EXIT("semctl"); 158 | } 159 | printf("current permissions is %o\n", su.buf->sem_perm.mode); 160 | 161 | sscanf(mode, "%o", (unsigned int*)&su.buf->sem_perm.mode); 162 | ret = semctl(semid, 0, IPC_SET, su); 163 | if (ret == -1) 164 | { 165 | ERR_EXIT("semctl"); 166 | } 167 | 168 | printf("permission updated..\n"); 169 | return ret; 170 | } 171 | 172 | void usage() 173 | { 174 | // 创建信号量 -c 175 | fprintf(stderr, "semtool -c\n"); 176 | // 删除 -d 177 | fprintf(stderr, "semtool -d\n"); 178 | // 获得值 -g 179 | fprintf(stderr, "semtool -g\n"); 180 | // 设置值 -s 181 | fprintf(stderr, "semtool -s \n"); 182 | // p操作 -p 183 | fprintf(stderr, "semtool -p\n"); 184 | // v操作 -v 185 | fprintf(stderr, "semtool -v\n"); 186 | // 查看权限 -f 187 | fprintf(stderr, "semtool -f\n"); 188 | // 更改权限 -m 189 | fprintf(stderr, "semtool -m \n"); 190 | } 191 | 192 | int main(int argc, char** argv) 193 | { 194 | int opt; 195 | 196 | opt = getopt(argc, argv, "cdgpvs:fm:"); 197 | if (opt == '?') 198 | { 199 | exit(EXIT_FAILURE); 200 | } 201 | if (opt == -1) 202 | { 203 | usage(); 204 | exit(EXIT_FAILURE); 205 | } 206 | 207 | // 为了获取一个独一无二的通信对象,必须使用键(可使用ftok()函数生成,返回值key)。 208 | // 这里的键是用来定位I P C 对象的标识符的 209 | key_t key = ftok(".", 's'); 210 | int semid; 211 | switch (opt) 212 | { 213 | case 'c': 214 | sem_creat(key); 215 | break; 216 | case 'p': 217 | semid = sem_open(key); 218 | sem_p(semid); 219 | sem_getval(semid); 220 | break; 221 | case 'v': 222 | semid = sem_open(key); 223 | sem_v(semid); 224 | sem_getval(semid); 225 | break; 226 | case 'd': 227 | semid = sem_open(key); 228 | sem_d(semid); 229 | break; 230 | case 's': 231 | semid = sem_open(key); 232 | sem_setval(semid, atoi(optarg)); 233 | break; 234 | case 'g': 235 | semid = sem_open(key); 236 | sem_getval(semid); 237 | break; 238 | case 'f': 239 | semid = sem_open(key); 240 | sem_getmode(semid); 241 | break; 242 | case 'm': 243 | semid = sem_open(key); 244 | sem_setmode(semid, argv[2]); 245 | break; 246 | } 247 | return 0; 248 | } -------------------------------------------------------------------------------- /sem02.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-13. 3 | // 4 | 5 | // p30 system v信号量(二) 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #define ERR_EXIT(m) \ 20 | do \ 21 | { \ 22 | perror(m); \ 23 | exit(EXIT_FAILURE); \ 24 | } while (0); 25 | 26 | union semun { 27 | int val; /* Value for SETVAL */ 28 | struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */ 29 | unsigned short *array; /* Array for GETALL, SETALL */ 30 | struct seminfo *__buf; /* Buffer for IPC_INFO 31 | (Linux-specific) */ 32 | }; 33 | 34 | // -c 35 | int sem_creat(key_t key) 36 | { 37 | int semid; 38 | semid = semget(key, 1, IPC_CREAT | IPC_EXCL | 0666); 39 | if (semid == -1) 40 | { 41 | ERR_EXIT("semget"); 42 | } 43 | return semid; 44 | } 45 | 46 | 47 | int sem_open(key_t key) 48 | { 49 | int semid; 50 | semid = semget(key, 0, 0); 51 | if (semid == -1) 52 | { 53 | ERR_EXIT("semget"); 54 | } 55 | return semid; 56 | } 57 | 58 | // -s 59 | int sem_setval(int semid, int val) 60 | { 61 | union semun su; 62 | su.val = val; 63 | int ret; 64 | ret = semctl(semid, 0, SETVAL, su); 65 | if (ret == -1) 66 | { 67 | ERR_EXIT("setval") 68 | } 69 | return 0; 70 | } 71 | 72 | // -g 73 | int sem_getval(int semid) 74 | { 75 | int ret; 76 | ret = semctl(semid, 0, GETVAL); 77 | if (ret == -1) 78 | { 79 | ERR_EXIT("getval") 80 | } 81 | printf("sem.val = %d\n", ret); 82 | return ret; 83 | } 84 | 85 | // -d 86 | int sem_d(int semid) 87 | { 88 | int ret; 89 | ret = semctl(semid, 0, IPC_RMID, NULL); 90 | if (ret == -1) 91 | { 92 | ERR_EXIT("rm_sem") 93 | } 94 | return 0; 95 | } 96 | 97 | // -p 98 | int sem_p(int semid) 99 | { 100 | struct sembuf sembuf; 101 | sembuf.sem_num = 0; 102 | sembuf.sem_op = -1; 103 | sembuf.sem_flg = 0; 104 | int ret; 105 | ret = semop(semid, &sembuf, 1); 106 | if (ret == -1) 107 | { 108 | ERR_EXIT("sem_p") 109 | } 110 | return ret; 111 | } 112 | 113 | // -v 114 | int sem_v(int semid) 115 | { 116 | struct sembuf sembuf; 117 | sembuf.sem_num = 0; 118 | sembuf.sem_op = 1; 119 | sembuf.sem_flg = 0; 120 | int ret; 121 | ret = semop(semid, &sembuf, 1); 122 | if (ret == -1) 123 | { 124 | ERR_EXIT("sem_v") 125 | } 126 | return ret; 127 | } 128 | 129 | // -f 130 | int sem_getmode(int semid) 131 | { 132 | union semun su; 133 | struct semid_ds sem; 134 | su.buf = &sem; 135 | int ret =semctl(semid, 0, IPC_STAT, su); 136 | if (ret == -1) 137 | { 138 | ERR_EXIT("semctl"); 139 | } 140 | printf("current permissions is %o\n", su.buf->sem_perm.mode); 141 | 142 | return ret; 143 | } 144 | 145 | 146 | // -m 147 | int sem_setmode(int semid, char* mode) 148 | { 149 | union semun su; 150 | struct semid_ds sem; 151 | su.buf = &sem; 152 | 153 | int ret =semctl(semid, 0, IPC_STAT, su); 154 | if (ret == -1) 155 | { 156 | ERR_EXIT("semctl"); 157 | } 158 | printf("current permissions is %o\n", su.buf->sem_perm.mode); 159 | 160 | sscanf(mode, "%o", (unsigned int*)&su.buf->sem_perm.mode); 161 | ret = semctl(semid, 0, IPC_SET, su); 162 | if (ret == -1) 163 | { 164 | ERR_EXIT("semctl"); 165 | } 166 | 167 | printf("permission updated..\n"); 168 | return ret; 169 | } 170 | 171 | void print(int sigmid, char* s) 172 | { 173 | int i = 0; 174 | int pause_time; 175 | for (int i = 0; i < 10; ++i) 176 | { 177 | sem_p(sigmid); 178 | 179 | printf("%s", s); 180 | fflush(stdout); 181 | pause_time = rand() % 3; 182 | sleep(pause_time); 183 | printf("%s", s); 184 | fflush(stdout); 185 | 186 | sem_v(sigmid); 187 | 188 | pause_time = rand() % 2; 189 | sleep(pause_time); 190 | } 191 | } 192 | 193 | int main(int argc, char** argv) 194 | { 195 | int sigmid = sem_creat(IPC_PRIVATE); 196 | sem_setval(sigmid, 0); 197 | pid_t pid = fork(); 198 | 199 | if (pid == -1) 200 | { 201 | ERR_EXIT("fork"); 202 | } 203 | 204 | if (pid > 0) 205 | { 206 | sem_setval(sigmid, 1); 207 | print(sigmid, "o"); 208 | 209 | } 210 | else 211 | { 212 | print(sigmid, "x"); 213 | } 214 | return 0; 215 | } -------------------------------------------------------------------------------- /sem03.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-13. 3 | // 4 | 5 | // p30 system v信号量(二) 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #define ERR_EXIT(m) \ 20 | do \ 21 | { \ 22 | perror(m); \ 23 | exit(EXIT_FAILURE); \ 24 | } while (0); 25 | 26 | union semun { 27 | int val; /* Value for SETVAL */ 28 | struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */ 29 | unsigned short *array; /* Array for GETALL, SETALL */ 30 | struct seminfo *__buf; /* Buffer for IPC_INFO 31 | (Linux-specific) */ 32 | }; 33 | 34 | int sigmid; 35 | 36 | void get2fork(int pid) 37 | { 38 | unsigned short int left = pid; 39 | unsigned short int right = (pid + 1) % 5; 40 | struct sembuf sembuf[2] = {{left, -1, 0}, {right, -1, 0}}; 41 | int ret = semop(sigmid, sembuf, 2); 42 | if (ret == -1) 43 | { 44 | ERR_EXIT("get2fork") 45 | } 46 | }; 47 | 48 | void put2fork(int pid) 49 | { 50 | unsigned short int left = pid; 51 | unsigned short int right = (pid + 1) % 5; 52 | struct sembuf sembuf[2] = {{left, 1, 0}, {right, 1, 0}}; 53 | int ret = semop(sigmid, sembuf, 2); 54 | if (ret == -1) 55 | { 56 | ERR_EXIT("get2fork") 57 | } 58 | }; 59 | 60 | 61 | void philosopher(int no) 62 | { 63 | while (1) 64 | { 65 | printf("%d is thinking\n", no); 66 | sleep(rand() % 3); 67 | printf("%d is hungry\n", no); 68 | get2fork(no); 69 | printf("%d is eating\n", no); 70 | sleep(rand() % 3); 71 | put2fork(no); 72 | } 73 | } 74 | 75 | 76 | int main(int argc, char** argv) 77 | { 78 | sigmid = semget(IPC_PRIVATE, 5, IPC_CREAT | IPC_EXCL | 0666); 79 | if (sigmid == -1) 80 | { 81 | ERR_EXIT("sigmid"); 82 | } 83 | 84 | union semun su; 85 | su.val = 1; 86 | for (int i = 0; i < 5; ++i) 87 | { 88 | semctl(sigmid, i, SETVAL, su); 89 | } 90 | 91 | int no = 0; 92 | pid_t pid; 93 | for (int i = 1; i < 5; ++i) 94 | { 95 | pid = fork(); 96 | if (pid > 0) 97 | { 98 | no = i; 99 | break; 100 | } 101 | } 102 | 103 | philosopher(no); 104 | return 0; 105 | } -------------------------------------------------------------------------------- /shmfifo/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5.1) 2 | project(NetworkProgramming) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | 6 | set(shmfifo_src 7 | shmfifo.cpp 8 | shmfifo.h) 9 | 10 | add_library(shmfifo ${shmfifo_src}) 11 | 12 | 13 | add_executable(shmfifo_recv shmfifo_recv.cpp) 14 | add_executable(shmfifo_send shmfifo_send.cpp) 15 | add_executable(shmfifo_destroy shmfifo_destroy.cpp) 16 | 17 | target_link_libraries(shmfifo_recv shmfifo) 18 | target_link_libraries(shmfifo_send shmfifo) 19 | target_link_libraries(shmfifo_destroy shmfifo semtool) -------------------------------------------------------------------------------- /shmfifo/shmfifo.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-13. 3 | // 4 | 5 | // p33 system v共享内存与信号量综合 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include "shmfifo.h" 22 | 23 | #define ERR_EXIT(m) \ 24 | do \ 25 | { \ 26 | perror(m); \ 27 | exit(EXIT_FAILURE); \ 28 | } while (0); 29 | 30 | union semun { 31 | int val; /* Value for SETVAL */ 32 | struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */ 33 | unsigned short *array; /* Array for GETALL, SETALL */ 34 | struct seminfo *__buf; /* Buffer for IPC_INFO 35 | (Linux-specific) */ 36 | }; 37 | 38 | int sem_creat(key_t key) 39 | { 40 | int semid; 41 | semid = semget(key, 1, IPC_CREAT | IPC_EXCL | 0666); 42 | if (semid == -1) 43 | { 44 | ERR_EXIT("semget"); 45 | } 46 | return semid; 47 | } 48 | 49 | int sem_setval(int semid, int val) 50 | { 51 | union semun su; 52 | su.val = val; 53 | int ret; 54 | ret = semctl(semid, 0, SETVAL, su); 55 | if (ret == -1) 56 | { 57 | ERR_EXIT("setval") 58 | } 59 | return 0; 60 | } 61 | 62 | // -p 63 | int sem_p(int semid) 64 | { 65 | struct sembuf sembuf; 66 | sembuf.sem_num = 0; 67 | sembuf.sem_op = -1; 68 | sembuf.sem_flg = 0; 69 | int ret; 70 | ret = semop(semid, &sembuf, 1); 71 | if (ret == -1) 72 | { 73 | ERR_EXIT("sem_p") 74 | } 75 | return ret; 76 | } 77 | 78 | // -v 79 | int sem_v(int semid) 80 | { 81 | struct sembuf sembuf; 82 | sembuf.sem_num = 0; 83 | sembuf.sem_op = 1; 84 | sembuf.sem_flg = 0; 85 | int ret; 86 | ret = semop(semid, &sembuf, 1); 87 | if (ret == -1) 88 | { 89 | ERR_EXIT("sem_v") 90 | } 91 | return ret; 92 | } 93 | 94 | // -d 95 | int sem_d(int semid) 96 | { 97 | int ret; 98 | ret = semctl(semid, 0, IPC_RMID, NULL); 99 | if (ret == -1) 100 | { 101 | ERR_EXIT("rm_sem") 102 | } 103 | return 0; 104 | } 105 | 106 | // -g 107 | int sem_getval(int semid) 108 | { 109 | int ret; 110 | ret = semctl(semid, 0, GETVAL); 111 | if (ret == -1) 112 | { 113 | ERR_EXIT("getval") 114 | } 115 | printf("sem.val = %d\n", ret); 116 | return ret; 117 | } 118 | 119 | int sem_open(key_t key) 120 | { 121 | int semid; 122 | semid = semget(key, 0, 0); 123 | if (semid == -1) 124 | { 125 | ERR_EXIT("semget"); 126 | } 127 | return semid; 128 | } 129 | 130 | shmfifo_t* shmfifo_init(int key, int blocksize, int blocks) 131 | { 132 | shmfifo_t* shmfifo1 = (shmfifo_t*) malloc(sizeof(shmfifo_t)); 133 | memset(shmfifo1, 0, sizeof(shmfifo_t)); 134 | int shmid = shmget(key, 0, 0); 135 | int size = sizeof(shmhead_t) + blocks * blocksize; 136 | if (shmid == -1) 137 | { 138 | // 创建共享内存 139 | shmid = shmget((key_t)key, size, 0666 | IPC_CREAT); 140 | if (shmid == -1) 141 | { 142 | ERR_EXIT("shmget"); 143 | } 144 | 145 | shmfifo1->shmid = shmid; 146 | 147 | void *shm = shmat(shmid, NULL, 0); 148 | if (shm == (void *)-1) 149 | { 150 | ERR_EXIT("shmat"); 151 | } 152 | 153 | shmfifo1->p_shm = (shmhead_t *)shm; 154 | 155 | // 创建信号量并赋值 156 | shmfifo1->sem_mutex = sem_creat(key+1); 157 | shmfifo1->sem_full = sem_creat(key+2); 158 | shmfifo1->sem_empty = sem_creat(key+3); 159 | 160 | sem_setval(shmfifo1->sem_mutex, 1); 161 | sem_setval(shmfifo1->sem_full, blocks); 162 | sem_setval(shmfifo1->sem_empty, 0); 163 | 164 | // 初始化其他成员变量 165 | memset(shmfifo1->p_shm, 0, sizeof(shmhead_t)); 166 | shmfifo1->p_shm->blocks = blocks; 167 | shmfifo1->p_shm->blocksize = blocksize; 168 | shmfifo1->p_shm->rd_index = 0; 169 | shmfifo1->p_shm->wr_index = 0; 170 | shmfifo1->p_payloadd = (char*)(shmfifo1->p_shm + 1); 171 | } 172 | else 173 | { 174 | shmfifo1->shmid = shmid; 175 | void *shm = shmat(shmid, NULL, 0); 176 | if (shm == (void *)-1) 177 | { 178 | ERR_EXIT("shmat"); 179 | } 180 | 181 | shmfifo1->p_shm = (shmhead_t *)shm; 182 | 183 | // 获取信号量 184 | shmfifo1->sem_mutex = sem_open(key + 1); 185 | shmfifo1->sem_full = sem_open(key + 2); 186 | shmfifo1->sem_empty = sem_open(key + 3); 187 | shmfifo1->p_payloadd = (char*)(shmfifo1->p_shm + 1); 188 | } 189 | return shmfifo1; 190 | } 191 | 192 | void shmfifo_put(shmfifo_t* fifo, const void* buf) 193 | { 194 | sem_p(fifo->sem_full); 195 | sem_p(fifo->sem_mutex); 196 | memcpy((fifo->p_shm->wr_index)*fifo->p_shm->blocksize + fifo->p_payloadd, buf, fifo->p_shm->blocksize); 197 | fifo->p_shm->wr_index = (fifo->p_shm->wr_index + 1) % fifo->p_shm->blocks; 198 | sem_v(fifo->sem_mutex); 199 | sem_v(fifo->sem_empty); 200 | } 201 | 202 | 203 | void shmfifo_get(shmfifo_t* fifo, char* buf) 204 | { 205 | sem_p(fifo->sem_empty); 206 | sem_p(fifo->sem_mutex); 207 | memcpy(buf, (fifo->p_shm->rd_index)*fifo->p_shm->blocksize + fifo->p_payloadd, fifo->p_shm->blocksize); 208 | fifo->p_shm->rd_index = (fifo->p_shm->rd_index + 1) % fifo->p_shm->blocks; 209 | sem_v(fifo->sem_mutex); 210 | sem_v(fifo->sem_full); 211 | } 212 | void shmfifo_destroy(shmfifo_t* fifo) 213 | { 214 | sem_d(fifo->sem_mutex); 215 | sem_d(fifo->sem_empty); 216 | sem_d(fifo->sem_full); 217 | shmctl(fifo->shmid, IPC_RMID, 0); 218 | free(fifo); 219 | } -------------------------------------------------------------------------------- /shmfifo/shmfifo.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-13. 3 | // 4 | 5 | #ifndef NETWORKPROGRAMMING_SHMFIFO_H 6 | #define NETWORKPROGRAMMING_SHMFIFO_H 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | typedef struct shmfifo shmfifo_t; 23 | typedef struct shmread shmhead_t; 24 | 25 | struct shmread 26 | { 27 | unsigned int blocksize; // 块大小 28 | unsigned int blocks; // 总块数 29 | unsigned int rd_index; // 读索引 30 | unsigned int wr_index; // 写索引 31 | }; 32 | 33 | struct shmfifo 34 | { 35 | shmhead_t *p_shm; // 共享内存头部指针 36 | char* p_payloadd; // 有效负载的起始地址 37 | 38 | int shmid; // 共享内存ID 39 | int sem_mutex; // 用来互斥用的信号量 40 | int sem_full; // 用来控制共享内参是否满的信号量 41 | int sem_empty; // 用来控制共享内参是否空的信号量 42 | }; 43 | 44 | shmfifo* shmfifo_init(int key, int blocksize, int blocks); 45 | void shmfifo_put(shmfifo* fifo, const void* buf); 46 | void shmfifo_get(shmfifo* fifo, char* buf); 47 | void shmfifo_destroy(shmfifo* fifo); 48 | 49 | #endif //NETWORKPROGRAMMING_SHMFIFO_H 50 | -------------------------------------------------------------------------------- /shmfifo/shmfifo_destroy.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-13. 3 | // 4 | 5 | // p33 system v共享内存与信号量综合 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include "shmfifo.h" 22 | 23 | #define ERR_EXIT(m) \ 24 | do \ 25 | { \ 26 | perror(m); \ 27 | exit(EXIT_FAILURE); \ 28 | } while (0); 29 | 30 | 31 | struct student 32 | { 33 | char name[32]; 34 | int age; 35 | }; 36 | 37 | int main(void) 38 | { 39 | shmfifo_t* shmfifo1 = shmfifo_init(1234, sizeof(student), 3); 40 | shmfifo_destroy(shmfifo1); 41 | return 0; 42 | } -------------------------------------------------------------------------------- /shmfifo/shmfifo_recv.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-13. 3 | // 4 | 5 | // p33 system v共享内存与信号量综合 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include "shmfifo.h" 22 | 23 | #define ERR_EXIT(m) \ 24 | do \ 25 | { \ 26 | perror(m); \ 27 | exit(EXIT_FAILURE); \ 28 | } while (0); 29 | 30 | struct student 31 | { 32 | char name[32]; 33 | int age; 34 | }; 35 | 36 | int main(int argc, char** argv) 37 | { 38 | shmfifo_t* shmfifo1 = shmfifo_init(1234, sizeof(student), 3); 39 | 40 | student* s = (struct student*)malloc(sizeof(student)); 41 | for(int i = 0; i < 5; ++i) 42 | { 43 | shmfifo_get(shmfifo1, (char *)s); 44 | printf("student name: %s, age: %d\n", s->name, s->age); 45 | } 46 | 47 | shmfifo_destroy(shmfifo1); 48 | return 0; 49 | } -------------------------------------------------------------------------------- /shmfifo/shmfifo_send.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-13. 3 | // 4 | 5 | // p33 system v共享内存与信号量综合 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include "shmfifo.h" 22 | 23 | #define ERR_EXIT(m) \ 24 | do \ 25 | { \ 26 | perror(m); \ 27 | exit(EXIT_FAILURE); \ 28 | } while (0); 29 | 30 | struct student 31 | { 32 | char name[32]; 33 | int age; 34 | }; 35 | 36 | int main(int argc, char** argv) 37 | { 38 | shmfifo_t* shmfifo1 = shmfifo_init(1234, sizeof(student), 3); 39 | 40 | student* s = (struct student*)malloc(sizeof(student)); 41 | memset(s, 0, sizeof(student)); 42 | s->age = 20; 43 | s->name[0] = 'A'; 44 | for(int i = 0; i < 5; ++i) 45 | { 46 | 47 | shmfifo_put(shmfifo1, s); 48 | s->name[0] = s->name[0] + i + 1; 49 | s->age = s->age + i + 1; 50 | printf("send ok\n"); 51 | } 52 | 53 | //shmfifo_destroy(shmfifo1); 54 | return 0; 55 | } -------------------------------------------------------------------------------- /shmread.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-13. 3 | // 4 | 5 | // p29 system v共享内存 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | using namespace std; 15 | 16 | #define ERR_EXIT(m) \ 17 | do \ 18 | { \ 19 | perror(m); \ 20 | exit(EXIT_FAILURE); \ 21 | } while (0); 22 | 23 | struct student 24 | { 25 | char name[32]; 26 | int age; 27 | }; 28 | 29 | int main(int argc, char** argv) 30 | { 31 | int shmid; // 共享内存标识符 32 | 33 | // 创建共享内存 34 | shmid = shmget((key_t)1234, 0, 0); 35 | if (shmid == -1) 36 | { 37 | ERR_EXIT("shmget"); 38 | } 39 | 40 | // 第一次创建完共享内存时,它还不能被任何进程访问,shmat()函数的作用就是用来启动对该共享内存的访问,并把共享内存连接到当前进程的地址空间 41 | // 将共享内存链接到当前进程的地址空间 42 | void *shm = shmat(shmid, 0, 0); 43 | if (shm == (void *)-1) 44 | { 45 | ERR_EXIT("shmat"); 46 | } 47 | 48 | // 设置共享内存 49 | student *shared = (struct student*) shm; 50 | printf("student name: %s, age: %d\n", shared->name, shared->age); 51 | 52 | memcpy(shared, "quit", 4); 53 | 54 | if (shmdt(shm) == -1) 55 | { 56 | ERR_EXIT("shmdt"); 57 | } 58 | 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /shmwrite.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-13. 3 | // 4 | 5 | // p29 system v共享内存 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | using namespace std; 15 | 16 | #define ERR_EXIT(m) \ 17 | do \ 18 | { \ 19 | perror(m); \ 20 | exit(EXIT_FAILURE); \ 21 | } while (0); 22 | 23 | struct student 24 | { 25 | char name[32]; 26 | int age; 27 | }; 28 | 29 | int main(int argc, char** argv) 30 | { 31 | int shmid; // 共享内存标识符 32 | 33 | // 创建共享内存 34 | shmid = shmget((key_t)1234, sizeof(student), 0666 | IPC_CREAT); 35 | if (shmid == -1) 36 | { 37 | ERR_EXIT("shmget"); 38 | } 39 | 40 | // 第一次创建完共享内存时,它还不能被任何进程访问,shmat()函数的作用就是用来启动对该共享内存的访问,并把共享内存连接到当前进程的地址空间 41 | // 将共享内存链接到当前进程的地址空间 42 | void *shm = shmat(shmid, NULL, 0); 43 | if (shm == (void *)-1) 44 | { 45 | ERR_EXIT("shmat"); 46 | } 47 | 48 | // 设置共享内存 49 | student *shared = (struct student*) shm; 50 | strcpy(shared->name, "hello"); 51 | shared->age = 20; 52 | 53 | while (true) 54 | { 55 | if (memcmp(shared->name, "quit", 4) == 0) 56 | { 57 | break; 58 | } 59 | } 60 | // 把共享内存从当前进程中分离 61 | if (shmdt(shm) == -1) 62 | { 63 | ERR_EXIT("shmdt"); 64 | } 65 | 66 | shmctl(shmid, IPC_RMID, 0); 67 | return 0; 68 | } 69 | -------------------------------------------------------------------------------- /sockpair.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-10. 3 | // 4 | 5 | // socket编程 17 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | using namespace std; 16 | 17 | #define ERR_EXIT(m) \ 18 | do \ 19 | { \ 20 | perror(m); \ 21 | exit(EXIT_FAILURE); \ 22 | } while(0); 23 | 24 | 25 | int main(int argc, char** argv) 26 | { 27 | int fd[2]; 28 | int r = socketpair(AF_UNIX, SOCK_STREAM, 0, fd); 29 | 30 | if (r < 0) 31 | { 32 | ERR_EXIT("socketpair"); 33 | } 34 | 35 | pid_t pid = fork(); 36 | if (pid == 0) 37 | { 38 | int val = 0; 39 | close(fd[0]); 40 | while (1) 41 | { 42 | sleep(1); 43 | ++val; 44 | printf("sending data: %d\n", val); 45 | write(fd[1], &val, sizeof val); 46 | read(fd[1], &val, sizeof val); 47 | printf("recver data: %d\n", val); 48 | } 49 | } 50 | else 51 | { 52 | close(fd[1]); 53 | int val; 54 | while (1) 55 | { 56 | read(fd[0], &val, sizeof val); 57 | val++; 58 | write(fd[0], &val, sizeof val); 59 | } 60 | } 61 | return 0; 62 | } -------------------------------------------------------------------------------- /sockpair02.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-10. 3 | // 4 | 5 | // 6 | // Created by jxq on 19-8-10. 7 | // 8 | 9 | // socket编程 17 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | using namespace std; 22 | // https://blog.csdn.net/y396397735/article/details/50684558 23 | 24 | #define ERR_EXIT(m) \ 25 | do \ 26 | { \ 27 | perror(m); \ 28 | exit(EXIT_FAILURE); \ 29 | } while(0); 30 | 31 | 32 | // https://www.cnblogs.com/mickole/articles/3204406.html 33 | void send_fd(int sock_fd, int send_fd) 34 | { 35 | int ret; 36 | struct msghdr msg; 37 | struct cmsghdr *p_cmsg; 38 | struct iovec vec; 39 | char cmsgbuf[CMSG_SPACE(sizeof(send_fd))]; // 整个结构体的大小 40 | int *p_fds; 41 | char sendchar = 0; 42 | 43 | msg.msg_control = cmsgbuf; 44 | msg.msg_controllen = sizeof(cmsgbuf); 45 | 46 | p_cmsg = CMSG_FIRSTHDR(&msg); // CMSG_FIRSTHDR宏可以得到首个 cmsghdr 结构体的指针 47 | p_cmsg->cmsg_level = SOL_SOCKET; 48 | p_cmsg->cmsg_type = SCM_RIGHTS; 49 | p_cmsg->cmsg_len = CMSG_LEN(sizeof(send_fd)); 50 | 51 | // 传入结构体指针 p_cmsg ,宏CMSG_DATA 可以得到准备存放send_fd 的位置指针,将send_fd 放进去 52 | p_fds = (int *)CMSG_DATA(p_cmsg); 53 | *p_fds = send_fd; // 通过传递辅助数据的方式传递文件描述符 54 | 55 | msg.msg_name = NULL; 56 | msg.msg_namelen = 0; 57 | msg.msg_iov = &vec; 58 | msg.msg_iovlen = 1; // 主要目的不是传递数据,故只传1个字符 59 | msg.msg_flags = 0; 60 | 61 | vec.iov_base = &sendchar; 62 | vec.iov_len = sizeof(sendchar); 63 | 64 | ret = sendmsg(sock_fd, &msg, 0); 65 | 66 | if (ret != 1) 67 | ERR_EXIT("sendmsg"); 68 | } 69 | 70 | int recv_fd(const int sock_fd) 71 | { 72 | int ret; 73 | struct msghdr msg; 74 | char recvchar; 75 | struct iovec vec; 76 | int recv_fd; 77 | 78 | char cmsgbuf[CMSG_SPACE(sizeof(recv_fd))]; 79 | struct cmsghdr *p_cmsg; 80 | int *p_fd; 81 | 82 | vec.iov_base = &recvchar; 83 | vec.iov_len = sizeof(recvchar); 84 | 85 | msg.msg_name = NULL; 86 | msg.msg_namelen = 0; 87 | msg.msg_iov = &vec; 88 | msg.msg_iovlen = 1; 89 | msg.msg_control = cmsgbuf; 90 | msg.msg_controllen = sizeof(cmsgbuf); 91 | msg.msg_flags = 0; 92 | 93 | p_fd = (int *)CMSG_DATA(CMSG_FIRSTHDR(&msg)); 94 | *p_fd = -1; 95 | 96 | ret = recvmsg(sock_fd, &msg, 0); 97 | if (ret != 1) 98 | ERR_EXIT("recvmsg"); 99 | 100 | p_cmsg = CMSG_FIRSTHDR(&msg); // 首个cmsghdr地址 101 | if (p_cmsg == NULL) 102 | ERR_EXIT("no passed fd"); 103 | 104 | 105 | p_fd = (int *)CMSG_DATA(p_cmsg); // 文件描述符 106 | recv_fd = *p_fd; 107 | if (recv_fd == -1) 108 | ERR_EXIT("no passed fd"); 109 | 110 | return recv_fd; 111 | } 112 | 113 | int main(int argc, char** argv) 114 | { 115 | int socketfd[2]; 116 | int r = socketpair(AF_UNIX, SOCK_STREAM, 0, socketfd); 117 | 118 | if (r < 0) 119 | { 120 | ERR_EXIT("socketpair"); 121 | } 122 | 123 | pid_t pid = fork(); 124 | if (pid == -1) 125 | { 126 | ERR_EXIT("fork"); 127 | } 128 | if (pid == 0) 129 | { 130 | int val = 0; 131 | close(socketfd[0]); 132 | int fd = recv_fd(socketfd[1]); 133 | char buf[1024] = {0}; 134 | read(fd, buf, sizeof buf); 135 | printf("buf = %s\n", buf); 136 | } 137 | else 138 | { 139 | close(socketfd[1]); 140 | int fd; 141 | fd = open("/home/jxq/CLionProjects/NetworkProgramming/text.txt", O_RDONLY); 142 | if (fd == -1) 143 | { 144 | ERR_EXIT("open"); 145 | } 146 | send_fd(socketfd[0], fd); 147 | } 148 | return 0; 149 | } -------------------------------------------------------------------------------- /thread.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-14. 3 | // 4 | 5 | // p37 poxis 线程(二) 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | using namespace std; 15 | 16 | 17 | #define ERR_EXIT(m) \ 18 | do \ 19 | { \ 20 | perror(m); \ 21 | exit(EXIT_FAILURE); \ 22 | } while(0); 23 | 24 | struct tsd_t 25 | { 26 | int id; 27 | char* arg; 28 | }; 29 | 30 | pthread_key_t thread_key; 31 | 32 | pthread_once_t once = PTHREAD_ONCE_INIT; 33 | 34 | void destr_function(void *) 35 | { 36 | printf("destroy...\n"); 37 | } 38 | 39 | void once_run(void) 40 | { 41 | pthread_key_create(&thread_key, destr_function); 42 | cout<<"once_run in thread "<<(unsigned int )pthread_self()<arg = (char *)arg; 50 | value->id = pthread_self(); 51 | 52 | pthread_setspecific(thread_key, value); 53 | printf("%s setspecific %p\n", (char*)arg, value); 54 | value = (struct tsd_t*)pthread_getspecific(thread_key); 55 | printf("tid = 0x%x str = %s\n", (int)value->id, value->arg); 56 | sleep(2); 57 | value = (struct tsd_t*)pthread_getspecific(thread_key); 58 | printf("tid = 0x%x str = %s\n", (int)value->id, value->arg); 59 | 60 | return NULL; 61 | } 62 | 63 | 64 | 65 | int main(int argc, char** argv) { 66 | 67 | //pthread_key_create(&thread_key, destr_function); 68 | 69 | pthread_t thread1; 70 | pthread_t thread2; 71 | 72 | pthread_create(&thread1, NULL, start_routine, (char *)"thread1"); 73 | pthread_create(&thread2, NULL, start_routine, (char *)"thread2"); 74 | 75 | 76 | pthread_join(thread1, NULL); 77 | pthread_join(thread2, NULL); 78 | return 0; 79 | } -------------------------------------------------------------------------------- /thread_create.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-14. 3 | // 4 | 5 | // p37 poxis 线程(一) 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | using namespace std; 15 | 16 | 17 | #define ERR_EXIT(m) \ 18 | do \ 19 | { \ 20 | perror(m); \ 21 | exit(EXIT_FAILURE); \ 22 | } while(0); 23 | 24 | void * start_routine (void *arg) 25 | { 26 | pthread_detach(pthread_self()); 27 | for (int i = 0; i < 20; ++i) 28 | { 29 | cout << "B"; 30 | } 31 | return (char *)"hello"; 32 | } 33 | 34 | int main(int argc, char** argv) { 35 | int ret; 36 | pthread_t thread; 37 | 38 | ret = pthread_create(&thread, NULL, start_routine, NULL); 39 | if (ret != 0) 40 | { 41 | ERR_EXIT("pthread_create"); 42 | } 43 | 44 | for (int i = 0; i < 20; ++i) 45 | { 46 | cout << "A"; 47 | } 48 | 49 | void *retval; 50 | if (pthread_join(thread, &retval) != 0) 51 | { 52 | ERR_EXIT("pthread_join"); 53 | } 54 | printf("\n%s\n", (char *)retval); 55 | 56 | return 0; 57 | } -------------------------------------------------------------------------------- /threadechosrv.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-6. 3 | // 4 | 5 | // p37 poxis 线程(一) 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | 17 | using namespace std; 18 | 19 | struct packet 20 | { 21 | int len; 22 | char buf[1024]; 23 | }; 24 | 25 | #define ERR_EXIT(m) \ 26 | do \ 27 | { \ 28 | perror(m); \ 29 | exit(EXIT_FAILURE); \ 30 | } while(0); 31 | 32 | ssize_t readn(int fd, void *buf, size_t count) 33 | { 34 | size_t nleft = count; // 剩余字节数 35 | ssize_t nread; 36 | char *bufp = (char*) buf; 37 | 38 | while (nleft > 0) 39 | { 40 | nread = read(fd, bufp, nleft); 41 | if (nread < 0) 42 | { 43 | if (errno == EINTR) 44 | { 45 | continue; 46 | } 47 | return -1; 48 | } else if (nread == 0) 49 | { 50 | return count - nleft; 51 | } 52 | 53 | bufp += nread; 54 | nleft -= nread; 55 | } 56 | return count; 57 | } 58 | 59 | ssize_t writen(int fd, const void *buf, size_t count) 60 | { 61 | size_t nleft = count; 62 | ssize_t nwritten; 63 | char* bufp = (char*)buf; 64 | 65 | while (nleft > 0) 66 | { 67 | if ((nwritten = write(fd, bufp, nleft)) < 0) 68 | { 69 | if (errno == EINTR) 70 | { 71 | continue; 72 | } 73 | return -1; 74 | } 75 | else if (nwritten == 0) 76 | { 77 | continue; 78 | } 79 | bufp += nwritten; 80 | nleft -= nwritten; 81 | } 82 | return count; 83 | } 84 | 85 | ssize_t recv_peek(int sockfd, void *buf, size_t len) 86 | { 87 | while (1) 88 | { 89 | int ret = recv(sockfd, buf, len, MSG_PEEK); // 查看传入消息 90 | if (ret == -1 && errno == EINTR) 91 | { 92 | continue; 93 | } 94 | return ret; 95 | } 96 | } 97 | 98 | ssize_t readline(int sockfd, void *buf, size_t maxline) 99 | { 100 | int ret; 101 | int nread; 102 | char *bufp = (char*)buf; // 当前指针位置 103 | int nleft = maxline; 104 | while (1) 105 | { 106 | ret = recv_peek(sockfd, buf, nleft); 107 | if (ret < 0) 108 | { 109 | return ret; 110 | } 111 | else if (ret == 0) 112 | { 113 | return ret; 114 | } 115 | nread = ret; 116 | int i; 117 | for (i = 0; i < nread; i++) 118 | { 119 | if (bufp[i] == '\n') 120 | { 121 | ret = readn(sockfd, bufp, i+1); 122 | if (ret != i+1) 123 | { 124 | exit(EXIT_FAILURE); 125 | } 126 | return ret; 127 | } 128 | } 129 | if (nread > nleft) 130 | { 131 | exit(EXIT_FAILURE); 132 | } 133 | nleft -= nread; 134 | ret = readn(sockfd, bufp, nread); 135 | if (ret != nread) 136 | { 137 | exit(EXIT_FAILURE); 138 | } 139 | bufp += nread; 140 | } 141 | return -1; 142 | } 143 | 144 | void echo_srv(int connfd) 145 | { 146 | char recvbuf[1024]; 147 | // struct packet recvbuf; 148 | int n; 149 | while (1) 150 | { 151 | memset(recvbuf, 0, sizeof recvbuf); 152 | int ret = readline(connfd, recvbuf, 1024); 153 | if (ret == -1) 154 | { 155 | ERR_EXIT("readline"); 156 | } 157 | if (ret == 0) 158 | { 159 | printf("client close\n"); 160 | break; 161 | } 162 | 163 | fputs(recvbuf, stdout); 164 | writen(connfd, recvbuf, strlen(recvbuf)); 165 | } 166 | 167 | } 168 | 169 | 170 | void * start_routine (void *arg) 171 | { 172 | pthread_detach(pthread_self()); 173 | int conn = *((int*)arg); 174 | echo_srv(conn); 175 | return (char *)"hello"; 176 | } 177 | 178 | int main(int argc, char** argv) { 179 | // 1. 创建套接字 180 | int listenfd; 181 | if ((listenfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { 182 | ERR_EXIT("socket"); 183 | } 184 | 185 | // 2. 分配套接字地址 186 | struct sockaddr_in servaddr; 187 | memset(&servaddr, 0, sizeof servaddr); 188 | servaddr.sin_family = AF_INET; 189 | servaddr.sin_port = htons(6666); 190 | servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 191 | // servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); 192 | // inet_aton("127.0.0.1", &servaddr.sin_addr); 193 | 194 | int on = 1; 195 | // 确保time_wait状态下同一端口仍可使用 196 | if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on) < 0) { 197 | ERR_EXIT("setsockopt"); 198 | } 199 | 200 | // 3. 绑定套接字地址 201 | if (bind(listenfd, (struct sockaddr *) &servaddr, sizeof servaddr) < 0) { 202 | ERR_EXIT("bind"); 203 | } 204 | // 4. 等待连接请求状态 205 | if (listen(listenfd, SOMAXCONN) < 0) { 206 | ERR_EXIT("listen"); 207 | } 208 | // 5. 允许连接 209 | struct sockaddr_in peeraddr; 210 | socklen_t peerlen = sizeof peeraddr; 211 | 212 | 213 | // 6. 数据交换 214 | pid_t pid; 215 | while (1) { 216 | int connfd; 217 | if ((connfd = accept(listenfd, (struct sockaddr *) &peeraddr, &peerlen)) < 0) { 218 | ERR_EXIT("accept"); 219 | } 220 | 221 | printf("id = %s, ", inet_ntoa(peeraddr.sin_addr)); 222 | printf("port = %d\n", ntohs(peeraddr.sin_port)); 223 | 224 | pthread_t thread; 225 | int ret = pthread_create(&thread, NULL, start_routine, &connfd); 226 | if (ret != 0) 227 | { 228 | ERR_EXIT("pthread_create"); 229 | } 230 | 231 | 232 | } 233 | // 7. 断开连接 234 | close(listenfd); 235 | 236 | 237 | return 0; 238 | } -------------------------------------------------------------------------------- /threadpool/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5.1) 2 | project(NetworkProgramming) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | 6 | set(threadpool 7 | condition.cpp 8 | condition.h 9 | threadpool.cpp 10 | threadpool.h) 11 | 12 | add_library(thread_src ${threadpool}) 13 | 14 | add_executable(test01 test.cpp) 15 | target_link_libraries(test01 thread_src pthread rt) -------------------------------------------------------------------------------- /threadpool/condition.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-15. 3 | // 4 | 5 | #include "condition.h" 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | using namespace std; 13 | 14 | int condition_init(condition_t *cond) 15 | { 16 | int state; 17 | state = pthread_cond_init(&(cond->pcond), NULL); 18 | if (state == 0) 19 | { 20 | return state; 21 | } 22 | state = pthread_mutex_init(&(cond->pmutex), NULL); 23 | if (state == 0) 24 | { 25 | return state; 26 | } 27 | return 0; 28 | } 29 | 30 | int condition_lock(condition_t *cond) 31 | { 32 | //cout << pthread_mutex_lock(&(cond->pmutex)) << endl; 33 | if (pthread_mutex_lock(&(cond->pmutex)) == 0) 34 | { 35 | printf("pthread_mutex_lock error\n"); 36 | exit(EXIT_FAILURE); 37 | } 38 | return 1; 39 | } 40 | 41 | int condition_unlock(condition_t *cond) 42 | { 43 | pthread_mutex_unlock(&(cond->pmutex)); 44 | } 45 | int condition_wait(condition_t *cond) 46 | { 47 | return pthread_cond_wait(&(cond->pcond), &(cond->pmutex)); 48 | } 49 | 50 | int condition_timewait(condition_t *cond, const struct timespec *abstime) 51 | { 52 | return pthread_cond_timedwait(&(cond->pcond), &(cond->pmutex), abstime); 53 | } 54 | 55 | int condition_signal(condition_t *cond) 56 | { 57 | return pthread_cond_signal(&(cond->pcond)); 58 | } 59 | 60 | int condition_broadcast(condition_t *cond) 61 | { 62 | return pthread_cond_broadcast(&(cond->pcond)); 63 | } 64 | 65 | int condition_destroy(condition_t *cond) 66 | { 67 | int state; 68 | state = pthread_cond_destroy(&(cond->pcond)); 69 | if (state == 0) 70 | { 71 | return state; 72 | } 73 | state = pthread_mutex_destroy(&(cond->pmutex)); 74 | if (state == 0) 75 | { 76 | return state; 77 | } 78 | return 0; 79 | } 80 | -------------------------------------------------------------------------------- /threadpool/condition.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-15. 3 | // 4 | 5 | // p41 线程池 6 | 7 | #ifndef NETWORKPROGRAMMING_CONDITION_H 8 | #define NETWORKPROGRAMMING_CONDITION_H 9 | 10 | #include 11 | 12 | typedef struct condition 13 | { 14 | pthread_mutex_t pmutex; 15 | pthread_cond_t pcond; 16 | } condition_t; 17 | 18 | int condition_init(condition_t *cond); 19 | int condition_lock(condition_t *cond); 20 | int condition_unlock(condition_t *cond); 21 | int condition_wait(condition_t *cond); 22 | int condition_timewait(condition_t *cond, const struct timespec *abstime); 23 | int condition_signal(condition_t *cond); 24 | int condition_broadcast(condition_t *cond); 25 | int condition_destroy(condition_t *cond); 26 | 27 | 28 | #endif //NETWORKPROGRAMMING_CONDITION_H 29 | -------------------------------------------------------------------------------- /threadpool/test.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-15. 3 | // 4 | 5 | // p41 线程池 6 | 7 | #include "condition.h" 8 | #include "threadpool.h" 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | void *run (void *arg) 15 | { 16 | printf("threadpool 0x%x working task %d\n", (int)pthread_self(), *(int*)(arg)); 17 | sleep(1); 18 | free(arg); 19 | return NULL; 20 | } 21 | 22 | int main(void) 23 | { 24 | // 结构体指针需要初始化 不晓得为啥报错 25 | threadpool_t pool; 26 | threadpool_init(&pool, 3); 27 | 28 | int i; 29 | for (i = 0; i < 10; ++i) 30 | { 31 | int *a = (int*)malloc(sizeof(int)); 32 | *a = i; 33 | threadpool_add_task(&pool, run, a); 34 | } 35 | // sleep(15); 36 | threadpool_destroy(&pool); 37 | return 0; 38 | } -------------------------------------------------------------------------------- /threadpool/threadpool.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-15. 3 | // 4 | 5 | // p41 线程池 6 | 7 | #include "threadpool.h" 8 | #include 9 | #include 10 | #include 11 | 12 | using namespace std; 13 | 14 | void *thread_routine (void *arg) 15 | { 16 | struct timespec abstime; 17 | int timeout; 18 | printf("thread 0x%x is starting\n", (int)pthread_self()); 19 | threadpool_t *pool = (threadpool_t*)arg; 20 | while (1) 21 | { 22 | timeout = 0; 23 | condition_lock(&pool->ready); 24 | ++pool->idle; 25 | // 等待队列有任务到来或者线程池销毁通知 26 | while (pool->first == NULL && !pool->quit) 27 | { 28 | printf("thread 0x%x is waiting\n", (int)pthread_self()); 29 | //condition_wait(&pool->ready); 30 | clock_gettime(CLOCK_REALTIME, &abstime); 31 | abstime.tv_sec += 2; 32 | // 超时设置2秒 33 | int state = condition_timewait(&pool->ready, &abstime); 34 | if (state == ETIMEDOUT) 35 | { 36 | printf("thread 0x%x is wait time out\n", (int)pthread_self()); 37 | timeout = 1; 38 | break; 39 | } 40 | } 41 | // 等待到条件,处于工作状态 42 | --pool->idle; 43 | if (pool->first != NULL) 44 | { 45 | // 从队头取出任务 46 | task_t *t = pool->first; 47 | pool->first = t->next; 48 | // 执行任务需要一定的时间,所以需要先解锁,以便生产者进程 49 | // 能够往队列中天剑任务,其他消费者线程能够进入等待任务 50 | condition_unlock(&pool->ready); 51 | t->run(t->arg); 52 | free(t); 53 | condition_lock(&pool->ready); 54 | } 55 | // 如果等待到销毁线程池通知,且任务都执行完毕 56 | if (pool->quit && pool->first == NULL) 57 | { 58 | pool->counter--; 59 | if (pool->counter == 0) 60 | { 61 | condition_signal(&pool->ready); 62 | } 63 | condition_unlock(&pool->ready); 64 | // 跳出循环之前记得解锁 65 | break; 66 | } 67 | 68 | if (timeout && pool->first == NULL) 69 | { 70 | pool->counter--; 71 | condition_unlock(&pool->ready); 72 | // 跳出循环之前记得解锁 73 | break; 74 | } 75 | 76 | condition_unlock(&pool->ready); 77 | } 78 | 79 | printf("thread 0x%x is exiting \n", (int)pthread_self()); 80 | 81 | return NULL; 82 | } 83 | 84 | // 初始化线程池 85 | void threadpool_init(threadpool_t *pool, int threads) 86 | { 87 | // pool = (threadpool_t*)malloc(sizeof(pool)); 88 | condition_init(&(pool->ready)); 89 | pool->first = NULL; 90 | pool->last = NULL; 91 | pool->counter = 0; 92 | pool->idle = 0; 93 | pool->max_threads = threads; 94 | pool->quit = 0; 95 | 96 | } 97 | 98 | // 在线程池中添加任务 99 | void threadpool_add_task(threadpool_t *pool, void *(*run)(void *arg), void *arg) 100 | { 101 | // 生成新任务 102 | task_t* newtask = (task_t *)malloc(sizeof(task_t)); 103 | //cout << (char *)pool->first->arg << endl; 104 | newtask->run = run; 105 | newtask->arg = arg; 106 | newtask->next = NULL; 107 | 108 | 109 | condition_lock(&pool->ready); 110 | // 将任务添加到队列中 111 | if (pool->first == NULL) 112 | { 113 | pool->first = newtask; 114 | } 115 | else 116 | { 117 | pool->last->next = newtask; 118 | } 119 | pool->last = newtask; 120 | 121 | // 如果有等待任务的线程,则唤醒其中一个 122 | if (pool->idle > 0) 123 | { 124 | condition_signal(&pool->ready); 125 | } 126 | else if (pool->counter < pool->max_threads) 127 | { 128 | // 没有等待线程,并且当前线程数不超过最大线程数,则创建一个新线程 129 | pthread_t tid; 130 | pthread_create(&tid, NULL, thread_routine, pool); 131 | ++pool->counter; 132 | } 133 | condition_unlock(&pool->ready); 134 | } 135 | 136 | // 销毁线程池 137 | void threadpool_destroy(threadpool_t *pool) 138 | { 139 | if (pool->quit) 140 | { 141 | return; 142 | } 143 | condition_lock(&pool->ready); 144 | pool->quit = 1; 145 | if (pool->counter > 0) 146 | { 147 | if (pool->idle > 0) 148 | { 149 | condition_broadcast(&pool->ready); 150 | } 151 | // 处于执行任务状态中的线程,不会收到广播 152 | // 线程池需要等执行任务状态中的线程全部退出 153 | while (pool->counter > 0) 154 | { 155 | condition_wait(&pool->ready); 156 | } 157 | } 158 | condition_unlock(&pool->ready); 159 | condition_destroy(&pool->ready); 160 | //free(pool); 161 | } -------------------------------------------------------------------------------- /threadpool/threadpool.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-15. 3 | // 4 | 5 | // p41 线程池 6 | 7 | #ifndef NETWORKPROGRAMMING_THREADPOOL_H 8 | #define NETWORKPROGRAMMING_THREADPOOL_H 9 | 10 | #include "condition.h" 11 | 12 | // 任务结构体,将任务放入队列由线程池中的线程来执行 13 | typedef struct task 14 | { 15 | void *(*run)(void *arg); // 任务回调函数 16 | void *arg; // 回调函数参数 17 | struct task* next; 18 | } task_t; 19 | 20 | // 线程池结构体 21 | typedef struct threadpool 22 | { 23 | condition_t ready; // 任务准备就绪或者线程池销毁通知 24 | task_t *first; // 任务队列头指针 25 | task_t *last; // 任务队列尾指针 26 | int counter; // 线程池当前线程数 27 | int idle; // 线程池中当前正在等待任务的线程数 28 | int max_threads; // 线程池中最大允许的线程数 29 | int quit; // 销毁线程池的时候置1 30 | } threadpool_t; 31 | 32 | // 初始化线程池 33 | void threadpool_init(threadpool_t *pool, int threads); 34 | 35 | // 在线程池中添加任务 36 | void threadpool_add_task(threadpool_t *pool, void *(*run)(void *arg), void *arg); 37 | 38 | // 销毁线程池 39 | void threadpool_destroy(threadpool_t *pool); 40 | 41 | 42 | #endif //NETWORKPROGRAMMING_THREADPOOL_H 43 | -------------------------------------------------------------------------------- /udpchat/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5.1) 2 | project(NetworkProgramming) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | 6 | #set(pub Pub.h) 7 | # 8 | #add_library(pub_src ${pub}) 9 | 10 | add_executable(UdpChatCli UdpChatCli.cpp) 11 | add_executable(UdpChatSrv UdpChatSrv.cpp) 12 | #target_link_libraries(UdpChatCli pub_src) 13 | #target_link_libraries(UdpChatSrv pub_src) 14 | -------------------------------------------------------------------------------- /udpchat/Pub.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-8. 3 | // 4 | 5 | #ifndef NETWORKPROGRAMMING_PUB_H 6 | #define NETWORKPROGRAMMING_PUB_H 7 | 8 | #include 9 | #include 10 | 11 | using namespace std; 12 | 13 | // C2S 14 | #define C2S_LOGIN 0x01 15 | #define C2S_LOGOUT 0x02 16 | #define C2S_ONLINE_USER 0x03 17 | 18 | #define MSG_LEN 512 19 | 20 | // S2C 21 | #define S2C_LOGIN_OK 0x01 22 | #define S2C_ALREADY_LOGINED 0x02 23 | #define S2C_SOMEONE_LOGIN 0x03 24 | #define S2C_SOMEONE_LOGOUT 0x04 25 | #define S2C_ONLINE_USER 0x05 26 | 27 | // C2C 28 | #define C2C_CHAT 0x06 29 | 30 | typedef struct message 31 | { 32 | int cmd; 33 | char body[MSG_LEN]; 34 | } MESSAGE; 35 | 36 | typedef struct user_info 37 | { 38 | char username[16]; 39 | unsigned int ip; 40 | unsigned short port; 41 | } USER_INFO; 42 | 43 | typedef struct char_msg 44 | { 45 | char username[16]; 46 | char msg[100]; 47 | } CHAT_MSG; 48 | 49 | typedef list USER_LIST; 50 | 51 | #endif //NETWORKPROGRAMMING_PUB_H 52 | -------------------------------------------------------------------------------- /udpchat/UdpChatSrv.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-8. 3 | // 4 | 5 | // socket编程15 UDP聊天实验室实现 6 | 7 | #include "Pub.h" 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include /* See NOTES */ 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #define ERR_EXIT(m) \ 20 | do \ 21 | { \ 22 | perror(m); \ 23 | exit(EXIT_FAILURE); \ 24 | } while (0); 25 | 26 | // 聊天室成员列表 27 | USER_LIST client_list; 28 | 29 | void test(int sock, struct sockaddr_in* peeraddr) 30 | { 31 | 32 | sendto(sock, "server", sizeof("server"), 0, (struct sockaddr *)&peeraddr, sizeof peeraddr); 33 | } 34 | 35 | void do_login(MESSAGE msg, int sock, struct sockaddr_in cliaddr) 36 | { 37 | // cout << "do_login" << endl; 38 | USER_INFO user; 39 | strcpy(user.username, msg.body); 40 | user.ip = cliaddr.sin_addr.s_addr; 41 | user.port = cliaddr.sin_port; 42 | 43 | /* 查找用户 */ 44 | USER_LIST::iterator it; 45 | for (it = client_list.begin(); it != client_list.end(); ++it) 46 | { 47 | if (strcmp(it->username, msg.body) == 0) 48 | { 49 | break; 50 | } 51 | } 52 | 53 | // 未找到用户 54 | if (it == client_list.end()) 55 | { 56 | printf("has a user login: %s <-> %s:%d\n", msg.body, inet_ntoa(cliaddr.sin_addr), cliaddr.sin_port); 57 | client_list.push_back(user); 58 | 59 | // 登录成功应答 60 | MESSAGE reply_msg; 61 | memset(&reply_msg, 0, sizeof(reply_msg)); 62 | reply_msg.cmd = htons(S2C_LOGIN_OK); 63 | sendto(sock, &msg, sizeof(msg), 0, (struct sockaddr *)&cliaddr, sizeof cliaddr); 64 | 65 | int count = htons((int)client_list.size()); 66 | // 发送在线人数 67 | sendto(sock, &count, sizeof(int), 0, (struct sockaddr*)&cliaddr, sizeof cliaddr); 68 | 69 | printf("sending user list information to: %s <-> %s:%d\n", msg.body, inet_ntoa(cliaddr.sin_addr), cliaddr.sin_port); 70 | // 发送在线列表 71 | for (it = client_list.begin(); it != client_list.end(); ++it) 72 | { 73 | sendto(sock, &*it, sizeof(USER_INFO), 0, (struct sockaddr*)&cliaddr, sizeof cliaddr); 74 | } 75 | 76 | // 向其他用户通知有新用户登录 77 | for (it = client_list.begin(); it != client_list.end(); ++it) 78 | { 79 | if (strcmp(it->username, msg.body) == 0) // 如果是当前用户,则跳过 80 | { 81 | continue; 82 | } 83 | 84 | struct sockaddr_in peeraddr; 85 | memset(&peeraddr, 0, sizeof peeraddr); 86 | peeraddr.sin_family = AF_INET; 87 | peeraddr.sin_port = it->port; 88 | peeraddr.sin_addr.s_addr = it->ip; 89 | 90 | msg.cmd = htons(S2C_SOMEONE_LOGIN); 91 | memcpy(msg.body, &user, sizeof(user)); 92 | 93 | if (sendto(sock, &msg, sizeof(msg), 0, (struct sockaddr*)&peeraddr, sizeof peeraddr) < 0) 94 | { 95 | ERR_EXIT("sendto"); 96 | } 97 | } 98 | 99 | } 100 | else // 找到该用户 fixme[如果找到该用户之后还有其他操作吗?] 101 | { 102 | printf("user %s has already logined\n", msg.body); 103 | 104 | MESSAGE reply_msg; 105 | memset(&reply_msg, 0, sizeof(MESSAGE)); 106 | reply_msg.cmd = htons(S2C_ALREADY_LOGINED); 107 | // int a = ntohs(reply_msg.cmd); 108 | sendto(sock, &reply_msg, sizeof(MESSAGE), 0, (struct sockaddr*)&cliaddr, sizeof cliaddr); 109 | } 110 | } 111 | 112 | void do_logout(MESSAGE msg, int sock, struct sockaddr_in cliaddr) 113 | { 114 | //cout << "do_logout" << endl; 115 | printf("has a user logout : %s <-> %s:%d\n", msg.body, inet_ntoa(cliaddr.sin_addr), cliaddr.sin_port); 116 | 117 | USER_LIST::iterator it; 118 | for (it = client_list.begin(); it != client_list.end(); ++it) 119 | { 120 | if (strcmp(it->username, msg.body) == 0) 121 | { 122 | break; 123 | } 124 | } 125 | 126 | if (it != client_list.end()) 127 | { 128 | client_list.erase(it); 129 | } 130 | 131 | // 向其他用户通知有用户退出 132 | for (it = client_list.begin(); it != client_list.end(); ++it) 133 | { 134 | if (strcmp(it->username, msg.body) == 0) 135 | { 136 | continue; 137 | } 138 | struct sockaddr_in peeraddr; 139 | memset(&peeraddr, 0, sizeof peeraddr); 140 | peeraddr.sin_family = AF_INET; 141 | peeraddr.sin_addr.s_addr = it->ip; 142 | peeraddr.sin_port = it->port; 143 | 144 | MESSAGE m; 145 | strcpy(m.body, msg.body); 146 | m.cmd = S2C_SOMEONE_LOGOUT; 147 | if (sendto(sock, &m, sizeof(MESSAGE), 0, (struct sockaddr*)&peeraddr, sizeof(peeraddr)) < 0) 148 | { 149 | ERR_EXIT("sendto"); 150 | } 151 | } 152 | } 153 | 154 | void do_sendlist(int sock, struct sockaddr_in cliaddr) 155 | { 156 | //cout << "do_sendlist" << endl; 157 | MESSAGE msg; 158 | msg.cmd = htons(S2C_ONLINE_USER); 159 | sendto(sock, (const char*)&msg, sizeof(msg), 0, (struct sockaddr*)&cliaddr, sizeof cliaddr); 160 | 161 | int count = htons((int)client_list.size()); 162 | /* 发送在线用户数 */ 163 | sendto(sock, (const char*)&count, sizeof (int), 0, (struct sockaddr*)&cliaddr, sizeof cliaddr); 164 | /* 发送在线用户列表 */ 165 | for (USER_LIST::iterator it = client_list.begin(); it != client_list.end(); ++it) 166 | { 167 | sendto(sock, &*it, sizeof(USER_INFO), 0, (struct sockaddr*)&cliaddr, sizeof cliaddr); 168 | } 169 | } 170 | 171 | void chat_srv(int sock) 172 | { 173 | struct sockaddr_in cliaddr; 174 | socklen_t clilen; 175 | int n; 176 | MESSAGE msg; 177 | while (1) 178 | { 179 | memset(&msg, 0, sizeof(msg)); 180 | clilen = sizeof cliaddr; 181 | n = recvfrom(sock, &msg, sizeof(msg), 0, (struct sockaddr *)&cliaddr, &clilen); 182 | if (n == -1) 183 | { 184 | if (errno == EINTR) 185 | { 186 | continue; 187 | } 188 | ERR_EXIT("recvfrom") 189 | } 190 | 191 | int cmd = ntohs(msg.cmd); 192 | switch (cmd) 193 | { 194 | case C2S_LOGIN: 195 | do_login(msg, sock, cliaddr); 196 | break; 197 | case C2S_LOGOUT: 198 | do_logout(msg, sock, cliaddr); 199 | break; 200 | case C2S_ONLINE_USER: 201 | do_sendlist(sock, cliaddr); 202 | break; 203 | default: 204 | break; 205 | } 206 | } 207 | close(sock); 208 | }; 209 | 210 | int main(void) 211 | { 212 | int sock; 213 | if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) 214 | { 215 | ERR_EXIT("socket"); 216 | } 217 | struct sockaddr_in servaddr; 218 | memset(&servaddr, 0, sizeof servaddr); 219 | servaddr.sin_family = PF_INET; 220 | servaddr.sin_port = htons(6666); 221 | servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 222 | 223 | if (bind(sock, (struct sockaddr *)&servaddr, sizeof servaddr) < 0) 224 | { 225 | ERR_EXIT("bind"); 226 | } 227 | 228 | chat_srv(sock); 229 | 230 | return 0; 231 | } 232 | -------------------------------------------------------------------------------- /udpcli.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-8. 3 | // 4 | 5 | // socket编程 13 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include /* See NOTES */ 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | using namespace std; 19 | 20 | #define ERR_EXIT(m) \ 21 | do \ 22 | { \ 23 | perror(m); \ 24 | exit(EXIT_FAILURE); \ 25 | } while (0); 26 | 27 | int main(void) 28 | { 29 | int sock; 30 | if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) 31 | { 32 | ERR_EXIT("socket"); 33 | } 34 | 35 | struct sockaddr_in server_addr; 36 | int srvlen; 37 | memset(&server_addr, 0, sizeof server_addr); 38 | server_addr.sin_family = AF_INET; 39 | server_addr.sin_port = htons(6666); 40 | server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 41 | 42 | struct sockaddr_in localaddr; 43 | socklen_t addrlen = sizeof localaddr; 44 | if (getsockname(sock, (struct sockaddr*)&localaddr, &addrlen) < 0) 45 | { 46 | ERR_EXIT("getsockname"); 47 | } 48 | printf("id = %s, ", inet_ntoa(localaddr.sin_addr)); 49 | printf("port = %d\n", ntohs(localaddr.sin_port)); 50 | 51 | char sendbuf[1024]; 52 | int ret; 53 | char recvbuf[1024]; 54 | while (fgets(sendbuf, sizeof sendbuf, stdin) != NULL) 55 | { 56 | srvlen = sizeof server_addr; 57 | sendto(sock, sendbuf, sizeof(sendbuf), 0, (struct sockaddr *)&server_addr, srvlen); 58 | // cout << sendbuf << endl; 59 | ret = recvfrom(sock, recvbuf, sizeof(recvbuf), 0, NULL, NULL); 60 | if (ret == -1) 61 | { 62 | if (errno == EINTR) 63 | { 64 | continue; 65 | } 66 | ERR_EXIT("recvfrom") 67 | } 68 | else if (ret > 0) 69 | { 70 | fputs(recvbuf, stdout); 71 | // sendto(sock, recvbuf, n, 0, (struct sockaddr *)&peeraddr, peerlen); 72 | } 73 | memset(sendbuf, 0, sizeof sendbuf); 74 | memset(recvbuf, 0, sizeof recvbuf); 75 | } 76 | 77 | return 0; 78 | } -------------------------------------------------------------------------------- /udpmulclt.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-8. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | // 名字长度包含'\0' 18 | #define _INT_NAME (64) 19 | // 报文最大长度,包含'\0' 20 | #define _INT_TEXT (512) 21 | 22 | //4.0 控制台打印错误信息, fmt必须是双引号括起来的宏 23 | #define CERR(fmt, ...) \ 24 | fprintf(stderr,"[%s:%s:%d][error %d:%s]" fmt "\r\n",\ 25 | __FILE__, __func__, __LINE__, errno, strerror(errno),##__VA_ARGS__) 26 | 27 | //4.1 控制台打印错误信息并退出, t同样fmt必须是 ""括起来的字符串常量 28 | #define CERR_EXIT(fmt,...) \ 29 | CERR(fmt,##__VA_ARGS__),exit(EXIT_FAILURE) 30 | /* 31 | * 简单的Linux上API错误判断检测宏, 好用值得使用 32 | */ 33 | #define IF_CHECK(code) \ 34 | if((code) < 0) \ 35 | CERR_EXIT(#code) 36 | 37 | // 发送和接收的信息体 38 | struct umsg{ 39 | char type; //协议 '1' => 向服务器发送名字, '2' => 向服务器发送信息, '3' => 向服务器发送退出信息 40 | char name[_INT_NAME]; //保存用户名字 41 | char text[_INT_TEXT]; //得到文本信息,空间换时间 42 | }; 43 | 44 | /* 45 | * udp聊天室的客户端, 子进程发送信息,父进程接受信息 46 | */ 47 | int main(int argc, char* argv[]) { 48 | int sd, rt; 49 | struct sockaddr_in addr = { AF_INET }; 50 | socklen_t alen = sizeof addr; 51 | pid_t pid; 52 | struct umsg msg = { '1' }; 53 | 54 | // 这里简单检测 55 | if(argc != 4) { 56 | fprintf(stderr, "uage : %s [ip] [port] [name]\n", argv[0]); 57 | exit(-1); 58 | } 59 | // 下面对接数据 60 | if((rt = atoi(argv[2]))<1024 || rt > 65535) 61 | CERR("atoi port = %s is error!", argv[2]); 62 | // 接着判断ip数据 63 | IF_CHECK(inet_aton(argv[1], &addr.sin_addr)); 64 | addr.sin_port = htons(rt); 65 | // 这里拼接用户名字 66 | strncpy(msg.name, argv[3], _INT_NAME - 1); 67 | 68 | //创建socket 连接 69 | IF_CHECK(sd = socket(PF_INET, SOCK_DGRAM, 0)); 70 | // 这里就是发送登录信息给udp聊天服务器了 71 | IF_CHECK(sendto(sd, &msg, sizeof msg, 0, (struct sockaddr*)&addr, alen)); 72 | 73 | //开启一个进程, 子进程处理发送信息, 父进程接收信息 74 | IF_CHECK(pid = fork()); 75 | if(pid == 0) { //子进程,先忽略退出处理防止成为僵尸进程 76 | signal(SIGCHLD, SIG_IGN); 77 | while(fgets(msg.text, _INT_TEXT, stdin)){ 78 | if(strcasecmp(msg.text, "quit\n") == 0){ //表示退出 79 | msg.type = '3'; 80 | // 发送数据并检测 81 | IF_CHECK(sendto(sd, &msg, sizeof msg, 0, (struct sockaddr*)&addr, alen)); 82 | break; 83 | } 84 | // 洗唛按发送普通信息 85 | msg.type = '2'; 86 | IF_CHECK(sendto(sd, &msg, sizeof msg, 0, (struct sockaddr*)&addr, alen)); 87 | } 88 | // 处理结算操作,并杀死父进程 89 | close(sd); 90 | kill(getppid(), SIGKILL); 91 | exit(0); 92 | } 93 | // 这里是父进程处理数据的读取 94 | for(;;){ 95 | bzero(&msg, sizeof msg); 96 | IF_CHECK(recvfrom(sd, &msg, sizeof msg, 0, (struct sockaddr*)&addr, &alen)); 97 | msg.name[_INT_NAME-1] = msg.text[_INT_TEXT-1] = '\0'; 98 | switch(msg.type){ 99 | case '1':printf("%s 登录了聊天室!\n", msg.name);break; 100 | case '2':printf("%s 说了: %s\n", msg.name, msg.text);break; 101 | case '3':printf("%s 退出了聊天室!\n", msg.name);break; 102 | default://未识别的异常报文,程序直接退出 103 | fprintf(stderr, "msg is error! [%s:%d] => [%c:%s:%s]\n", inet_ntoa(addr.sin_addr), 104 | ntohs(addr.sin_port), msg.type, msg.name, msg.text); 105 | goto __exit; 106 | } 107 | } 108 | 109 | __exit: 110 | // 杀死并等待子进程退出 111 | close(sd); 112 | kill(pid, SIGKILL); 113 | waitpid(pid, NULL, -1); 114 | 115 | return 0; 116 | } -------------------------------------------------------------------------------- /udpmulsrv.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-8. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #define _SHORT_PORT (8088) 13 | 14 | // 15 | // udp server heoo 16 | // 17 | 18 | void test(int sock, struct sockaddr_in peeraddr, char* recvbuf, int len, int al) 19 | { 20 | //sendto(sock, "server", sizeof("server"), 0, (struct sockaddr *)&peeraddr, sizeof peeraddr); 21 | //sendto(sock, recvbuf, n, 0, (struct sockaddr *)&peeraddr, sizeof peeraddr); 22 | sendto(sock, recvbuf, len, 0, (struct sockaddr *)&peeraddr, al); 23 | } 24 | 25 | int main(int argc, char * argv[]) { 26 | int fd, len; 27 | struct sockaddr_in ar = { AF_INET }; 28 | socklen_t al = sizeof (struct sockaddr_in); 29 | char msg[BUFSIZ]; 30 | 31 | if ((fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { 32 | perror("main socket dgram"); 33 | exit(EXIT_FAILURE); 34 | } 35 | 36 | printf("udp server start [%d][0.0.0.0][%hd] ...\n", fd, _SHORT_PORT); 37 | 38 | // 服务器绑定地址 39 | ar.sin_port = htons(_SHORT_PORT); 40 | if (bind(fd, (struct sockaddr *)&ar, al) == -1) { 41 | perror("main bind INADDR_ANY"); 42 | exit(EXIT_FAILURE); 43 | } 44 | 45 | // 阻塞的接收不同客户端数据来回搞 46 | while ((len = recvfrom(fd, msg, sizeof msg - 1, 0, (struct sockaddr *)&ar, &al)) > 0) { 47 | msg[len] = '\0'; 48 | printf("[%s:%hd] -> %s\n", inet_ntoa(ar.sin_addr), ntohs(ar.sin_port), msg); 49 | 50 | // 回显继续发送给客户端 51 | // sendto(fd, msg, len, 0, (struct sockaddr *)&ar, al); 52 | test(fd, ar, msg, len, al); 53 | } 54 | 55 | return close(fd); 56 | } -------------------------------------------------------------------------------- /udpsrv.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-8. 3 | // 4 | 5 | // socket编程 13 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include /* See NOTES */ 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #define ERR_EXIT(m) \ 19 | do \ 20 | { \ 21 | perror(m); \ 22 | exit(EXIT_FAILURE); \ 23 | } while (0); 24 | 25 | void test(int sock, struct sockaddr_in* peeraddr, char* recvbuf, int n) 26 | { 27 | //sendto(sock, "server", sizeof("server"), 0, (struct sockaddr *)&peeraddr, sizeof peeraddr); 28 | sendto(sock, recvbuf, n, 0, (struct sockaddr *)&peeraddr, sizeof peeraddr); 29 | } 30 | void echo_srv(int sock) 31 | { 32 | char recvbuf[1024] = {0}; 33 | struct sockaddr_in peeraddr; 34 | socklen_t peerlen; 35 | int n; 36 | while (1) 37 | { 38 | peerlen = sizeof peeraddr; 39 | memset(recvbuf, 0, sizeof recvbuf); 40 | n = recvfrom(sock, recvbuf, sizeof(recvbuf), 0, (struct sockaddr *)&peeraddr, &peerlen); 41 | printf("id = %s, ", inet_ntoa(peeraddr.sin_addr)); 42 | printf("port = %d\n", ntohs(peeraddr.sin_port)); 43 | if (n == -1) 44 | { 45 | if (errno == EINTR) 46 | { 47 | continue; 48 | } 49 | ERR_EXIT("recvfrom") 50 | } 51 | else if (n > 0) 52 | { 53 | fputs(recvbuf, stdout); 54 | //sendto(sock, recvbuf, n, 0, (struct sockaddr *)&peeraddr, peerlen); 55 | //sendto(sock, "h", sizeof("h"), 0, (struct sockaddr *)&peeraddr, sizeof peeraddr); 56 | test(sock, &peeraddr, recvbuf, n); 57 | } 58 | } 59 | close(sock); 60 | }; 61 | 62 | int main(void) 63 | { 64 | int sock; 65 | if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) 66 | { 67 | ERR_EXIT("socket"); 68 | } 69 | struct sockaddr_in servaddr; 70 | memset(&servaddr, 0, sizeof servaddr); 71 | servaddr.sin_family = PF_INET; 72 | servaddr.sin_port = htons(6666); 73 | servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 74 | 75 | if (bind(sock, (struct sockaddr *)&servaddr, sizeof servaddr) < 0) 76 | { 77 | ERR_EXIT("bind"); 78 | } 79 | 80 | echo_srv(sock); 81 | 82 | return 0; 83 | } -------------------------------------------------------------------------------- /unixcli.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-10. 3 | // 4 | 5 | // socket编程 16 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | using namespace std; 16 | 17 | #define ERR_EXIT(m) \ 18 | do \ 19 | { \ 20 | perror(m); \ 21 | exit(EXIT_FAILURE); \ 22 | } while(0); 23 | 24 | 25 | void clisrv(int sock) 26 | { 27 | char sendbuf[1024]; 28 | char recvbuf[1024]; 29 | memset(recvbuf, 0, sizeof(recvbuf)); 30 | memset(sendbuf, 0, sizeof(sendbuf)); 31 | while (fgets(sendbuf, sizeof sendbuf, stdin) != NULL) 32 | { 33 | if (write(sock, sendbuf, sizeof(sendbuf)) < 0) 34 | { 35 | ERR_EXIT("write"); 36 | } 37 | int ret; 38 | if ((ret = read(sock, &recvbuf, sizeof recvbuf)) < 0) 39 | { 40 | ERR_EXIT("read"); 41 | } 42 | if (ret == 0) 43 | { 44 | printf("server close\n"); 45 | break; 46 | } 47 | fputs(recvbuf, stdout); 48 | memset(recvbuf, 0, sizeof(recvbuf)); 49 | memset(sendbuf, 0, sizeof(sendbuf)); 50 | } 51 | } 52 | 53 | 54 | int main(int argc, char** argv) 55 | { 56 | int clientfd; 57 | if ((clientfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) 58 | { 59 | ERR_EXIT("sokcet"); 60 | } 61 | 62 | struct sockaddr_un cliaddr; 63 | cliaddr.sun_family = AF_UNIX; 64 | strcpy(cliaddr.sun_path, "/home/jxq/CLionProjects/NetworkProgramming/text_unix"); 65 | 66 | int conn; 67 | if ((conn = connect(clientfd, (struct sockaddr*)&cliaddr, sizeof(cliaddr))) < 0) 68 | { 69 | ERR_EXIT("connect"); 70 | } 71 | 72 | clisrv(clientfd); 73 | 74 | 75 | return 0; 76 | } -------------------------------------------------------------------------------- /unixsrv.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by jxq on 19-8-10. 3 | // 4 | 5 | // socket编程 16 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | using namespace std; 16 | 17 | #define ERR_EXIT(m) \ 18 | do \ 19 | { \ 20 | perror(m); \ 21 | exit(EXIT_FAILURE); \ 22 | } while(0); 23 | 24 | 25 | void echosrv(int clientfd) 26 | { 27 | char recvbuf[1024]; 28 | while (1) { 29 | memset(recvbuf, 0, sizeof recvbuf); 30 | int ret; 31 | if ((ret = read(clientfd, recvbuf, sizeof(recvbuf))) < 0) { 32 | ERR_EXIT("read"); 33 | } 34 | if (ret == 0) { 35 | printf("client close\n"); 36 | break; 37 | } 38 | fputs(recvbuf, stdout); 39 | write(clientfd, &recvbuf, strlen(recvbuf)); 40 | } 41 | close(clientfd); 42 | } 43 | 44 | int main(int argc, char** argv) 45 | { 46 | int listenfd; 47 | 48 | unlink("/home/jxq/CLionProjects/NetworkProgramming/text_unix"); // 解除原有text_unix对象链接 49 | if ((listenfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) 50 | { 51 | ERR_EXIT("socket"); 52 | } 53 | 54 | struct sockaddr_un servaddr; 55 | servaddr.sun_family = AF_UNIX; 56 | strcpy(servaddr.sun_path, "/home/jxq/CLionProjects/NetworkProgramming/text_unix"); 57 | 58 | if (bind(listenfd, (struct sockaddr*)&servaddr, sizeof servaddr) < 0) 59 | { 60 | ERR_EXIT("bind"); 61 | } 62 | 63 | if (listen(listenfd, SOMAXCONN) < 0) 64 | { 65 | ERR_EXIT("listen"); 66 | } 67 | 68 | struct sockaddr_un cliaddr; 69 | socklen_t clilen; 70 | int clientfd; 71 | while (1) 72 | { 73 | if ((clientfd = accept(listenfd, (struct sockaddr*)&cliaddr, &clilen)) < 0) 74 | { 75 | ERR_EXIT("accept"); 76 | } 77 | echosrv(clientfd); 78 | } 79 | close(listenfd); 80 | 81 | return 0; 82 | } --------------------------------------------------------------------------------