├── FIFO ├── client.c └── server.c ├── Makefile ├── README.md ├── dup_dup2.c ├── exec ├── Makefile ├── com.c └── exec.c ├── fork_vfork ├── different of fork and vfork.txt ├── fork.c └── vfork.c ├── httpd ├── Makefile ├── database │ ├── database.cpp │ └── database.h ├── htdocs │ ├── check.cgi │ ├── color.cgi │ ├── index.html │ └── index.html~ ├── memc │ ├── memc.cpp │ └── memc.h ├── server │ ├── httpd.cpp │ └── httpd.h └── sock │ ├── sock.cpp │ └── sock.h ├── msg ├── Makefile ├── client.c ├── msgqueue.c ├── msgqueue.h └── server.c ├── my ├── 5class │ ├── UDP │ │ ├── Makefile │ │ ├── udp_client │ │ ├── udp_client.c │ │ ├── udp_server │ │ └── udp_server.c │ ├── alarm │ │ ├── Makefile │ │ └── alarm.c │ ├── awk │ │ ├── Count_capacity.awk │ │ ├── file │ │ └── test.awk │ ├── daemon │ │ ├── Makefile │ │ ├── daemon.c │ │ └── daemon.out │ ├── dup │ │ ├── Makefile │ │ ├── my_dup │ │ └── my_dup.c │ ├── epoll │ │ ├── Makefile │ │ ├── client.sh │ │ ├── epoll_client.c │ │ ├── epoll_http │ │ │ ├── Makefile │ │ │ ├── client.sh │ │ │ ├── epoll_client │ │ │ ├── epoll_client.c │ │ │ ├── epoll_server │ │ │ ├── epoll_server.c │ │ │ └── server.sh │ │ ├── epoll_server.c │ │ └── server.sh │ ├── hold_pattern │ │ └── file │ ├── httpd │ │ ├── Makefile │ │ ├── client.c │ │ ├── client.h │ │ ├── httpd.c │ │ ├── httpd.h │ │ └── server.c │ ├── kill │ │ └── kill_myself.c │ ├── mask_pending │ │ ├── Makefile │ │ ├── ke_chong_ru │ │ ├── ke_chong_ru.c │ │ ├── mask.c │ │ ├── mask.out │ │ ├── sighandler │ │ ├── sighandler.c │ │ ├── sleep │ │ └── sleep.c │ ├── poll │ │ ├── Makefile │ │ └── my_poll.c │ ├── raise │ │ └── raise.c │ ├── regular │ │ └── rule │ ├── schedul │ │ └── schedul.sh │ ├── sed │ │ ├── file │ │ └── test.sed │ ├── select │ │ ├── Makefile │ │ ├── my_select.c │ │ └── select_tcp │ │ │ ├── Makefile │ │ │ ├── select_client │ │ │ ├── select_client.c │ │ │ ├── select_server │ │ │ ├── select_server.c │ │ │ ├── start_client.sh │ │ │ └── start_server.sh │ ├── shell │ │ ├── array │ │ │ ├── array.sh │ │ │ ├── fabo.sh │ │ │ ├── max_min.sh │ │ │ └── sum.sh │ │ ├── basic │ │ │ └── shell1 │ │ ├── fun │ │ │ └── func.sh │ │ ├── mk_dir │ │ │ └── mk_dir.sh │ │ ├── other │ │ │ └── other.sh │ │ ├── passwd │ │ │ └── passwd.sh │ │ ├── process │ │ │ ├── add.c │ │ │ └── file.c │ │ ├── string │ │ │ ├── file │ │ │ ├── log │ │ │ └── string.sh │ │ ├── test │ │ │ └── test.sh │ │ └── while │ │ │ └── while.sh │ ├── socket │ │ ├── Makefile │ │ ├── client │ │ ├── client.c │ │ ├── main.c │ │ ├── server │ │ └── server.c │ ├── socketpair │ │ ├── Makefile │ │ └── my_socketpair.c │ └── tty │ │ └── tty.c └── 6class │ ├── FILE │ ├── Makefile │ ├── dup_dup2.c │ ├── file_fd.c │ ├── file_fd.out │ └── log │ ├── Gdb │ └── SeqList.cpp │ ├── c_schedul │ ├── a.out │ ├── main.c │ ├── main.out │ ├── main1.c │ └── main1.out │ ├── ctags │ ├── main.c │ ├── main.c~ │ ├── my_test.c │ ├── my_test.h │ └── tags │ ├── exec │ ├── Makefile │ ├── bin │ │ ├── Makefile │ │ ├── com.c │ │ └── com.out │ ├── exec.c │ └── exec.out │ ├── fifo │ ├── Makefile │ ├── client │ ├── client.c │ ├── server │ └── server.c │ ├── fork │ ├── Makefile │ ├── errno.c │ ├── errno.out │ ├── file │ ├── fork.c │ ├── vfork │ └── vfork.c │ ├── id │ ├── Makefile │ ├── id.c │ ├── id.out │ ├── log │ ├── read_write.c │ └── read_write.out │ ├── makefile │ ├── Makefile │ └── test.c │ ├── makefile1 │ ├── make1 │ │ ├── Makefile │ │ └── test.c │ └── make2 │ │ ├── main.c │ │ ├── makefile │ │ ├── proc.c │ │ └── proc.h │ └── msg │ ├── Makefile │ ├── client │ └── client.c ├── my_socketpair.c ├── pipe.c ├── pthread ├── Condition Variable(条件变量) │ ├── Makefile │ └── cond_mutex.c └── 线程终止 │ ├── Makefile │ └── pthread.c ├── schedul_Shell.sh ├── sem ├── Makefile ├── my_sem.c ├── my_sem.h ├── 父子进程互斥访问stdout │ ├── Makefile │ ├── lib │ │ ├── libmy_sem.a │ │ └── my_sem.h │ └── sem_stdout.c └── 生成的静态库lib │ ├── libmy_sem.a │ └── my_sem.h ├── shm ├── Makefile ├── shm_client.c ├── shm_comm.c ├── shm_comm.h └── shm_server.c ├── wait and waitpid ├── different of wait and waitpid.txt ├── mywait.c ├── wait.c └── waitpid.c └── 多路复用之select、poll、epoll ├── my_epoll ├── Makefile ├── client.sh ├── epoll_client.c ├── epoll_server.c └── server.sh ├── my_poll.c └── my_select ├── Makefile ├── select_client.c └── select_server.c /FIFO/client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | int main() 7 | { 8 | int fd = open("fifo_pipe",O_WRONLY,0);//以只写的方式打开 9 | if(fd < 0){ 10 | perror("error"); 11 | return 2; 12 | } 13 | char buf[1024]; 14 | while(1){ 15 | printf("client Enter :"); 16 | fflush(stdout); 17 | memset(buf,'\0',sizeof(buf)); 18 | fgets(buf,sizeof(buf)-1,stdin); 19 | buf[strlen(buf)-1] = '\0'; 20 | write(fd,buf,strlen(buf)); 21 | if(strcasecmp(buf,"Quit") == 0){//忽略大小写 22 | break; 23 | } 24 | } 25 | close(fd); 26 | printf("client Quit\n"); 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /FIFO/server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | int main() 7 | { 8 | if(mkfifo("/home/xiaoxiaosu/class/6class/fifo/fifo_pipe",0666|S_IFIFO) < 0){ 9 | perror("error"); 10 | return 1; 11 | } 12 | int fd = open("fifo_pipe",O_RDONLY,0);//以只读的方式打开命名管道 13 | printf("open file success\n"); 14 | if(fd < 0){ 15 | perror("error"); 16 | } 17 | char buf[1024]; 18 | while(1){ 19 | memset(buf,'\0',sizeof(buf)); 20 | int len = read(fd,buf,sizeof(buf)-1); 21 | if(len > 0){ 22 | printf("client say : %s\n",buf); 23 | } 24 | if(strcasecmp("Quit",buf) == 0){//忽略大小写的quit 25 | break; 26 | } 27 | } 28 | close(fd); 29 | printf("server Quit\n"); 30 | return 0; 31 | } 32 | 33 | 34 | //本人博客对于pipe和FIFO分析及区别有更详细的说明 35 | //见:http://blog.csdn.net/SuLiJuan66/article/details/50588885 -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | #方法一:分步生成可执行文件 2 | test:test.o 3 | gcc -o test test.o 4 | test.o:test.s 5 | gcc -c test.s -o test.o 6 | test.s:test.i 7 | gcc -S test.i -o test.s 8 | test.i:test.c 9 | gcc -E test.c -o test.i 10 | .PHONY:clean 11 | clean: 12 | rm -rf test.o test.s test.i 13 | 14 | #方法二:一步生成可执行文件 15 | test:test.c 16 | gcc -o test test.c 17 | .PHONY:clean 18 | clean: 19 | rm -rf test 20 | 21 | #方法三:通过定义变量生成可执行文件 22 | SOU=test 23 | DST=test.c 24 | CC=gcc 25 | FLAGS=#-static #编写线程时候:FLAGS=-lpthread 26 | 27 | $(SOU):$(DST) 28 | gcc -o $@ $^ $(FLAGS) 29 | .PHONY:clean 30 | clean: 31 | rm -rf $(SOU) 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # _Linux-OS-Network_ 2 | 系统编程:Makefile的编写、进程线程区别以及控制、生产者消费者模型、System V标准和POSIX标准中的IPC间通信、简单Shell脚本的编写;网络编程:基于TCP/UDP的客户端/服务器、socket、高级I/O、select/poll/epoll、Http协议 3 | -------------------------------------------------------------------------------- /dup_dup2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #define OPEN_FILE "./log" 8 | 9 | int main() 10 | { 11 | //close(1);//stdout is closing 12 | //FILE *f_p = fopen(OPEN_FILE, "w+");//read,write,create 13 | //if( NULL == f_p ){ 14 | // perror("fopen"); 15 | // return 1; 16 | //} 17 | int fd = open(OPEN_FILE, O_RDWR | O_CREAT, 0666); 18 | if( fd < 0 ){ 19 | perror("open"); 20 | return 1; 21 | } 22 | printf("dup begin : %d\n",fd); 23 | //------dup()----- 24 | //close(1); //需要手动关闭为呢见描述符 25 | //system calls create a copy of the file descriptor oldfd. 26 | //dup() uses the lowest-numbered unused descriptor for the new descriptor. 27 | //int new_fd = dup(fd); 28 | 29 | //-----dup2()------ 30 | int new_fd = dup2(fd, 1);//不许要手动关闭文件描述符号 31 | 32 | printf("dup end : new : %d, old : %d\n",new_fd,fd); 33 | int count = 10; 34 | while(count){ 35 | printf("hello world ; %d\n",count); 36 | count--; 37 | } 38 | fflush(stdout);//重定向到文件就由行缓冲变成满缓冲,所以得刷新 39 | //fclose(f_p); 40 | close(fd); 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /exec/Makefile: -------------------------------------------------------------------------------- 1 | DST:exec 2 | SOU:exec.c 3 | 4 | $(DST):$(SOU) 5 | gcc -o $@ $^ 6 | .PHONY:clean 7 | clean: 8 | rm -rf $(DST) 9 | -------------------------------------------------------------------------------- /exec/com.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | int main() 6 | { 7 | //putenv("PATH=bin/com"); 8 | printf("pid:%d,ppid:%d\n",getpid(),getppid()); 9 | printf("get PATH : %s\n",getenv("PATH"));//获取环境变量 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /exec/exec.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | int main(int argc,char* argv[]) 5 | { 6 | pid_t id = fork(); 7 | if(id == 0){ 8 | execl("/bin/ls","ls","-al","../exec",NULL);//如果execl函数执行成功,就不会执行printf语句,没有返回 9 | 10 | execlp("com.out","com.out",NULL);//将从根目录起到当前文件的路径如/home/xiaoxiaosu/class/6class/exec/bin(com.out在bin目录底下)添加到PATH即可,函数名带p,表示运行时在环境变量下查找适用路径 11 | //execlp(argv[1],argv[1],argv[2],NULL);//通过命令行传参数 12 | 13 | char* argv[] = {"ls","-al","./bin",NULL}; 14 | char* my_env[] = {"PATH=/I/AM/PATH",NULL}; 15 | execle("/home/xiaoxiaosu/class/6class/exec/bin/com.out","com.out",NULL,my_env); 16 | //execle("/bin/ls","ls","-al","./bin",my_env,NULL); 17 | 18 | execv("/bin/ls",argv); 19 | 20 | execvp("/bin/ls",argv); 21 | execve("/bin/ls",argv,my_env); 22 | 23 | printf("haha,I am here...\n");//当execl执行错误才会输出这条语句 24 | perror("error"); 25 | exit(0); 26 | }else{ 27 | wait(NULL); 28 | } 29 | return 0; 30 | } 31 | 32 | //以上主函数中的execl、execlp、execle、execv、execvp、execve函数不能同存 33 | 34 | 35 | (1)不带字母p (表示path)的exec函数 第一个参数必须是程序的相对路径或绝对路径,例如 36 | "/bin/ls"或"./a.out",而不能 是"ls"或"a.out"。对于带字母p的函数: 如果参数中包含/,则 37 | 将其视为路径名。 否则视为不带路径的程序名,在PATH环境变量的目录列表中搜索这 38 | 个程序。 39 | (2)带有字母l( 表示list)的exec函数要求将新程序的每个命令行参数都当作一个参数传给 40 | 它,命令行 参数的个数是可变的,因此函数原型中有...,...中的最后一个可变参数应该是 41 | NULL, 起sentinel的作用。 42 | (3)带有字母v( 表示vector)的函数,则应该先构造一个指向各参数的指针数 组,然后将该数 43 | 组的首地址当作参数传给它,数组中的最后一个指针也应该是NULL,就像main函数 的 44 | argv参数或者环境变量表一样。 45 | (4)对于以e (表示environment)结尾的exec函数,可以把一份新的环境变量表传给它,其他 46 | exec函数仍使用当前的环境变量表执行新程序。 -------------------------------------------------------------------------------- /fork_vfork/different of fork and vfork.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoxiao-su/_Linux-OS-Network_/a561603918e0bd1fc57a5fb1f0b980fe5227a2de/fork_vfork/different of fork and vfork.txt -------------------------------------------------------------------------------- /fork_vfork/fork.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | 9 | char *msg = "hello bit"; 10 | 11 | int g_val = 0;//父子进程看起来像是共享同一全局变量,实则并非如此 12 | 13 | int main() 14 | { 15 | 16 | printf("%s\n",msg); 17 | 18 | int val = 0; 19 | 20 | printf("uid:%d,euid:%d,gid:%d,egid:%d\n",getuid(),geteuid(),getgid(),getegid()); 21 | 22 | pid_t id = fork(); 23 | 24 | if(id < 0){ 25 | 26 | printf("fork error\n"); 27 | 28 | exit(1); 29 | 30 | }else if(id == 0){ 31 | 32 | val++; 33 | 34 | g_val++; 35 | 36 | printf("child:pid:%d,ppid:%d,val:%d,&val:0x%x,g_val:%d,&g_val:0x%x\n", 37 | getpid(),getppid(),val,&val,g_val,&g_val); 38 | 39 | }else{ 40 | 41 | sleep(1); 42 | 43 | printf("father:pid:%d,ppid:%d,val:%d,&val:0x%x,g_val:%d,&g_val:0x%x\n", 44 | getpid(),getppid(),val,&val,g_val,&g_val); 45 | 46 | sleep(3); 47 | 48 | } 49 | 50 | return 0 51 | 52 | } 53 | 54 | 55 | //分析在fork前执行语句printf("%s\n",msg);重定向到文件中会出现什么结果? 56 | 57 | //gcc -o fork fork.c 后执行./fork >file,即输出重定向到文件里面,则输出缓冲由行缓冲变成全缓冲, 58 | 即子进程拥有一份缓冲区的拷贝,父进程也有一份缓冲区的拷贝,当子进程执行完return后,刷新自己的缓 59 | 冲区,当父进程return后也刷新自己的缓冲区,所以此时虽然只有一条printf语句,但是当输出重定向到文 60 | 件里面就会出现两条hello bit语句,若程序运行输出到终端上,就只会出现一条hello bit(行缓冲) 61 | -------------------------------------------------------------------------------- /fork_vfork/vfork.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | 11 | int g_val = 0;//父子进程共享一个全局变量 12 | 13 | int main() 14 | { 15 | 16 | int val = 0; 17 | 18 | pid_t id = vfork(); 19 | 20 | if(id < 0){ 21 | 22 | printf("vfork error\n"); 23 | 24 | exit(1); 25 | 26 | }else if(id == 0){ 27 | 28 | val++; 29 | 30 | sleep(2); 31 | 32 | g_val++; 33 | 34 | printf("child:pid:%d,ppid:%d,val:%d,&val:0x%x,g_val:%d,&g_val:0x%x\n", 35 | getpid(),getppid(),val,&val,g_val,&g_val); 36 | 37 | exit(0);//当子进程exec或者exit后,父进程才能执行相关操作 38 | 39 | }else{ 40 | 41 | sleep(5); 42 | 43 | printf("father:pid:%d,ppid:%d,val:%d,&val:0x%x,g_val:%d,&g_val:0x%x\n", 44 | getpid(),getppid(),val,&val,g_val,&g_val); 45 | 46 | } 47 | 48 | return 0; 49 | 50 | } 51 | 52 | 53 | -------------------------------------------------------------------------------- /httpd/Makefile: -------------------------------------------------------------------------------- 1 | ROOT_PWD=$(shell pwd) 2 | SRC=$(shell ls -R | grep -E '*.cpp') 3 | OBJ=$(SRC:.cpp=.o) 4 | 5 | DATA=$(ROOT_PWD)/database 6 | SOCK=$(ROOT_PWD)/sock 7 | MEMC=$(ROOT_PWD)/memc 8 | SERVER=$(ROOT_PWD)/server 9 | 10 | CC=g++ 11 | FLAGS=-std=c++0x 12 | LIB_PATH= -L /usr/local/lib -L /usr/lib/mysql 13 | LINK_LIB=-lboost_thread -lpthread -lmemcached -lmysqlclient 14 | INCLUDE= -I /usr/local/include -I$(DATA) -I$(SOCK) -I$(MEMC) 15 | 16 | httpd: $(OBJ) 17 | $(CC) -o $@ $^ $(LINK_LIB) $(LIB_PATH) 18 | 19 | %.o:$(SERVER)/%.cpp 20 | $(CC) -c $< $(INCLUDE) $(FLAGS) 21 | %.o:$(DATA)/%.cpp 22 | $(CC) -c $< 23 | %.o:$(SOCK)/%.cpp 24 | $(CC) -c $< 25 | %.o:$(MEMC)/%.cpp 26 | $(CC) -c $< $(FLAGS) 27 | 28 | .PHONY:clean 29 | clean: 30 | rm httpd *.o 31 | -------------------------------------------------------------------------------- /httpd/database/database.cpp: -------------------------------------------------------------------------------- 1 | #include"database.h" 2 | /************************************************/ 3 | /* query info by page_name from the database 4 | * Parameters: the buffer to save query result 5 | * the key for query 6 | * return val 0:success -1:error */ 7 | /***********************************************/ 8 | int query_database(char* page_info,char* page_name) 9 | { 10 | char sql[100] = "select page from weather where cityname="; 11 | strcat(sql, "'"); 12 | strcat(sql, page_name); 13 | strcat(sql, "'"); 14 | MYSQL my_connection; 15 | MYSQL_ROW row;// 16 | int ret; 17 | MYSQL_RES *res; 18 | mysql_init(&my_connection); 19 | if (mysql_real_connect(&my_connection, "localhost", "root", "marker", "wea", 0, NULL, 0)) 20 | { 21 | //printf("Connection database success\n"); 22 | ret = mysql_query(&my_connection, sql); 23 | if (ret != 0) 24 | { 25 | printf("query error %d: %s\n", mysql_errno(&my_connection), mysql_error(&my_connection)); 26 | mysql_close(&my_connection); 27 | return -1; 28 | } 29 | res = mysql_store_result(&my_connection); 30 | if (!res) 31 | { 32 | printf("query error %d: %s\n", mysql_errno(&my_connection), mysql_error(&my_connection)); 33 | mysql_close(&my_connection); 34 | return -1; 35 | } 36 | row = mysql_fetch_row(res);//return NULL if no more row 37 | if (row == NULL) 38 | { 39 | printf("get data from database error\n"); 40 | mysql_free_result(res); 41 | mysql_close(&my_connection); 42 | return -1; 43 | } 44 | printf("get data:<%s> from database success\n", page_name); 45 | //rc = memcached_set(memc, page_name, strlen(page_name), row[0], strlen(row[0]), (time_t)180, (uint32_t)0); 46 | // if(rc) 47 | strcpy(page_info, row[0]); 48 | mysql_free_result(res); 49 | mysql_close(&my_connection); 50 | } 51 | else 52 | { 53 | printf("connect error %d: %s\n", mysql_errno(&my_connection), mysql_error(&my_connection)); 54 | mysql_close(&my_connection); 55 | return -1; 56 | } 57 | return 0; 58 | } 59 | 60 | -------------------------------------------------------------------------------- /httpd/database/database.h: -------------------------------------------------------------------------------- 1 | #ifndef _DATABASE_ 2 | #define _DATABASE_ 3 | 4 | #include 5 | #include 6 | #include 7 | int query_database(char*,char*); 8 | #endif 9 | -------------------------------------------------------------------------------- /httpd/htdocs/check.cgi: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/perl -Tw 2 | 3 | use strict; 4 | use CGI; 5 | 6 | my($cgi) = new CGI; 7 | 8 | print $cgi->header('text/html'); 9 | print $cgi->start_html(-title => "Example CGI script", 10 | -BGCOLOR => 'red'); 11 | print $cgi->h1("CGI Example"); 12 | print $cgi->p, "This is an example of CGI\n"; 13 | print $cgi->p, "Parameters given to this script:\n"; 14 | print "
    \n"; 15 | foreach my $param ($cgi->param) 16 | { 17 | print "
  • ", "$param ", $cgi->param($param), "\n"; 18 | } 19 | print "
"; 20 | print $cgi->end_html, "\n"; 21 | -------------------------------------------------------------------------------- /httpd/htdocs/color.cgi: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/perl -Tw 2 | 3 | use strict; 4 | use CGI; 5 | 6 | my($cgi) = new CGI; 7 | 8 | print $cgi->header; 9 | my($color) = "blue"; 10 | $color = $cgi->param('color') if defined $cgi->param('color'); 11 | 12 | print $cgi->start_html(-title => uc($color), 13 | -BGCOLOR => $color); 14 | print $cgi->h1("This is $color"); 15 | print $cgi->end_html; 16 | -------------------------------------------------------------------------------- /httpd/htdocs/index.html: -------------------------------------------------------------------------------- 1 | 2 | Index 3 | 4 | 5 | 北京 6 | 天津 7 | 烟台 8 | 青岛 9 | 上海 10 | 杭州 11 | 武汉 12 | 13 | -------------------------------------------------------------------------------- /httpd/htdocs/index.html~: -------------------------------------------------------------------------------- 1 | 2 | Index 3 | 4 | 5 | 北京 6 | 天津 7 | 烟台 8 | 青岛 9 | 上海 10 | 杭州 11 | 武汉 12 | 13 | -------------------------------------------------------------------------------- /httpd/memc/memc.cpp: -------------------------------------------------------------------------------- 1 | #include"memc.h" 2 | /********************************************************/ 3 | /*Initialize and set memcached 4 | *Return val:a pointer to memcached_st structure that 5 | * will then be used by other libmemcached 6 | * functions to communicate with the server */ 7 | /*******************************************************/ 8 | memcached_st* memcache_init() 9 | { 10 | memcached_st *memc; 11 | memcached_return rc; 12 | memcached_server_st* servers; 13 | 14 | memc = memcached_create(NULL); 15 | servers = memcached_server_list_append(NULL, (char*)"localhost", 11211, &rc); 16 | servers = memcached_server_list_append(servers, (char*)"localhost", 11212, &rc); 17 | // servers = memcached_server_list_append(servers, (char*)"localhost", 1113, &rc); 18 | 19 | rc = memcached_server_push(memc, servers); 20 | memcached_server_free(servers); 21 | 22 | memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_DISTRIBUTION, MEMCACHED_DISTRIBUTION_CONSISTENT); 23 | memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RETRY_TIMEOUT, 20); 24 | memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT, 5); 25 | return memc; 26 | } 27 | /*****************************************************************/ 28 | /* Query data from memcached 29 | * Parameters:memcached_st pointer to communicate with the server 30 | * the buffer to save query result 31 | * the key for query 32 | * Return val 0 success -1 failed */ 33 | /****************************************************************/ 34 | int query_memcache(memcached_st* memc,char* page_info,char* page_name) 35 | { 36 | size_t value_length = 0; 37 | //char* returned by memcached_get must be free 38 | char *str_get_by_mem = memcached_get(memc, page_name, strlen(page_name), &value_length, (uint32_t)0, NULL); 39 | if (str_get_by_mem != NULL) 40 | { 41 | strcpy(page_info, str_get_by_mem); 42 | //printf("get data from cache success\n"); 43 | free(str_get_by_mem); 44 | return 0; 45 | } 46 | else 47 | { 48 | printf("get data:<%s >from cache failed\n", page_name); 49 | free(str_get_by_mem); 50 | return -1; 51 | } 52 | } 53 | 54 | /****************************************/ 55 | / * free the memcached*/ 56 | / * *************************************/ 57 | void memcache_destroy(memcached_st* memc) 58 | { 59 | memcached_free(memc); 60 | } 61 | -------------------------------------------------------------------------------- /httpd/memc/memc.h: -------------------------------------------------------------------------------- 1 | #ifndef _MEMC_ 2 | #define _MEMC_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | memcached_st* memcache_init(); 9 | int query_memcache(memcached_st*,char*,char*); 10 | void memcache_destroy(memcached_st*); 11 | #endif 12 | -------------------------------------------------------------------------------- /httpd/server/httpd.cpp: -------------------------------------------------------------------------------- 1 | #include"httpd.h" 2 | #include"database.h" 3 | #include"memc.h" 4 | #include"sock.h" 5 | 6 | 7 | /**************************************************************/ 8 | /* Run as a thread. Receive the data from network and process 9 | * the request ,query and send the page data 10 | * Parameters: the socket connected to the client 11 | * the epoll_event processed with current thread */ 12 | /*************************************************************/ 13 | void accept_request(int client,struct epoll_event* even) 14 | { 15 | signal(13,SIG_IGN);//ignore the sigpipe 16 | char buf[1024]; 17 | int numchars; 18 | char method[255]; 19 | char url[255]; 20 | char path[512]; 21 | size_t i, j; 22 | struct stat st; 23 | char *query_string = NULL; 24 | 25 | numchars = get_line(client, buf, sizeof(buf)); 26 | i = 0; j = 0; 27 | while (!ISspace(buf[j]) && (i < sizeof(method)-1)) 28 | { 29 | method[i] = buf[j]; 30 | i++; j++; 31 | } 32 | method[i] = '\0'; 33 | if (strcasecmp(method, "GET") && strcasecmp(method, "POST")) 34 | { 35 | unimplemented(client); 36 | return; 37 | } 38 | 39 | 40 | i = 0; 41 | while (ISspace(buf[j]) && (j < sizeof(buf))) 42 | j++; 43 | while (!ISspace(buf[j]) && (i < sizeof(url)-1) && (j < sizeof(buf))) 44 | { 45 | url[i] = buf[j]; 46 | i++; j++; 47 | } 48 | url[i] = '\0'; 49 | 50 | sprintf(path, "htdocs%s", url); 51 | char *page_info = (char*)malloc(MAX_SIZE_OF_PAGE);//the content of the html page 52 | page_info[0] = '\0'; 53 | //request the homepage 54 | if (path[strlen(path) - 1] == '/') 55 | { 56 | strcat(path, "index.html"); 57 | if (stat(path, &st) == -1) 58 | { 59 | while ((numchars > 0) && strcmp("\n", buf)) /* read & discard headers */ 60 | numchars = get_line(client, buf, sizeof(buf)); 61 | not_found(client); 62 | } 63 | else 64 | { 65 | if ((st.st_mode & S_IFMT) == S_IFDIR) 66 | strcat(path, "/index.html"); 67 | serve_file(client, path); 68 | } 69 | } 70 | //request the page stored in database 71 | else 72 | { 73 | //try to get data from cache first. if failed then try to get it in database 74 | char *page_name = url + 1;//such as "BeiJing.html" 75 | memcached_st *memc = memcache_init(); 76 | if (query_memcache(memc,page_info,page_name) < 0) 77 | { 78 | if(query_database(page_info,page_name) < 0) 79 | { 80 | printf("Im here query database faile and close the client"); 81 | free(page_info); 82 | memcache_destroy(memc); 83 | close(client); 84 | return; 85 | } 86 | memcached_set(memc, page_name, strlen(page_name), page_info, strlen(page_info), (time_t)180, (uint32_t)0); 87 | } 88 | memcache_destroy(memc); 89 | header_and_cat(client, page_info); 90 | } 91 | free(page_info); 92 | close(client); 93 | epoll_ctl(epollfd, EPOLL_CTL_DEL, client, even); 94 | } 95 | 96 | /**********************************************************************/ 97 | /* send the http header and the content of the page 98 | * Parameters: client socket 99 | * the buffer to send */ 100 | /**********************************************************************/ 101 | void header_and_cat(int client, char* page_info) 102 | { 103 | int numchars = 1; 104 | char buf[1024]; 105 | 106 | buf[0] = 'A'; buf[1] = '\0'; 107 | while ((numchars > 0) && strcmp("\n", buf)) /* read & discard headers */ 108 | numchars = get_line(client, buf, sizeof(buf)); 109 | headers(client, NULL); 110 | socket_send(client, page_info); 111 | 112 | } 113 | 114 | /**********************************************************************/ 115 | /* Inform the client that a request it has made has a problem. 116 | * Parameters: client socket */ 117 | /**********************************************************************/ 118 | void bad_request(int client) 119 | { 120 | char buf[1024]; 121 | 122 | sprintf(buf, "HTTP/1.0 400 BAD REQUEST\r\n"); 123 | socket_send(client, buf); 124 | sprintf(buf, "Content-type: text/html\r\n"); 125 | socket_send(client, buf); 126 | sprintf(buf, "\r\n"); 127 | socket_send(client, buf); 128 | sprintf(buf, "

Your browser sent a bad request, "); 129 | socket_send(client, buf); 130 | sprintf(buf, "such as a POST without a Content-Length.\r\n"); 131 | socket_send(client, buf); 132 | } 133 | 134 | /**********************************************************************/ 135 | /* Put the entire contents of a file out on a socket. This function 136 | * is named after the UNIX "cat" command, because it might have been 137 | * easier just to do something like pipe, fork, and exec("cat"). 138 | * Parameters: the client socket descriptor 139 | * FILE pointer for the file to cat */ 140 | /**********************************************************************/ 141 | void cat(int client, FILE *resource) 142 | { 143 | /*///////////////////////debug//// 144 | * 145 | *struct sockaddr_in name; 146 | * u_short port; 147 | * int namelen = sizeof(name); 148 | * getsockname(client, (struct sockaddr *)&name, &namelen); 149 | * port = ntohs(name.sin_port); 150 | * printf("send port in fun headr_and_cat is %d\n",port); 151 | */ 152 | char buf[1024]; 153 | 154 | fgets(buf, sizeof(buf), resource); 155 | while (!feof(resource)) 156 | { 157 | socket_send(client, buf); 158 | fgets(buf, sizeof(buf), resource); 159 | } 160 | } 161 | /**********************************************************************/ 162 | /* Inform the client that a CGI script could not be executed. 163 | * Parameter: the client socket descriptor. */ 164 | /**********************************************************************/ 165 | void cannot_execute(int client) 166 | { 167 | char buf[1024]; 168 | 169 | sprintf(buf, "HTTP/1.0 500 Internal Server Error\r\n"); 170 | socket_send(client, buf); 171 | sprintf(buf, "Content-type: text/html\r\n"); 172 | socket_send(client, buf); 173 | sprintf(buf, "\r\n"); 174 | socket_send(client, buf); 175 | sprintf(buf, "

Error prohibited CGI execution.\r\n"); 176 | socket_send(client, buf); 177 | } 178 | 179 | 180 | 181 | /**********************************************************************/ 182 | /* Get a line from a socket, whether the line ends in a newline, 183 | carriage return, or a CRLF combination. Terminates the string read 184 | * with a null character. If no newline indicator is found before the 185 | * end of the buffer, the string is terminated with a null. If any of 186 | * the above three line terminators is read, the last character of the 187 | * string will be a linefeed and the string will be terminated with a 188 | * null character. 189 | * Parameters: the socket descriptor 190 | * the buffer to save the data in 191 | * the size of the buffer 192 | * Returns: the number of bytes stored (excluding null) */ 193 | /**********************************************************************/ 194 | int get_line(int sock, char *buf, int size) 195 | { 196 | int i = 0; 197 | char c = '\0'; 198 | int n; 199 | 200 | while ((i < size - 1) && (c != '\n')) 201 | { 202 | n = recv(sock, &c, 1, 0); 203 | /* DEBUG printf("%02X\n", c); */ 204 | if (n > 0) 205 | { 206 | if (c == '\r') 207 | { 208 | n = recv(sock, &c, 1, MSG_PEEK); 209 | /* DEBUG printf("%02X\n", c); */ 210 | if ((n > 0) && (c == '\n')) 211 | recv(sock, &c, 1, 0); 212 | else 213 | c = '\n'; 214 | } 215 | buf[i] = c; 216 | i++; 217 | } 218 | else 219 | c = '\n'; 220 | } 221 | buf[i] = '\0'; 222 | 223 | return(i); 224 | } 225 | 226 | /**********************************************************************/ 227 | /* Return the informational HTTP headers about a file. */ 228 | /* Parameters: the socket to print the headers on 229 | * the name of the file */ 230 | /**********************************************************************/ 231 | void headers(int client, const char *filename) 232 | { 233 | char buf[1024]; 234 | (void)filename; /* could use filename to determine file type */ 235 | 236 | strcpy(buf, "HTTP/1.0 200 OK\r\n"); 237 | socket_send(client, buf); 238 | strcpy(buf, SERVER_STRING); 239 | socket_send(client, buf); 240 | 241 | sprintf(buf, "Content-/Type: text/html\r\n"); 242 | socket_send(client, buf); 243 | strcpy(buf, "\r\n"); 244 | socket_send(client, buf); 245 | 246 | 247 | } 248 | 249 | /**********************************************************************/ 250 | /* Give a client a 404 not found status message. */ 251 | /**********************************************************************/ 252 | void not_found(int client) 253 | { 254 | char buf[1024]; 255 | 256 | sprintf(buf, "HTTP/1.0 404 NOT FOUND\r\n"); 257 | socket_send(client, buf); 258 | sprintf(buf, SERVER_STRING); 259 | socket_send(client, buf); 260 | sprintf(buf, "Content-Type: text/html\r\n"); 261 | socket_send(client, buf); 262 | sprintf(buf, "\r\n"); 263 | socket_send(client, buf); 264 | sprintf(buf, "Not Found\r\n"); 265 | socket_send(client, buf); 266 | sprintf(buf, "

The server could not fulfill\r\n"); 267 | socket_send(client, buf); 268 | sprintf(buf, "your request because the resource specified\r\n"); 269 | socket_send(client, buf); 270 | sprintf(buf, "is unavailable or nonexistent.\r\n"); 271 | socket_send(client, buf); 272 | sprintf(buf, "\r\n"); 273 | socket_send(client, buf); 274 | } 275 | 276 | /**********************************************************************/ 277 | /* Send a regular file to the client. Use headers, and report 278 | * errors to client if they occur. 279 | * Parameters: a pointer to a file structure produced from the socket 280 | * file descriptor 281 | * the name of the file to serve */ 282 | /**********************************************************************/ 283 | void serve_file(int client, const char *filename) 284 | { 285 | FILE *resource = NULL; 286 | int numchars = 1; 287 | char buf[1024]; 288 | 289 | buf[0] = 'A'; buf[1] = '\0'; 290 | while ((numchars > 0) && strcmp("\n", buf)) /* read & discard headers */ 291 | numchars = get_line(client, buf, sizeof(buf)); 292 | 293 | resource = fopen(filename, "r"); 294 | if (resource == NULL) 295 | not_found(client); 296 | else 297 | { 298 | headers(client, filename); 299 | cat(client, resource); 300 | } 301 | fclose(resource); 302 | } 303 | 304 | /**********************************************************************/ 305 | /* Inform the client that the requested web method has not been 306 | * implemented. 307 | * Parameter: the client socket */ 308 | /**********************************************************************/ 309 | void unimplemented(int client) 310 | { 311 | char buf[1024]; 312 | 313 | sprintf(buf, "HTTP/1.0 501 Method Not Implemented\r\n"); 314 | socket_send(client, buf); 315 | sprintf(buf, SERVER_STRING); 316 | socket_send(client, buf); 317 | sprintf(buf, "Content-Type: text/html\r\n"); 318 | socket_send(client, buf); 319 | sprintf(buf, "\r\n"); 320 | socket_send(client, buf); 321 | sprintf(buf, "Method Not Implemented\r\n"); 322 | socket_send(client, buf); 323 | sprintf(buf, "\r\n"); 324 | socket_send(client, buf); 325 | sprintf(buf, "

HTTP request method not supported.\r\n"); 326 | socket_send(client, buf); 327 | sprintf(buf, "\r\n"); 328 | socket_send(client, buf); 329 | } 330 | 331 | /**********************************************************************/ 332 | 333 | 334 | 335 | int epollfd; 336 | struct epoll_event eventList[MAX_EVENTS]; 337 | 338 | int main(void) 339 | { 340 | int server_sock = -1; 341 | server_sock = startup(); 342 | //init epoll 343 | struct epoll_event event; 344 | epollfd = epoll_create(MAX_EVENTS); 345 | if (epollfd == -1){ 346 | perror("epoll create failed."); 347 | exit(1); 348 | } 349 | event.events = EPOLLIN | EPOLLET; 350 | event.data.fd = server_sock; 351 | 352 | //epoll_ctrl 353 | if (epoll_ctl(epollfd, EPOLL_CTL_ADD, server_sock, &event) < 0){ 354 | printf("epoll add fail : fd = %d\n", server_sock); 355 | return -1; 356 | } 357 | boost::threadpool::pool tp(THREAD_SIZE); 358 | while (1) 359 | { 360 | int ret = epoll_wait(epollfd, eventList, MAX_EVENTS, -1); 361 | if (ret < 0) 362 | { 363 | printf("epoll wait failed\n"); 364 | break; 365 | } 366 | for (int n = 0; n < ret; n++) 367 | { 368 | if (eventList[n].data.fd == server_sock) 369 | { 370 | while(AcceptConn(server_sock) > 0); 371 | } 372 | else 373 | { 374 | tp.schedule(boost::bind(accept_request, eventList[n].data.fd,&eventList[n])); 375 | } 376 | } 377 | 378 | } 379 | close(server_sock); 380 | close(epollfd); 381 | tp.wait(); 382 | 383 | return(0); 384 | } 385 | -------------------------------------------------------------------------------- /httpd/server/httpd.h: -------------------------------------------------------------------------------- 1 | #ifndef _HTTPD_ 2 | #define _HTTPD_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | void accept_request(int); 17 | void bad_request(int); 18 | void cat(int, FILE *); 19 | void cannot_execute(int); 20 | void error_die(const char *); 21 | int get_line(int, char *, int); 22 | void headers(int, const char *); 23 | void not_found(int); 24 | void serve_file(int, const char *); 25 | void unimplemented(int); 26 | void header_and_cat(int, char*); 27 | #define ISspace(x) isspace((int)(x)) 28 | #define SERVER_STRING "Server: jdbhttpd/0.1.0\r\n" 29 | #define MAX_SIZE_OF_PAGE 200 30 | #define MAX_EVENTS 100 31 | #define THREAD_SIZE 50 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /httpd/sock/sock.cpp: -------------------------------------------------------------------------------- 1 | #include"sock.h" 2 | 3 | /*************************************************/ 4 | /* send data to NoBlock socket descriptor 5 | * Parameters: the client socket descriptor 6 | * the buffer to send 7 | /***********************************************/ 8 | void socket_send(int fd,char* buf) 9 | { 10 | int nsend; 11 | int data_size = strlen(buf); 12 | int n = data_size; 13 | while(n > 0) 14 | { 15 | nsend = send(fd,buf + data_size -n,n,0); 16 | if(nsend < n) 17 | { 18 | if(nsend == -1 && errno != EAGAIN) 19 | { 20 | // perror("send error"); 21 | } 22 | break; 23 | } 24 | n -= nsend; 25 | } 26 | } 27 | 28 | /*****************************************************/ 29 | /* The function accept the connect from the sevfd 30 | * and add the new socketfd to epoll 31 | * Parameters: the server socket descriptor 32 | * Return va: 1 success -1 failed */ 33 | /***************************************************/ 34 | 35 | int AcceptConn(int srvfd) 36 | { 37 | int confd; 38 | struct epoll_event event; 39 | 40 | struct sockaddr_in sin; 41 | socklen_t len = sizeof(struct sockaddr_in); 42 | bzero(&sin, len); 43 | 44 | confd = accept(srvfd, (struct sockaddr*)&sin, &len); 45 | 46 | if (confd == -1) 47 | { 48 | return -1; 49 | } 50 | setSockNonBlock(confd); 51 | 52 | event.data.fd = confd; 53 | event.events = EPOLLIN | EPOLLET; 54 | if (epoll_ctl(epollfd, EPOLL_CTL_ADD, confd, &event) == -1) { 55 | perror("epoll_ctl(EPOLL_CTL_ADD) failed\n"); 56 | exit(EXIT_FAILURE); 57 | } 58 | return 1; 59 | } 60 | 61 | /**********************************************************************/ 62 | /* This function starts the process of listening for web connections 63 | * on a specified port. 64 | * Returns: the socket */ 65 | /**********************************************************************/ 66 | int startup() 67 | { 68 | int httpd = 0; 69 | struct sockaddr_in name; 70 | 71 | httpd = socket(PF_INET, SOCK_STREAM, 0); 72 | if (httpd == -1) 73 | { 74 | perror("socket"); 75 | exit(1); 76 | } 77 | memset(&name, 0, sizeof(name)); 78 | name.sin_family = AF_INET; 79 | name.sin_port = htons(SER_PORT); 80 | name.sin_addr.s_addr = htonl(INADDR_ANY); 81 | if (bind(httpd, (struct sockaddr *)&name, sizeof(name)) < 0) 82 | { 83 | perror("bind"); 84 | exit(1); 85 | } 86 | if (listen(httpd, 5) < 0) 87 | { 88 | perror("listen"); 89 | exit(1); 90 | } 91 | 92 | setSockNonBlock(httpd); 93 | printf("server is running at port %d\n",SER_PORT); 94 | return(httpd); 95 | } 96 | /***************************************************/ 97 | /*set socket descriptor on NoBlock mode 98 | *Parameter: socket descriptor. */ 99 | /***************************************************/ 100 | void setSockNonBlock(int sock) 101 | { 102 | int flags; 103 | flags = fcntl(sock, F_GETFL, 0); 104 | if (flags < 0) 105 | { 106 | perror("fcntl(F_GETFL) failed"); 107 | exit(1); 108 | } 109 | if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) < 0) 110 | { 111 | perror("fcntl(F_SETFL) failed"); 112 | exit(1); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /httpd/sock/sock.h: -------------------------------------------------------------------------------- 1 | #ifndef _SOCK_ 2 | #define _SOCK_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #define SER_PORT 59470 17 | extern int epollfd; 18 | int AcceptConn(int); 19 | void socket_send(int,char*); 20 | int startup(); 21 | void setSockNonBlock(int); 22 | //void socket_recv(int,char*); 23 | #endif 24 | -------------------------------------------------------------------------------- /msg/Makefile: -------------------------------------------------------------------------------- 1 | SER=server 2 | CLI=client 3 | CC=gcc 4 | 5 | .PHONY:all 6 | all:$(CLI) $(SER) 7 | 8 | $(CLI):client.c msgqueue.c 9 | $(CC) -w -o $@ $^ 10 | $(SER):server.c msgqueue.c 11 | $(CC) -w -o $@ $^ 12 | 13 | .PHONY:clean 14 | clean: 15 | rm -rf $(CLI) $(SER) 16 | 17 | -------------------------------------------------------------------------------- /msg/client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "msgqueue.h" 3 | 4 | int client() 5 | { 6 | int msgqueue_id = get_queue(); 7 | char buf[_SIZE_]; 8 | while(1) 9 | { 10 | printf("Please Enter : "); 11 | fflush(stdout); 12 | memset(buf,'\0',sizeof(buf));//buf保存消费掉的消息 13 | gets(buf);//client从标准输出上获取信息并且存放在buf里面 14 | send_msg(msgqueue_id,CLIENT_TYPE,buf);//经buf里面的消息发送给server 15 | if(strncasecmp(buf,"Quit",4) == 0){ 16 | printf("Quit\n"); 17 | return 0; 18 | } 19 | sleep(2); 20 | memset(buf,'\0',sizeof(buf));//buf保存消费掉的消息 21 | int ret = recv_msg(msgqueue_id,SERVER_TYPE,buf,sizeof(buf));//client删除从server发送来的消息 22 | if(ret == 0) 23 | { 24 | printf("server say : %s\n",buf); 25 | } 26 | } 27 | } 28 | int main() 29 | { 30 | client(); 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /msg/msgqueue.c: -------------------------------------------------------------------------------- 1 | #include "msgqueue.h" 2 | static int com_creat_queue(int def) 3 | { 4 | key_t key = ftok(_PATH_,_PROJ_ID_);//key标识唯一的消息队列 5 | if(key < 0){ 6 | perror("ftok"); 7 | return -1; 8 | } 9 | int msgqueue_id = msgget(key,def); 10 | if(msgqueue_id < 0){ 11 | perror("msgget");//创建消息队列失败 12 | return -2; 13 | } 14 | return msgqueue_id; 15 | } 16 | int creat_queue() 17 | { 18 | int def = IPC_CREAT|IPC_EXCL|0666;//IPC_CREAT和IPC_EXCL一起使用保证创建一个全新的消息队列,IPC_EXCL单独使用没有用,必须和IPC_CREAT配合着使用,若消息队列存在,则错误返回;0666是使创建的消息队列的权限是666 19 | return com_creat_queue(def); 20 | } 21 | int get_queue() 22 | { 23 | int def = IPC_CREAT;//如果该队列不存在,则创建它,否则打开它 24 | return com_creat_queue(def); 25 | } 26 | int send_msg(int msgqueue_id,int who,char *msg) 27 | {//生产消息 28 | struct msgbuf _buf;//_buf存放要发送的消息 29 | memset(&_buf,'\0',sizeof(_buf)); 30 | _buf.mtype = who;//指定是谁发送的消息,也可以指定是谁接受该条消息 31 | strncpy(_buf.mtext,msg,sizeof(msg)+1); 32 | printf("I say : %s\n",_buf.mtext); 33 | return msgsnd(msgqueue_id,&_buf,sizeof(_buf.mtext),0); 34 | } 35 | int recv_msg(int msgqueue_id,int want,char out[],int out_len) 36 | {//消费消息 37 | struct msgbuf _buf; 38 | memset(&_buf,'\0',sizeof(_buf));//将_buf里面的消息删除 39 | int ret = msgrcv(msgqueue_id,&_buf,sizeof(_buf.mtext),want,0);// 想要把want的_buf里面的消息删除,成功则返回消息的大小 40 | //int ret = msgrcv(msgqueue_id,&_buf,sizeof(_buf),want,0);// 想要把want的_buf里面的消息删除,成功则返回消息的大小 41 | if(ret <= -1){ 42 | perror("msgrcv"); 43 | return -1; 44 | } 45 | memset(out,'\0',out_len);//用out将删除的消息保存起来 46 | //strncpy(out,_buf.mtext,ret); 47 | strcpy(out,_buf.mtext); 48 | //printf("%s\n",out); 49 | return 0; 50 | } 51 | int delete_queue(int msgqueue_id) 52 | {//删除消息队列 53 | int ret = msgctl(msgqueue_id,IPC_RMID,NULL); 54 | if(ret < 0){ 55 | perror("msgctl"); 56 | return -3; 57 | } 58 | return 0; 59 | } 60 | 61 | 62 | 函数的作用分析见博客:http://blog.csdn.net/sulijuan66/article/details/50589684 -------------------------------------------------------------------------------- /msg/msgqueue.h: -------------------------------------------------------------------------------- 1 | #ifndef _DEBUG_ 2 | #define _DEBUG_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define _PATH_ "." //当前路径下 11 | #define _PROJ_ID_ 0x6654 12 | #define _SIZE_ 3000 13 | 14 | #define SERVER_TYPE 2 15 | #define CLIENT_TYPE 1 16 | 17 | struct msgbuf 18 | { 19 | long mtype; //标识是谁发的消息,也可以标识是给谁发的消息,此处举例是前者 20 | char mtext[_SIZE_];//存放发的消息 21 | }; 22 | int creat_queue();//由server创建消息队列,保证创建的是一个全新的消息队列 23 | int get_queue(); //client访问消息队列,若不存在,则创建它;若存在,则打开它(不能保证打开的是一个全新的消息队列) 24 | 25 | int send_msg(int msgqueue_id,int who,char *msg); //生产消息 26 | int recv_msg(int msgqueue_id,int wang,char out[],int out_len); //消费消息 27 | 28 | int delete_msgqueue(int msgqueue_id); //删除消息队列 29 | 30 | #endif 31 | 32 | -------------------------------------------------------------------------------- /msg/server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "msgqueue.h" 3 | 4 | int server() 5 | { 6 | int msgqueue_id = creat_queue(); 7 | if(msgqueue_id < 0){ 8 | perror("server"); 9 | return -1; 10 | } 11 | char buf[_SIZE_]; 12 | while(1) 13 | { 14 | sleep(2); 15 | memset(buf,'\0',sizeof(buf));//buf保存消费掉的消息 16 | int ret = recv_msg(msgqueue_id,CLIENT_TYPE,buf,sizeof(buf));//server删除从client发送来的消息 17 | if(ret == 0) 18 | { 19 | if(strncasecmp(buf,"Quit",4) == 0){ 20 | printf("client Quit!\n"); 21 | break; 22 | } 23 | printf("client say : %s\n",buf); 24 | } 25 | printf("Please Enter : "); 26 | fflush(stdout); 27 | memset(buf,'\0',sizeof(buf)); 28 | gets(buf);//server从标准输出上获取信息并且存放在buf里面 29 | send_msg(msgqueue_id,SERVER_TYPE,buf);//经buf里面的消息发送给client 30 | } 31 | return delete_queue(msgqueue_id);//最后由server删除消息队列 32 | } 33 | int main() 34 | { 35 | server(); 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /my/5class/UDP/Makefile: -------------------------------------------------------------------------------- 1 | CLI=udp_client 2 | SER=udp_server 3 | CC=gcc 4 | FLAGS=#-static 5 | .PHONY:all 6 | all:$(CLI) $(SER) 7 | 8 | $(CLI):udp_client.c 9 | $(CC) -o $@ $^ $(FLAGS) 10 | $(SER):udp_server.c 11 | $(CC) -o $@ $^ $(FLAGS) 12 | .PHONY:clean 13 | clean: 14 | rm -rf $(CLI) $(SER) 15 | -------------------------------------------------------------------------------- /my/5class/UDP/udp_client: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoxiao-su/_Linux-OS-Network_/a561603918e0bd1fc57a5fb1f0b980fe5227a2de/my/5class/UDP/udp_client -------------------------------------------------------------------------------- /my/5class/UDP/udp_client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | int main() 7 | { 8 | int sock = socket(AF_INET,SOCK_DGRAM,0); 9 | if(sock == -1){ 10 | perror("socket"); 11 | return -1; 12 | } 13 | struct sockaddr_in remote; 14 | remote.sin_family = AF_INET; 15 | remote.sin_port = htons(8080); 16 | remote.sin_addr.s_addr = inet_addr("192.168.18.129"); 17 | 18 | char buf[1024]; 19 | while(1){ 20 | memset(buf,'\0',sizeof(buf)); 21 | printf("Please Enhter"); 22 | fflush(stdout); 23 | socklen_t len = sizeof(remote); 24 | gets(buf); 25 | sendto(sock,buf,sizeof(buf)-1,0,(struct sockaddr*)&remote,sizeof(remote)); 26 | recvfrom(sock,buf,sizeof(buf)-1,0,(struct sockaddr*)&remote,&len); 27 | printf("echo :%s\n",buf); 28 | 29 | } 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /my/5class/UDP/udp_server: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoxiao-su/_Linux-OS-Network_/a561603918e0bd1fc57a5fb1f0b980fe5227a2de/my/5class/UDP/udp_server -------------------------------------------------------------------------------- /my/5class/UDP/udp_server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | static void usage(const char *msg) 7 | { 8 | if(msg == NULL){ 9 | printf("%s [ip] [port]\n"); 10 | } 11 | } 12 | 13 | int start(const char* const ip,short port) 14 | { 15 | int sock = socket(AF_INET,SOCK_DGRAM,0); 16 | if(sock == -1) 17 | { 18 | perror("scoket"); 19 | return -1; 20 | } 21 | struct sockaddr_in local; 22 | local.sin_family = AF_INET; 23 | local.sin_port = htons(port); 24 | local.sin_addr.s_addr = inet_addr(ip); 25 | if( bind(sock,(struct sockaddr*)&local,sizeof(local)) == -1) 26 | { 27 | perror("bind"); 28 | return -1; 29 | } 30 | return sock; 31 | } 32 | int main(int argc,char* argv[]) 33 | { 34 | if(argc != 3){ 35 | usage(argv[0]); 36 | return 1; 37 | } 38 | const char* ip = argv[1]; 39 | short port = atoi(argv[2]);//sprintf,sscanf 40 | int sock = start(ip,port);//启动一个udp套接 41 | char buf[1024]; 42 | if( sock > 0){ 43 | while(1){ 44 | memset(buf,'\0',sizeof(buf)); 45 | struct sockaddr_in client; 46 | socklen_t len = 0; 47 | recvfrom(sock,buf,sizeof(buf)-1,0,(struct sockaddr*)&client,&len); 48 | printf("client :%s\n",buf); 49 | sendto(sock,buf,sizeof(buf)-1,0,(struct sockaddr*)&client,len); 50 | } 51 | } 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /my/5class/alarm/Makefile: -------------------------------------------------------------------------------- 1 | alarm.out:alarm.c 2 | gcc -o alarm.out alarm.c 3 | PHONY:clean 4 | clean: 5 | rm -rf alarm.out 6 | -------------------------------------------------------------------------------- /my/5class/alarm/alarm.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | int main() 4 | { 5 | alarm(1);//此函数的返回值是0或者是上一次闹钟的剩余秒数 6 | int count = 0; 7 | while(1){ 8 | printf("I am alive;%d\n",count++); 9 | } 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /my/5class/awk/Count_capacity.awk: -------------------------------------------------------------------------------- 1 | #!/bin/awk -f 2 | 3 | ls -lR file 4 | 5 | BEGIN{ 6 | size = 0; 7 | } 8 | { 9 | 10 | } 11 | END{ 12 | 13 | } 14 | -------------------------------------------------------------------------------- /my/5class/awk/file: -------------------------------------------------------------------------------- 1 | root:x:0:0:root:/root:/bin/bash 2 | bin:x:1:1:bin:/bin:/sbin/nologin 3 | daemon:x:2:2:daemon:/sbin:/sbin/nologin 4 | adm:x:3:4:adm:/var/adm:/sbin/nologin 5 | lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin 6 | sync:x:5:0:sync:/sbin:/bin/sync 7 | shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown 8 | halt:x:7:0:halt:/sbin:/sbin/halt 9 | mail:x:8:12:mail:/var/spool/mail:/sbin/nologin 10 | uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin 11 | operator:x:11:0:operator:/root:/sbin/nologin 12 | games:x:12:100:games:/usr/games:/sbin/nologin 13 | gopher:x:13:30:gopher:/var/gopher:/sbin/nologin 14 | ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin 15 | nobody:x:99:99:Nobody:/:/sbin/nologin 16 | dbus:x:81:81:System message bus:/:/sbin/nologin 17 | usbmuxd:x:113:113:usbmuxd user:/:/sbin/nologin 18 | vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin 19 | rtkit:x:499:497:RealtimeKit:/proc:/sbin/nologin 20 | avahi-autoipd:x:170:170:Avahi IPv4LL Stack:/var/lib/avahi-autoipd:/sbin/nologin 21 | pulse:x:498:496:PulseAudio System Daemon:/var/run/pulse:/sbin/nologin 22 | haldaemon:x:68:68:HAL daemon:/:/sbin/nologin 23 | ntp:x:38:38::/etc/ntp:/sbin/nologin 24 | apache:x:48:48:Apache:/var/www:/sbin/nologin 25 | saslauth:x:497:76:"Saslauthd user":/var/empty/saslauth:/sbin/nologin 26 | postfix:x:89:89::/var/spool/postfix:/sbin/nologin 27 | abrt:x:173:173::/etc/abrt:/sbin/nologin 28 | gdm:x:42:42::/var/lib/gdm:/sbin/nologin 29 | sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin 30 | tcpdump:x:72:72::/:/sbin/nologin 31 | xiaoxiaosu:x:500:500:CentOS6.5:/home/xiaoxiaosu:/bin/bash 32 | -------------------------------------------------------------------------------- /my/5class/awk/test.awk: -------------------------------------------------------------------------------- 1 | #!/bin/awk -f 2 | BEGIN{ 3 | a_n = 0; 4 | b_n = 0; 5 | c_n = 0; 6 | } 7 | /^a.*n$/{ 8 | a_n++; 9 | } 10 | /^b.*n$/{ 11 | b_n++; 12 | } 13 | /^c.*n$/{ 14 | c_n++; 15 | } 16 | END{ 17 | printf("a_n:%d\n",a_n); 18 | printf("b_n:%d\n",b_n); 19 | printf("c_n:%d\n",c_n); 20 | printf("filename:%s\n",FILENAME); 21 | } 22 | -------------------------------------------------------------------------------- /my/5class/daemon/Makefile: -------------------------------------------------------------------------------- 1 | daemon.out:daemon.c 2 | gcc -o daemon.out daemon.c 3 | .PHONY:clean 4 | clean: 5 | rm -rf daemon.out 6 | -------------------------------------------------------------------------------- /my/5class/daemon/daemon.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | int mydaemon() 6 | { 7 | umask(0); 8 | pid_t id = fork(); 9 | if(id > 0){ 10 | exit(0); 11 | } 12 | signal(SIGCHLD,SIG_IGN); 13 | setsid();//建立一个会话 14 | //if(fork() > 0){//保证后续的操作不嫩过程为会话首进程 15 | // exit(0); 16 | //} 17 | close(0); 18 | close(1); 19 | close(2); 20 | chdir("/");//修改当前工作目录为根目录 21 | return 0; 22 | } 23 | int main() 24 | { 25 | //mydaemon(); 26 | daemon(0,0);//系统调用,该进程调用前是一个普通进程,调用之后就变成一个精灵进程 27 | while(1){//只有一个一个进程在执行while语句 28 | sleep(1); 29 | } 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /my/5class/daemon/daemon.out: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoxiao-su/_Linux-OS-Network_/a561603918e0bd1fc57a5fb1f0b980fe5227a2de/my/5class/daemon/daemon.out -------------------------------------------------------------------------------- /my/5class/dup/Makefile: -------------------------------------------------------------------------------- 1 | my_dup:my_dup.c 2 | gcc -o $@ $^ 3 | .PHONY:clean 4 | clean: 5 | rm -rf my_dup ./log 6 | -------------------------------------------------------------------------------- /my/5class/dup/my_dup: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoxiao-su/_Linux-OS-Network_/a561603918e0bd1fc57a5fb1f0b980fe5227a2de/my/5class/dup/my_dup -------------------------------------------------------------------------------- /my/5class/dup/my_dup.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #define OPEN_FILE "./log" 8 | 9 | int main() 10 | { 11 | //close(1);//stdout is closing 12 | //FILE *f_p = fopen(OPEN_FILE, "w+");//read,write,create 13 | //if( NULL == f_p ){ 14 | // perror("fopen"); 15 | // return 1; 16 | //} 17 | int fd = open(OPEN_FILE, O_RDWR | O_CREAT, 0666); 18 | if( fd < 0 ){ 19 | perror("open"); 20 | return 1; 21 | } 22 | printf("dup begin : %d\n",fd); 23 | //------dup()----- 24 | //close(1); //需要手动关闭为呢见描述符 25 | //system calls create a copy of the file descriptor oldfd. 26 | //dup() uses the lowest-numbered unused descriptor for the new descriptor. 27 | //int new_fd = dup(fd); 28 | 29 | //-----dup2()------ 30 | int new_fd = dup2(fd, 1);//不许要手动关闭文件描述符号 31 | 32 | printf("dup end : new : %d, old : %d\n",new_fd,fd); 33 | int count = 10; 34 | while(count){ 35 | printf("hello world ; %d\n",count); 36 | count--; 37 | } 38 | fflush(stdout);//重定向到文件就由行缓冲变成满缓冲,所以得刷新 39 | //fclose(f_p); 40 | close(fd); 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /my/5class/epoll/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY:all 2 | all:epoll_client epoll_server 3 | 4 | epoll_server:epoll_server.c 5 | gcc -o $@ $^ 6 | epoll_client:epoll_client.c 7 | gcc -o $@ $^ 8 | .PHONY:clean 9 | clean: 10 | rm -rf epoll_client epoll_server 11 | 12 | -------------------------------------------------------------------------------- /my/5class/epoll/client.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ./epoll_client 192.168.18.129 8080 4 | -------------------------------------------------------------------------------- /my/5class/epoll/epoll_client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | static void usage(const char *proc) 10 | { 11 | printf("%s [ip] [port]",proc); 12 | } 13 | 14 | int main(int argc,char* argv[]) 15 | { 16 | if( argc != 3){ 17 | usage(argv[0]); 18 | return 1; 19 | } 20 | int sock = socket(AF_INET,SOCK_STREAM,0); 21 | if( sock < 0){ 22 | perror("socket"); 23 | return 1; 24 | } 25 | int port = atoi(argv[2]); 26 | const char *ip = argv[1]; 27 | struct sockaddr_in remote; 28 | remote.sin_family = AF_INET; 29 | remote.sin_port = htons(port); 30 | remote.sin_addr.s_addr = inet_addr(ip); 31 | 32 | //客户端不需要绑定,需要链接 33 | if(connect(sock, (struct sockaddr*)&remote, sizeof(remote)) < 0){ 34 | perror("connect"); 35 | return 0; 36 | } 37 | char buf[1024]; 38 | //while(1){ 39 | memset(buf, '\0', sizeof(buf)); 40 | printf("Please Enter : "); 41 | fflush(stdout); 42 | gets(buf); 43 | write(sock, buf, strlen(buf)); 44 | close(sock); 45 | //} 46 | 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /my/5class/epoll/epoll_http/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY:all 2 | all:epoll_client epoll_server 3 | 4 | epoll_server:epoll_server.c 5 | gcc -o $@ $^ 6 | epoll_client:epoll_client.c 7 | gcc -o $@ $^ 8 | .PHONY:clean 9 | clean: 10 | rm -rf epoll_client epoll_server 11 | 12 | -------------------------------------------------------------------------------- /my/5class/epoll/epoll_http/client.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ./epoll_client 192.168.18.129 8080 4 | -------------------------------------------------------------------------------- /my/5class/epoll/epoll_http/epoll_client: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoxiao-su/_Linux-OS-Network_/a561603918e0bd1fc57a5fb1f0b980fe5227a2de/my/5class/epoll/epoll_http/epoll_client -------------------------------------------------------------------------------- /my/5class/epoll/epoll_http/epoll_client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | static void usage(const char *proc) 10 | { 11 | printf("%s [ip] [port]",proc); 12 | } 13 | 14 | int main(int argc,char* argv[]) 15 | { 16 | if( argc != 3){ 17 | usage(argv[0]); 18 | return 1; 19 | } 20 | int sock = socket(AF_INET,SOCK_STREAM,0); 21 | if( sock < 0){ 22 | perror("socket"); 23 | return 1; 24 | } 25 | int port = atoi(argv[2]); 26 | const char *ip = argv[1]; 27 | struct sockaddr_in remote; 28 | remote.sin_family = AF_INET; 29 | remote.sin_port = htons(port); 30 | remote.sin_addr.s_addr = inet_addr(ip); 31 | 32 | //客户端不需要绑定,需要链接 33 | if(connect(sock, (struct sockaddr*)&remote, sizeof(remote)) < 0){ 34 | perror("connect"); 35 | return 0; 36 | } 37 | char buf[1024]; 38 | //while(1){ 39 | memset(buf, '\0', sizeof(buf)); 40 | printf("Please Enter : "); 41 | fflush(stdout); 42 | gets(buf); 43 | write(sock, buf, strlen(buf)); 44 | close(sock); 45 | //} 46 | 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /my/5class/epoll/epoll_http/epoll_server: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoxiao-su/_Linux-OS-Network_/a561603918e0bd1fc57a5fb1f0b980fe5227a2de/my/5class/epoll/epoll_http/epoll_server -------------------------------------------------------------------------------- /my/5class/epoll/epoll_http/epoll_server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define _PORT_ 80 11 | #define _BACKLOG_ 5 12 | #define _SIZE_ 10240 13 | #define _TIMEOUT_ 3000 14 | 15 | static void set_nonblock(int fd) 16 | { 17 | int fl = fcntl(fd, F_GETFL); 18 | if( fl < 0 ){ 19 | perror("fcntl error!\n"); 20 | return; 21 | } 22 | if( fcntl(fd, F_SETFL, fl|O_NONBLOCK)){ 23 | perror("fcntl set nonblock error\n"); 24 | return; 25 | } 26 | } 27 | 28 | static int read_data(int fd, char buf[]) 29 | { 30 | int nread = 0; 31 | int n = 0; 32 | //read normal data 33 | while( (nread = read(fd, buf+n, 128)) > 0){ 34 | n = nread; 35 | } 36 | return nread; 37 | } 38 | 39 | static int write_data(int fd, char buf[]) 40 | { 41 | int len = strlen(buf); 42 | int nwrite = 0; 43 | int send_n = 0; 44 | do{ 45 | nwrite = write(fd, buf+send_n, len-send_n); 46 | send_n += nwrite; 47 | }while(nwrite > 0); 48 | return nwrite; 49 | } 50 | 51 | int epoll_server() 52 | { 53 | struct sockaddr_in ser; 54 | struct sockaddr_in cli; 55 | int sock = socket(AF_INET, SOCK_STREAM, 0); 56 | if( sock == 0 ){ 57 | perror("socket"); 58 | return 1; 59 | } 60 | set_nonblock( sock ); 61 | 62 | ser.sin_family = AF_INET; 63 | ser.sin_port = htons(_PORT_); 64 | ser.sin_addr.s_addr = INADDR_ANY;//由系统指定任一个IP地址 65 | 66 | int yes = 1; 67 | setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)); 68 | 69 | //bind 70 | if(bind(sock, (struct sockaddr*)&ser, sizeof(ser)) < 0){ 71 | perror("bind error!"); 72 | return 2; 73 | } 74 | 75 | if(listen(sock, _BACKLOG_) < 0){ 76 | perror("listen error!"); 77 | return 3; 78 | } 79 | 80 | int epoll_fd = epoll_create(256); 81 | if(epoll_fd < 0){ 82 | perror("epoll_create error!"); 83 | close(sock); 84 | return 4; 85 | } 86 | struct epoll_event ev,revent[20]; 87 | 88 | ev.data.fd = sock; 89 | ev.events = EPOLLIN; 90 | if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, sock, &ev) != 0){ 91 | perror("epoll_ctl error!"); 92 | return 5; 93 | } 94 | //int timeout = _TIMEOUT_; 95 | int timeout = -1; 96 | for(;;){ 97 | int revent_size = sizeof(revent)/sizeof(revent[0]); 98 | int epoll_n = epoll_wait(epoll_fd, revent, revent_size, timeout); 99 | switch(epoll_n){ 100 | case -1: 101 | perror("epoll_wait error!"); 102 | exit(6); 103 | break; 104 | case 0: 105 | printf("epoll_wait timeout!\n"); 106 | break; 107 | default: 108 | { 109 | int i = 0; 110 | int new_fd = 0; 111 | socklen_t len = sizeof(cli); 112 | for(; i < epoll_n; i++){ 113 | char buf[_SIZE_]; 114 | memset(buf, '\0', sizeof(buf)); 115 | int fd = revent[i].data.fd; 116 | if( fd == sock ){//sock ready, accept 117 | while( new_fd = accept(fd,(struct sockaddr*)&cli, &len) ){ 118 | set_nonblock(new_fd); 119 | ev.data.fd = new_fd; 120 | ev.events = EPOLLIN|EPOLLET; 121 | if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, new_fd, &ev) < 0){ 122 | perror("add new fd error!\n"); 123 | exit(7); 124 | } 125 | printf("get a new client, fd is : %d\n",new_fd); 126 | } 127 | continue; 128 | } 129 | if( revent[i].events & EPOLLIN){ 130 | int ret = read_data(fd, buf); 131 | if( ret < 0 ){ 132 | printf("##########################"); 133 | printf("buf : %s\n",buf); 134 | printf("##########################"); 135 | }else if( ret == 0 ){ 136 | perror("remote cli is close!"); 137 | }else{ 138 | //do nothing 139 | } 140 | } 141 | //echo data back 142 | ev.data.fd = fd; 143 | ev.events = revent[i].events | EPOLLOUT; 144 | if(epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fd, &ev) < 0){ 145 | perror("mod event error"); 146 | //exit(0); 147 | } 148 | if(revent[i].events & EPOLLOUT){ 149 | memset(buf, '\0', sizeof(buf)); 150 | sprintf(buf, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\n\r\nhello world",13); 151 | write_data(fd,buf); 152 | close(fd); 153 | epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, NULL); 154 | } 155 | } 156 | } 157 | break; 158 | } 159 | } 160 | } 161 | 162 | int main() 163 | { 164 | epoll_server(); 165 | return 0; 166 | } 167 | -------------------------------------------------------------------------------- /my/5class/epoll/epoll_http/server.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ./epoll_server 192.168.18.129 8080 4 | -------------------------------------------------------------------------------- /my/5class/epoll/epoll_server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #define EVENT_SIZE 64 11 | 12 | //基于TCP协议 13 | static void usage(const char *const proc) 14 | { 15 | printf("%s [ip] [port]\n",proc); 16 | } 17 | //设置文件描述符非阻塞,保证对端没有关闭写端时,read函数不会一直阻塞 18 | static void set_nonblock(int new_sock) 19 | { 20 | int fl = fcntl(new_sock, F_GETFL); 21 | if( fl < 0 ){ 22 | perror("fcntl"); 23 | exit(1); 24 | } 25 | fcntl(new_sock, F_SETFL, fl | O_NONBLOCK); 26 | } 27 | 28 | //if 0-> read success, and write success, and remote close 29 | static int read_write_data(int fd) 30 | { 31 | char buf[10240]; 32 | int len = sizeof(buf)-1; 33 | ssize_t sz = 0; 34 | int total = 0; 35 | memset(buf, '\0', sizeof(buf)); 36 | while( (sz = recv(fd, buf+total, len, 0)) > 0 ){ 37 | total += sz; 38 | if( sz < len ){ 39 | break; 40 | } 41 | } 42 | if( total > 0 ){ 43 | buf[total] = '\0'; 44 | printf("buf : %s\n",buf); 45 | memset(buf, '\0', sizeof(buf)); 46 | sprintf(buf, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\n\r\nhello world:)",13);//回显消息 47 | send(fd, buf, sizeof(buf), 0); 48 | } 49 | return 0; 50 | } 51 | 52 | int start(const char* ip,short port) 53 | { 54 | int sock = socket(AF_INET,SOCK_STREAM,0); 55 | if(sock < 0){ 56 | perror("socket"); 57 | return -1; 58 | } 59 | //防止因为timewait情况而使得某个端口无法绑定的情况 60 | int flag = 1; 61 | setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)); 62 | //绑定前进行本地信息的填充 63 | struct sockaddr_in local; 64 | local.sin_family = AF_INET; 65 | local.sin_port = htons(port); 66 | local.sin_addr.s_addr = inet_addr(ip); 67 | //进行绑定 68 | if( bind(sock, (struct sockaddr*)&local, sizeof(local)) < 0){ 69 | perror("bind"); 70 | exit(1); 71 | } 72 | //监听链接,一次最多可以监听5个链接 73 | if( listen(sock, 5) < 0){ 74 | perror("listen"); 75 | exit(1); 76 | } 77 | return sock; 78 | } 79 | 80 | int main(int argc,char* argv[]) 81 | { 82 | if(argc != 3){ 83 | usage(argv[1]); 84 | return 0; 85 | } 86 | const char* ip = argv[1]; 87 | short port = atoi(argv[2]); 88 | int listen_sock = start(ip,port); 89 | //创建一个epoll句柄,占用一个文件描述符 90 | int epfd = epoll_create(256); 91 | if(epfd < 0){ 92 | perror("epoll_create"); 93 | exit(1); 94 | } 95 | 96 | struct epoll_event _event; 97 | _event.events = EPOLLIN;//对读事件感兴趣 98 | if(epoll_ctl(epfd,EPOLL_CTL_ADD,listen_sock,&_event) < 0)//将listen_sock添加进epfd中 99 | { 100 | perror("epoll_ctl"); 101 | exit(1); 102 | } 103 | //out -> ready fd & event 104 | struct epoll_event ready_event[EVENT_SIZE];//存放 105 | int ready_event_size = EVENT_SIZE; 106 | int timeout = 3000; 107 | 108 | int ready_num = 0; 109 | while(1){//accept 110 | switch(ready_num = epoll_wait(epfd, ready_event, ready_event_size, timeout)) 111 | { 112 | case 0://timeout 113 | perror("timeout"); 114 | break; 115 | case -1://error 116 | perror("epoll_wait"); 117 | break; 118 | default://success -> we have fd & events ready at least 1 119 | { 120 | int i = 0; 121 | for(; i < ready_num; i++){ 122 | int fd = ready_event[i].data.fd; 123 | if( fd == listen_sock && (ready_event[i].events & EPOLLIN) ){//listen socket 124 | struct sockaddr_in client; 125 | socklen_t len = sizeof(client); 126 | int new_sock = accept(fd, (struct sockaddr*)&client, &len); 127 | if( new_sock < 0 ){ 128 | perror("accept"); 129 | continue; 130 | } 131 | //accpt success 132 | set_nonblock(new_sock); 133 | _event.events = EPOLLIN | EPOLLOUT | EPOLLET; 134 | if(epoll_ctl(epfd, EPOLL_CTL_ADD, new_sock, &_event) < 0){ 135 | perror("epoll_wait"); 136 | close(new_sock); 137 | continue; 138 | } 139 | }else if( (ready_event[i].events & EPOLLIN) && (ready_event[i].events & EPOLLOUT) ){//other socket 140 | if( read_write_data(fd) == 0 ){ 141 | close(fd); 142 | epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL); 143 | } 144 | } 145 | } 146 | } 147 | break; 148 | } 149 | } 150 | return 0; 151 | } 152 | -------------------------------------------------------------------------------- /my/5class/epoll/server.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ./epoll_server 192.168.18.129 8080 4 | -------------------------------------------------------------------------------- /my/5class/hold_pattern/file: -------------------------------------------------------------------------------- 1 | 0 2 | 1 3 | 2 4 | 3 5 | 4 6 | 5 7 | 6 8 | 7 9 | 8 10 | 9 11 | -------------------------------------------------------------------------------- /my/5class/httpd/Makefile: -------------------------------------------------------------------------------- 1 | PWD=$(shell pwd) 2 | BIN=httpd 3 | SRC=httpd.c 4 | INCLUDE=. 5 | CC=gcc 6 | FLAGS=-o 7 | LDFLAGS=#-static 8 | LIB= 9 | 10 | $(BIN):$(SRC) 11 | $(CC) $(FLAGS) $@ $^ $(LDFLAGS) 12 | .PHONY:clean 13 | clean: 14 | rm -rf $(BIN) 15 | -------------------------------------------------------------------------------- /my/5class/httpd/client.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoxiao-su/_Linux-OS-Network_/a561603918e0bd1fc57a5fb1f0b980fe5227a2de/my/5class/httpd/client.c -------------------------------------------------------------------------------- /my/5class/httpd/client.h: -------------------------------------------------------------------------------- 1 | #ifndef _DEMO_CLIET_ 2 | #define _DEMO_CLIENT_ 3 | 4 | #endif 5 | -------------------------------------------------------------------------------- /my/5class/httpd/httpd.c: -------------------------------------------------------------------------------- 1 | #include "httpd.h" 2 | //多进程的http 3 | void usage(const char* proc) 4 | { 5 | printf("Usage : %s [ip] [port]",proc); 6 | } 7 | 8 | void printf_log(const char* fun,int line,int errno,const char* err_str) 9 | 10 | int start(short port) 11 | { 12 | int listen_sock = socket(AF_INET,SOCK_STREAM,0); 13 | if(listen_sock == -1){ 14 | printf_log(__FUNCTION__,__LINE__,errno,strerror(errno)); 15 | exit(1); 16 | } 17 | struct sockaddr_in local; 18 | local.sin_family = AF_INET; 19 | local.sin_port = htons(port); 20 | local.sin_addr = INADDR_ANY; 21 | socklen_t len = sizeof(local); 22 | if(bind(listen_sock,(struct sockaddr*)local,len) == -1){ 23 | printf_log(__FUNCTION__,__LINE__,errno,strerror(errno)); 24 | exit(2); 25 | } 26 | if(listen(listen_sock,BACKLOG) == -1){ 27 | printf_log(__FUNCTION__,__LINE__,errno,strerror(errno)); 28 | exit(3); 29 | } 30 | return listen_sock; 31 | } 32 | 33 | int main(int argc,char *argv[]) 34 | { 35 | if(argc != 3){ 36 | usage(argv[0]); 37 | exit(1); 38 | } 39 | short port = atoi(argv[2]); 40 | printf("port:%d\n",port); 41 | int sock = start(port); 42 | } 43 | -------------------------------------------------------------------------------- /my/5class/httpd/httpd.h: -------------------------------------------------------------------------------- 1 | #ifndef _HTTPD_H_ 2 | #define _HTTP_H_ 3 | 4 | #define BACKLOG 5 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /my/5class/httpd/server.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoxiao-su/_Linux-OS-Network_/a561603918e0bd1fc57a5fb1f0b980fe5227a2de/my/5class/httpd/server.c -------------------------------------------------------------------------------- /my/5class/kill/kill_myself.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void handler(int sig) 4 | { 5 | 6 | } 7 | int main() 8 | { 9 | signal(2,handler); 10 | } 11 | -------------------------------------------------------------------------------- /my/5class/mask_pending/Makefile: -------------------------------------------------------------------------------- 1 | #mask.out:mask.c 2 | # gcc -o mask.out mask.c 3 | #PHONY:clean 4 | #clean: 5 | # rm -rf mask.out 6 | #sighandler:sighandler.c 7 | # gcc -o $@ $^ 8 | #PHONY:clean 9 | #clean: 10 | # rm -rf sighandler 11 | #sleep:sleep.c 12 | # gcc -o $@ $^ 13 | #PHONY:clean 14 | #clean: 15 | # rm -rf sleep 16 | ke_chong_ru:ke_chong_ru.c 17 | gcc -o $@ $^ -O3 #优化方案有三种 -O1 -O2 -O3 ,其中-O3优化等级最高 18 | PHONY:clean 19 | clean: 20 | rm -rf ke_chong_ru 21 | 22 | -------------------------------------------------------------------------------- /my/5class/mask_pending/ke_chong_ru: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoxiao-su/_Linux-OS-Network_/a561603918e0bd1fc57a5fb1f0b980fe5227a2de/my/5class/mask_pending/ke_chong_ru -------------------------------------------------------------------------------- /my/5class/mask_pending/ke_chong_ru.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | int flag = 1;//volatile防止编译器进行优化 4 | void handler(int sig) 5 | { 6 | printf("hello bit\n"); 7 | flag = 0; 8 | } 9 | int main() 10 | { 11 | signal(SIGINT,handler); 12 | while(flag); 13 | } 14 | -------------------------------------------------------------------------------- /my/5class/mask_pending/mask.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | void handler(int sig) 5 | { 6 | printf("catch a sig,signum:%d\n",sig); 7 | exit(1); 8 | } 9 | int show_pending(sigset_t *pending) 10 | { 11 | if(pending == NULL){ 12 | return 0; 13 | } 14 | int i = 1; 15 | int flag = 0; 16 | for(;i<32;i++) 17 | { 18 | if(sigismember(pending,i)) 19 | { 20 | printf("1"); 21 | flag = 1; 22 | }else 23 | { 24 | printf("0"); 25 | } 26 | } 27 | printf("\n"); 28 | return flag; 29 | } 30 | int main() 31 | { 32 | signal(SIGINT,handler);//对信号进行自定义函数处理 33 | sigset_t new; 34 | sigset_t old; 35 | sigset_t pending;//pending表 36 | 37 | sigemptyset(&new);//初始化为全0; 38 | sigemptyset(&old);//初始化为全0; 39 | 40 | sigaddset(&new,SIGINT);//往block表里添加信号有效位 41 | sigprocmask(SIG_SETMASK,&new,&old);//old表保存老的block表的位 42 | while(1){ 43 | sigemptyset(&pending);//初始化pending表 44 | sigpending(&pending);//获取pending表的信号 45 | int ret = show_pending(&pending); 46 | if(ret == 1){ 47 | printf("begin unbrock sig\n"); 48 | sleep(3); 49 | sigprocmask(SIG_SETMASK,&old,NULL);//恢复block表 50 | } 51 | sleep(1); 52 | } 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /my/5class/mask_pending/mask.out: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoxiao-su/_Linux-OS-Network_/a561603918e0bd1fc57a5fb1f0b980fe5227a2de/my/5class/mask_pending/mask.out -------------------------------------------------------------------------------- /my/5class/mask_pending/sighandler: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoxiao-su/_Linux-OS-Network_/a561603918e0bd1fc57a5fb1f0b980fe5227a2de/my/5class/mask_pending/sighandler -------------------------------------------------------------------------------- /my/5class/mask_pending/sighandler.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | void handler(int sig) 5 | { 6 | switch(sig){ 7 | case SIGINT: 8 | printf("catch a signal sigint:%d\n",sig); 9 | break; 10 | case SIGUSR1: 11 | printf("catch a signal sigusr1:%d\n",sig); 12 | break; 13 | default: 14 | break; 15 | } 16 | } 17 | //int main() 18 | //{ 19 | // signal(SIGINT,handler);//捕捉信号 20 | // while(1){ 21 | // printf("hello bit\n"); 22 | // } 23 | // return 0; 24 | //} 25 | 26 | int main() 27 | { 28 | struct sigaction new_act; 29 | memset(&new_act,0,sizeof(new_act)); 30 | new_act.sa_handler = handler; 31 | //new_act.sa_handler = SIG_IGN;//忽略信号处理 32 | sigemptyset(&new_act.sa_mask); 33 | 34 | 35 | sigaction(SIGINT,&new_act,NULL);//也可以捕捉信号 36 | signal(SIGUSR1,handler); 37 | while(1){ 38 | printf("hello bit\n"); 39 | sleep(1); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /my/5class/mask_pending/sleep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoxiao-su/_Linux-OS-Network_/a561603918e0bd1fc57a5fb1f0b980fe5227a2de/my/5class/mask_pending/sleep -------------------------------------------------------------------------------- /my/5class/mask_pending/sleep.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | void alarm_handler(int sig) 6 | {} 7 | 8 | int mysleep(int second) 9 | { 10 | struct sigaction act,oact; 11 | memset(&act,0,sizeof(act)); 12 | memset(&oact,0,sizeof(oact)); 13 | act.sa_handler = alarm_handler;//自定义函数 14 | sigemptyset(&act.sa_mask);//进行清空 15 | sigaction(SIGALRM,&act,&oact); 16 | alarm(second); 17 | pause();//调用自定义函数就会发生出错返回-1 18 | int ret = alarm(0);//取消闹钟,将闹钟清零了 19 | printf("%d\n",ret); 20 | sigaction(SIGALRM,&oact,NULL);//恢复信号处理动作,以免影响原来函数的信号,对函数的顺序执行有一定的影响 21 | return ret;//返回闹钟以前剩余的秒数 22 | } 23 | int main() 24 | { 25 | while(1){ 26 | mysleep(3); 27 | printf("hello bit\n"); 28 | } 29 | return 0; 30 | } 31 | 32 | -------------------------------------------------------------------------------- /my/5class/poll/Makefile: -------------------------------------------------------------------------------- 1 | my_poll:my_poll.c 2 | gcc -o $@ $^ 3 | .PHONY:clean 4 | clean: 5 | rm -rf my_poll 6 | -------------------------------------------------------------------------------- /my/5class/poll/my_poll.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() 6 | { 7 | int timeout = 3000; //大概三秒钟 8 | char buf[1024]; 9 | struct pollfd fd_poll[1]; //设置只有一个事件 10 | while(1){ 11 | fd_poll[0].fd = 0; //关心的是读事件 12 | fd_poll[0].events = POLLIN;//保存用户感兴趣的事件 13 | fd_poll[0].revents = 0; //保存内核返回的就绪事件 14 | memset(buf, '\0', sizeof(buf)); 15 | switch( poll(fd_poll, 1, timeout) ){ 16 | case 0: 17 | perror("timeout!"); 18 | break; 19 | case -1: 20 | perror("poll"); 21 | break; 22 | default: 23 | { 24 | if( fd_poll[0].revents & POLLIN ){//read event ready,检查相同位 25 | gets(buf); 26 | printf("buf : %s\n",buf); 27 | } 28 | } 29 | break; 30 | } 31 | } 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /my/5class/raise/raise.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | raise(8);//出现核心转储,自己给自己发送信号 7 | abort();//自己给自己发送信号 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /my/5class/regular/rule: -------------------------------------------------------------------------------- 1 | aaaa.bbbb.cccc 2 | 192.345.90.567 3 | -------------------------------------------------------------------------------- /my/5class/schedul/schedul.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #shell脚本编写 3 | 4 | bar='' #定义变量不需要类型,不用分号 5 | index=0 6 | 7 | flag=("|" "/" "-" "\\") #定义数组,\ 和下面的 % 都属于特殊字符,所以需要转义 8 | 9 | while [ $index -le 100 ] #while语句进行条件判断 10 | do 11 | pos=index%4 #或者 let pos=index%4 12 | bar=${bar}# # ${bar}是取bar的值 13 | sleep 0.1 14 | printf "[%-100s][%d%%][%c]\r" "${bar}" "${index}" "${flag[pos]}"; 15 | (( index++ )) #或者用let index++ 16 | done 17 | -------------------------------------------------------------------------------- /my/5class/sed/file: -------------------------------------------------------------------------------- 1 | 0 hello world 2 | 1 hello world 3 | 2 hello world 4 | 3 hello world 5 | 4 hello world 6 | 5 hello world 7 | 6 hello world 8 | 7 hello world 9 | 8 hello world 10 | 9 hello world 11 | 12 | tesssssssstwyuaaaa 13 | testesteswyuaaaaaa 14 | wyuaaaaaa 15 | -------------------------------------------------------------------------------- /my/5class/sed/test.sed: -------------------------------------------------------------------------------- 1 | sed '7,9s/.\+/~&~/' file 2 | -------------------------------------------------------------------------------- /my/5class/select/Makefile: -------------------------------------------------------------------------------- 1 | my_select:my_select.c 2 | gcc -o $@ $^ 3 | .PHONY:clean 4 | clean: 5 | rm -rf my_select 6 | -------------------------------------------------------------------------------- /my/5class/select/my_select.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() 7 | { 8 | int max_fd = 1; 9 | fd_set r_set;//可读文件描述符集 10 | fd_set w_set;//可写文件描述符集 11 | while(1){ 12 | FD_ZERO(&r_set);//初始化 13 | FD_ZERO(&w_set);//初始化 14 | 15 | FD_SET(0, &r_set);//将文件描述符0加入文件描述符集中 16 | FD_SET(1,&w_set); 17 | max_fd = 0; 18 | 19 | struct timeval timeout={5, 0}; 20 | switch( select(max_fd+1, &r_set, &w_set, NULL, &timeout)){ 21 | case 0://timeout 22 | printf("time is out!\n"); 23 | break; 24 | case -1://error 25 | perror("select"); 26 | exit(1); 27 | break; 28 | default://success 29 | { 30 | char buf[1024]; 31 | memset(buf, '\0', sizeof(buf)); 32 | if(FD_ISSET(0, &r_set)){//检查文件描述符0是否已经就绪 33 | ssize_t sz = read(0, buf, sizeof(buf)-1); 34 | if( sz > 0 ){ 35 | buf[sz] = '\0'; 36 | printf("read event ready : %s\n",buf); 37 | } 38 | }else if(FD_ISSET(1,&w_set)){//检查文件描述符1是否就绪 39 | char *msg = "this is select test\n"; 40 | write(1, msg, strlen(msg)); 41 | }else{//作为扩展 42 | } 43 | } 44 | break; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /my/5class/select/select_tcp/Makefile: -------------------------------------------------------------------------------- 1 | #my_select:my_select.c 2 | # gcc -o $@ $^ 3 | #.PHONY:clean 4 | #clean: 5 | # rm -rf my_select 6 | 7 | 8 | .PHONY:all 9 | all:select_server select_client 10 | 11 | select_server:select_server.c 12 | gcc -o $@ $^ 13 | select_client:select_client.c 14 | gcc -o $@ $^ 15 | 16 | .PHONY:clean 17 | clean: 18 | rm -rf select_server select_client 19 | 20 | -------------------------------------------------------------------------------- /my/5class/select/select_tcp/select_client: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoxiao-su/_Linux-OS-Network_/a561603918e0bd1fc57a5fb1f0b980fe5227a2de/my/5class/select/select_tcp/select_client -------------------------------------------------------------------------------- /my/5class/select/select_tcp/select_client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | static void usage(const char *proc) 10 | { 11 | printf("%s [ip] [port]",proc); 12 | } 13 | 14 | int main(int argc,char* argv[]) 15 | { 16 | if( argc != 3){ 17 | usage(argv[0]); 18 | return 1; 19 | } 20 | 21 | int sock = socket(AF_INET,SOCK_STREAM,0); 22 | if( sock < 0){ 23 | perror("socket"); 24 | return 1; 25 | } 26 | 27 | int port = atoi(argv[2]); 28 | const char *ip = argv[1]; 29 | struct sockaddr_in remote; 30 | remote.sin_family = AF_INET; 31 | remote.sin_port = htons(port); 32 | remote.sin_addr.s_addr = inet_addr(ip); 33 | 34 | //客户端进行链接,不需要绑定 35 | if(connect(sock, (struct sockaddr*)&remote, sizeof(remote)) < 0){ 36 | perror("connect"); 37 | return 0; 38 | } 39 | 40 | //模拟一次传输信息过程 41 | char buf[1024]; 42 | //while(1){ 43 | memset(buf, '\0', sizeof(buf)); 44 | printf("Please Enter : "); 45 | fflush(stdout); 46 | gets(buf); 47 | write(sock, buf, strlen(buf)); 48 | close(sock); 49 | //} 50 | 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /my/5class/select/select_tcp/select_server: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoxiao-su/_Linux-OS-Network_/a561603918e0bd1fc57a5fb1f0b980fe5227a2de/my/5class/select/select_tcp/select_server -------------------------------------------------------------------------------- /my/5class/select/select_tcp/select_server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | #define _FD_NUM_ 512 11 | #define _FD_DEFAULT_VAL_ -1 12 | 13 | typedef struct _select_fd{ 14 | int max_fd; //记录最大文件描述符 15 | int fd_arr[_FD_NUM_]; //保存放到select监控集中的fd 16 | }select_fd_t; 17 | 18 | //说明正确运行方式 19 | static void usage(const char *proc) 20 | { 21 | printf("%s [ip] [port]\n",proc); 22 | } 23 | 24 | //把fd添加进数组里面,同时更新最大文件描述符 25 | static void add_read_fd(fd_set *set, select_fd_t *select_fd) 26 | { 27 | int i = 0; 28 | for( ;i<_FD_NUM_; i++){ 29 | if( select_fd->fd_arr[i] != _FD_DEFAULT_VAL_ ){ 30 | FD_SET( select_fd->fd_arr[i], set ); 31 | if( select_fd->fd_arr[i] > select_fd->max_fd ){ 32 | select_fd->max_fd = select_fd->fd_arr[i]; 33 | } 34 | } 35 | } 36 | } 37 | 38 | //在数组中为监听到的新的文件描述符分配最小的未被使用的数组下标,来存储 39 | static int add_new_fd(select_fd_t *select_fd, int new_fd) 40 | { 41 | //当数组满了就会添加失败 42 | int i = 1; 43 | for(; i < _FD_NUM_; i++){ 44 | if(select_fd->fd_arr[i] == _FD_DEFAULT_VAL_){ 45 | select_fd->fd_arr[i] = new_fd; 46 | return 0;//yes 47 | } 48 | } 49 | return -1; 50 | } 51 | 52 | //将完成任务的文件描述符从文件描述符集中删除 53 | static void delete_new_fd(select_fd_t *select_fd, int fd ) 54 | { 55 | int i = 1; 56 | for(; i < _FD_NUM_; i++){ 57 | if(select_fd->fd_arr[i] == fd){ 58 | select_fd->fd_arr[i] = _FD_DEFAULT_VAL_; 59 | } 60 | } 61 | } 62 | 63 | //初始化结构体 64 | void init_select_set( select_fd_t *select_fd, int listen_fd ) 65 | { 66 | select_fd->max_fd = listen_fd;//监听新的链接 67 | select_fd->fd_arr[0] = listen_fd; 68 | int i = 1; 69 | for( ;i<_FD_NUM_; i++){ 70 | select_fd->fd_arr[i] = _FD_DEFAULT_VAL_; 71 | } 72 | } 73 | 74 | //读事件就绪后,对数据进行读取 75 | static int read_data_show(int new_fd) 76 | { 77 | char buf[1024]; 78 | ssize_t sz = 0; 79 | int total = 0; 80 | while((sz = read(new_fd, buf+total, 64)) > 0){ 81 | total += sz; 82 | } 83 | if(sz == 0){//success 84 | buf[total] = '\0'; 85 | printf("client data : %s\n",buf); 86 | return 0; 87 | }else if(sz < 0){ 88 | perror("read"); 89 | return -1; 90 | }else{ 91 | //do nothing 92 | } 93 | } 94 | 95 | int start(const char* ip, short port) 96 | { 97 | int sock = socket(AF_INET, SOCK_STREAM, 0); 98 | if( sock < 0 ){ 99 | perror("socket"); 100 | exit(1); 101 | } 102 | //本地信息的填充 103 | struct sockaddr_in local; 104 | local.sin_family = AF_INET; 105 | local.sin_port = htons(port); 106 | local.sin_addr.s_addr = inet_addr(ip);//把点分十进制转化成short int 107 | //绑定链接 108 | if(bind(sock, (struct sockaddr*)&local, sizeof(local)) < 0){ 109 | perror("bind"); 110 | exit(1); 111 | } 112 | //监听链接 113 | if( listen(sock,5) < 0){ 114 | perror("listen"); 115 | exit(1); 116 | } 117 | return sock; 118 | } 119 | 120 | int main(int argc, char* argv[]) 121 | { 122 | if( argc != 3 ){ 123 | usage(argv[1]); 124 | exit(1); 125 | } 126 | int port = atoi(argv[2]); 127 | 128 | int listen_sock = start(argv[1]/*ip*/,port); 129 | if( listen_sock < 0 ){ 130 | perror("start"); 131 | exit(2); 132 | } 133 | // 134 | select_fd_t select_set; 135 | init_select_set(&select_set, listen_sock ); 136 | fd_set r_set;//可读文件描述符的集合 137 | 138 | while(1){ 139 | FD_ZERO(&r_set); 140 | add_read_fd(&r_set, &select_set); 141 | struct timeval timeout={5, 0}; 142 | switch(select(select_set.max_fd+1, &r_set, NULL, NULL, &timeout)){ 143 | case 0://timeout 144 | perror("timeout!"); 145 | break; 146 | case -1://error 147 | perror("select"); 148 | break; 149 | default://success 150 | { 151 | int i = 0; 152 | //遍历数组来确定哪一个文件描述符已经就绪 153 | for(; i < _FD_NUM_; i++){ 154 | int fd = select_set.fd_arr[i]; 155 | if( i == 0 && FD_ISSET(fd, &r_set)){//listen_sock 156 | struct sockaddr_in client; 157 | socklen_t len = sizeof(client); 158 | int new_fd = accept(fd, (struct sockaddr*)&client, &len);//继续监听新的链接 159 | if(new_fd == -1){ 160 | perror("accept"); 161 | continue; 162 | } 163 | if( 0 == add_new_fd(&select_set,new_fd)){//把新的链接加入数组里面 164 | //do nothing 165 | }else{//add error,arr is full 166 | close(fd);//处理不了的链接就直接关闭这个链接 167 | } 168 | continue; 169 | } 170 | if( fd != _FD_DEFAULT_VAL_ && FD_ISSET(fd,&r_set)){ 171 | if( 0 == read_data_show(fd) ){//read success 172 | delete_new_fd(&select_set,fd); 173 | close(fd); 174 | }else{ 175 | //do nothing 176 | } 177 | } 178 | } 179 | } 180 | break; 181 | } 182 | } 183 | return 0; 184 | } 185 | -------------------------------------------------------------------------------- /my/5class/select/select_tcp/start_client.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ./select_client 127.0.0.1 8080 4 | -------------------------------------------------------------------------------- /my/5class/select/select_tcp/start_server.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ./select_server 127.0.0.1 8080 4 | -------------------------------------------------------------------------------- /my/5class/shell/array/array.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #定义数组,shell不支持多维数组,只支持一维数组,可以有字符下标 3 | 4 | arr=('a' 'b' 'c' 'd' 'e') #类似于初始化列表 5 | arr=('aaa' 'bbb' 'ccc' 'd' 'e') #类似于初始化列表 6 | echo ${arr[@]} #打印数组 7 | echo ${arr[*]} #打印数组,两者等价 8 | echo ${#arr[@]} #数组元素个数 9 | echo ${arr[0]} #打印单个字符 10 | echo ${arr[1]} 11 | echo ${arr[2]} 12 | echo ${arr[3]} 13 | echo ${arr[4]} 14 | 15 | for val in ${arr[@]} #在每个元素后面加上_bit 16 | do 17 | echo ${val}_bit 18 | done 19 | 20 | index=0 21 | while [ $index -lt ${#arr[@]} ] 22 | do 23 | echo ${arr[$index]}_bit 24 | (( index++ )) 25 | #index=`expr $index + 1` 26 | done 27 | 28 | #赋值 29 | arr[0]="000" #打印时候,arr[3]、arr[4]没有赋值,故为NULL,此时数组大小为4,只算赋值的元素个数,但是可以访问arr[3]、arr[4] 30 | arr[1]="111" #无论初始化为字符串还是整数。在shell看来都是字符串 31 | arr[2]="222" 32 | arr[5]="555" 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /my/5class/shell/array/fabo.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | one=1 4 | two=1 5 | arr[0]=0 6 | arr[1]=1 7 | index=2 8 | max=$1 9 | 10 | while [ $index -le $max ] 11 | do 12 | let arr[$index+2]=${arr[$index + 1]}+${arr[$index]} 13 | # let sum=$one+$two 14 | # one=$two 15 | # two=$sum 16 | (( index++ )) 17 | done 18 | echo "${arr[$index-1]}" 19 | #echo "$sum" 20 | 21 | 22 | #function sum(){ 23 | # local tmp=$1 24 | # local tmp1 25 | # if [ $1 -eq 1 ];then 26 | # r=1 27 | # elif 28 | # tmp1=`expr ${tmp} - 1` 29 | # sum $tmp1 30 | # r=`expr $r + $tmp` 31 | # fi 32 | #} 33 | # 34 | #sum $1 35 | #echo $r 36 | -------------------------------------------------------------------------------- /my/5class/shell/array/max_min.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | proc=${basenanme $0} 4 | 5 | function usage(){ 6 | echo "Usage:${proc}data1....." 7 | exit 1 8 | } 9 | 10 | [ $# -lt 1 ] && usage 11 | 12 | min=$1 #第一个参数 13 | max=$1 14 | sum=0 15 | 16 | for val in $@ 17 | do 18 | if [ $min -gt $val ];then 19 | min=$val 20 | fi 21 | if [ $max -lt $val ];then 22 | max=$val 23 | fi 24 | let sum+=$val 25 | done 26 | 27 | echo "max = ${max}" 28 | echo "min = ${min}" 29 | echo "sum = ${sum}" 30 | #echo "ibase=10,scale=2"#10进制和精度 31 | #echo $? 32 | -------------------------------------------------------------------------------- /my/5class/shell/array/sum.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | sum=100 4 | 5 | function Sum(){ 6 | local total=0 #虽然在函数内但却是全局变量,加上local则变成局部变量 7 | 8 | } 9 | -------------------------------------------------------------------------------- /my/5class/shell/basic/shell1: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | str="sulijuan" 4 | val=10 5 | f_val=3.14 6 | 7 | echo "str = ${str} Is a Student" 8 | echo "val = ${val}" 9 | echo "f_val = ${f_val}" 10 | 11 | fun(){ 12 | echo "fun()" 13 | } 14 | 15 | fun 16 | 17 | while : 18 | do 19 | echo "hello" 20 | sleep 1 21 | done 22 | -------------------------------------------------------------------------------- /my/5class/shell/fun/func.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | #function是指明fun十一个函数,起到的作用只是直观就知道fun是一个函数而已,不加也可以的 5 | #function fun(){ 6 | # echo "This Is a Function" 7 | #} 8 | #fun #函数的调用 9 | 10 | function fun(){ 11 | echo $1 12 | echo $2 13 | echo $3 14 | echo $@ 15 | echo $$ 16 | echo $! 17 | echo "this is a function" 18 | } 19 | fun a b c d #函数的传参数 20 | 21 | #fun "hello""good" #传字符串 22 | 23 | 24 | #function fun(){ 25 | # echo 1 #函数中的echo语句不多时候,可以使用echo返回值 26 | # echo "this is a function" 27 | # #return 100 #当函数中echo语句比较多就无法确定哪一个是返回值,此时就用return,建议都使用return返回值 28 | #} 29 | #ret=$(fun) #或者ret=`fun` 30 | #echo $ret 31 | -------------------------------------------------------------------------------- /my/5class/shell/mk_dir/mk_dir.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | function umage(){ 4 | echo "" 5 | } 6 | 7 | function exist_dir(){ 8 | dir=$1 9 | basename $0 10 | } 11 | for dir in $@ #$@是当前参数列表 12 | do 13 | if exist_dir "$dir";then 14 | echo "${dir} is exist,break" 15 | exit 1 16 | elif 17 | echo "${dir} is no exist,creat it" 18 | mkdir "${dir}" 19 | fi 20 | done 21 | -------------------------------------------------------------------------------- /my/5class/shell/other/other.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo $0 #可执行脚本的名称 4 | echo $1 $2 $3 #命令行第一、二、三个参数 5 | echo $# #参数个数,不输入任何数时shell里是0(不包括可执行文件名),argc为1(此时的1是可执行文件名的计数) 6 | echo $$ #当前shell进程的PID 7 | echo $! #但前shell脚本里面离$!最近的后台进程的PID 8 | echo $@ #参数列表 9 | echo $? #退出码 10 | ############ 11 | echo $0 #可执行文件 12 | echo $1 $2 $3 #命令行第一、二、三个参数 13 | echo $# #参数个数,不输入任何数时shell里是0(不包括可执行文件名),argc为1(此时的1是可执行文件名的计数) 14 | ./back_proc 15 | sleep1 16 | ./back_proc #此时$!打印的是这个进程的PID 17 | sleep1 18 | echo $$ #当前shell进程的PID 19 | echo $! #但前shell脚本里面离$!最近的后台进程的PID 20 | echo $@ #参数列表 21 | echo $? #退出码 22 | ############ 23 | shift 1 #shift 2:改变当前参数列表的值(移位) 24 | echo "$1" 25 | echo "$2" 26 | echo "$3" 27 | echo "$4" 28 | sum=0 29 | for val in $@ 30 | do 31 | let sum+=val 32 | echo "$sum" 33 | done 34 | -------------------------------------------------------------------------------- /my/5class/shell/passwd/passwd.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | read passwd 4 | count=0 5 | while [ ! $"X${passwd}" == "Xyes" ] 6 | do 7 | let count++ 8 | if [ $count -gt 5 ];then 9 | echo "you have try 5 times,sorry!" 10 | exit 1 11 | fi 12 | echo "Please try again" 13 | read passwd 14 | done 15 | echo "success!" 16 | -------------------------------------------------------------------------------- /my/5class/shell/process/add.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int g_val; 5 | int g_arr[3] = {0}; 6 | 7 | void fun() 8 | { 9 | printf("hello world\n"); 10 | } 11 | 12 | int main() 13 | { 14 | static int a = 10; 15 | 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /my/5class/shell/process/file.c: -------------------------------------------------------------------------------- 1 | #include 2 | #incldue 3 | #include 4 | int main() 5 | { 6 | printf("hello world\n,%d,%d\n",getpid(),getppid()); 7 | //当前进程的创建者始终不会改变,而创建的进程一直在改变 8 | sleep(1); 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /my/5class/shell/string/file: -------------------------------------------------------------------------------- 1 | 123abc456 2 | 123abc456 3 | 123abc456 4 | 123abc456 5 | 6 | -------------------------------------------------------------------------------- /my/5class/shell/string/log: -------------------------------------------------------------------------------- 1 | 456ABC123 2 | 456ABC123 3 | 456ABC123 4 | 456ABC123 5 | 6 | -------------------------------------------------------------------------------- /my/5class/shell/string/string.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #输出重定向>、输入重定向< 4 | 5 | g_file=file 6 | while read line 7 | do 8 | #echo $line 9 | part1=$(echo $line | cut -c 1-3) 10 | part2=$(echo $line | cut -c 4-6 | tr '[a-z]' '[A-Z]') 11 | part3=$(echo $line | cut -c 7-9) 12 | echo "${part3}""${part2}""${part1}" #>>log追加重定向,要不然会覆盖 13 | sleep 1 14 | #done<${g_file} 15 | donelog 16 | -------------------------------------------------------------------------------- /my/5class/shell/test/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #read val 3 | #test $val -eq 0 4 | #echo $? 5 | #[ $val -eq 0 ] 6 | #echo $? 7 | #if test $val -eq 0;then 8 | # echo "girl" 9 | #else 10 | # echo "boy" 11 | #fi 12 | read sex 13 | 14 | if [ "X$sex" == "Xman" ];then #加入X是为了防止sex是空串,两个命令写在一起要用分号隔开,shell下的判断语句没有{}符号, 15 | echo "hello boy" 16 | elif [ "X$sex" == "Xwomen" ];then #注意这里的elif 17 | echo "hello girl" 18 | else 19 | echo "unknow" 20 | fi #语句是以fi结束的 21 | 22 | 23 | val="" 24 | [ "X$val" == "Xboy" ] #使用=也可以进行比较,但是建议使用== 25 | echo $? 26 | [ -d "./log" ] # 判断当前目录底下是否有log这个目录,-f判断是否有该文件 27 | echo $? 28 | 29 | if [ -d "./log" ];then 30 | echo "log Is dir" 31 | fi 32 | 33 | if [ -f "file" ];then 34 | echo "file Is file" 35 | fi 36 | 37 | if [ -f "file1" ];then 38 | : #这是一条空语句,什么操作也不做,但是冒号不可以去掉,不像c语言 39 | fi 40 | 41 | 42 | if :;then 43 | echo ": is always true" 44 | fi 45 | 46 | [ ! -d "./log" ] || { #相当于if else 47 | echo "dir Is dir" 48 | } 49 | 50 | [ -f "file" ] && { #相当于 if then 51 | echo "file Is file" 52 | } 53 | #&&和||用于连接两个命令,而-a和-o仅用于在测试表达式中连接两个测试条件 54 | 55 | read val1 #读入一个变量 56 | read val2 57 | [ $val1 -eq 0 -a $val2 -eq 1] #-a 在两个条件之间表示逻辑与&& 58 | echo $? 59 | 60 | [ $val1 -eq 0 -o $val2 -eq 1] #-o 在两个条件之间表示逻辑或|| 61 | echo $? 62 | 63 | 64 | #整数比较:是否相等(-eq),大于(-gt),大于等于(-ge),小于(-lt),小于等于(-le) 65 | #在shell脚本下:0表示真,非0为假 66 | #$? 取到test的返回值 67 | 68 | 69 | #case语句,与c语言中的switch,case语句的不同在于:c语言中的switch语句只能判断字符或者数字,而shell中的case语句什么都可以判断,比如指针、结构体、正则表达式、 70 | read val3 71 | case $val3 in 72 | 'a' ) 73 | echo "a" 74 | ;; 75 | 'b' ) 76 | echo "b" 77 | ;; 78 | '*' ) 79 | echo "*" 80 | ;; 81 | "start" ) 82 | echo "This is start" 83 | "stop"|"start" ) #其一满足就执行该语句 84 | echo "this is stop and start" 85 | ;; 86 | esac 87 | 88 | 89 | echo $0 $1 $2 $3 #$0是可执行文件名称、$1是第一个命令参数...类似于main函数里的char* argv[] 90 | $0 91 | -------------------------------------------------------------------------------- /my/5class/shell/while/while.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #while循环 4 | #read count 5 | #index=0 6 | #while [ &{index} -le &{count} ] 7 | #do 8 | # echo &index 9 | # #let index++ 10 | # ((index++)) 11 | #done 12 | 13 | #for循环 14 | #read count1 15 | ##for count1 in {a..z} 16 | #for count1 in {1..100} 17 | #do 18 | # sleep 1 19 | # echo $count1 20 | #done 21 | 22 | for count1 in $# 23 | do 24 | sleep 1 25 | echo $count1 26 | done 27 | 28 | 29 | ##另一种形式的for循环 30 | #read top 31 | #for (( i=0;i<$top ;i++ )) #若是空循环,不执行任何语句,就在do和done中间加一个分号: 32 | #do 33 | # sleep 1 34 | # echo $top 35 | #done 36 | 37 | #do--while循环 38 | #read top 39 | #count=0 40 | #until [ ${count} -ge ${top} ];do #知道count大于等于top,要不然就输出count 41 | # echo $count 42 | # let count++ 43 | #done 44 | 45 | #for循环怎么写死循环 46 | #for (( ; ; )) 47 | #do 48 | # sleep 1 49 | # echo "dead" 50 | #done 51 | 52 | #while语句怎么写死循环 53 | #while : #:表示恒成立 54 | #do 55 | # echo "dead" 56 | #done 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /my/5class/socket/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY:all 2 | all:server client 3 | server:server.c 4 | gcc -o $@ $^ 5 | client:client.c 6 | gcc -o $@ $^ -lpthread 7 | .PHONY:clean 8 | clean: 9 | rm -rf client server 10 | -------------------------------------------------------------------------------- /my/5class/socket/client: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoxiao-su/_Linux-OS-Network_/a561603918e0bd1fc57a5fb1f0b980fe5227a2de/my/5class/socket/client -------------------------------------------------------------------------------- /my/5class/socket/client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | static void usage() 9 | { 10 | printf("./client [remote_ip] [remote_port]\n"); 11 | } 12 | 13 | int main(int argc,char *argv[]) 14 | { 15 | if(argc != 3){ 16 | return -1; 17 | } 18 | short port = atoi(argv[2]); 19 | int conn_fd = socket(AF_INET,SOCK_STREAM,0); 20 | if(conn_fd == -1){ 21 | perror("socket"); 22 | return -1; 23 | } 24 | struct sockaddr_in remote; 25 | //memset(); 26 | remote.sin_family = AF_INET; 27 | remote.sin_port = htons(port); 28 | inet_aton(argv[1],&remote.sin_addr); 29 | if(connect(conn_fd,(struct sockaddr*)&remote,sizeof(remote)) == -1){ 30 | perror("conet"); 31 | close(conn_fd); 32 | return -1; 33 | } 34 | printf("connet seccess...\n"); 35 | char buf[1024]; 36 | while(1){ 37 | memset(buf,'\0',sizeof(buf)); 38 | printf("Please Enter :> "); 39 | gets(buf); 40 | if(strncasecmp("quit",buf, 4) == 0){ 41 | break; 42 | } 43 | fflush(stdout); 44 | write(conn_fd,buf,sizeof(buf)); 45 | ssize_t sz = read(conn_fd,buf,sizeof(buf)); 46 | if(sz > 0){ 47 | buf[sz] = '\0'; 48 | printf("echo data:%s\n",buf); 49 | } 50 | } 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /my/5class/socket/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main() 3 | { 4 | return 0; 5 | } 6 | -------------------------------------------------------------------------------- /my/5class/socket/server: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoxiao-su/_Linux-OS-Network_/a561603918e0bd1fc57a5fb1f0b980fe5227a2de/my/5class/socket/server -------------------------------------------------------------------------------- /my/5class/socket/server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | //基于流式tcp 12 | 13 | void recycle(int sig){//捕获信号 14 | pid_t id; 15 | while((id = waitpid(-1,NULL,WNOHANG)) > 0){ 16 | printf("wait child %d\n",id); 17 | } 18 | } 19 | static void usage() 20 | { 21 | printf("%s [ip] [port]\n"); 22 | } 23 | int start(char* ip,short port)//成功的话返回sock,否则返回-1 24 | { 25 | //step 1 26 | int sock_fd = socket(AF_INET,SOCK_STREAM,0);//IPV4协议,流式套接,创建套接,成功返回新的套接,否则返回-1 27 | if(sock_fd == -1){ 28 | perror("socket"); 29 | return -1; 30 | } 31 | //step 2 32 | struct sockaddr_in local;//绑定本地信息 33 | local.sin_family = AF_INET; 34 | local.sin_port = htons(port);//将主机序列转换成网络序列,host -> net 35 | inet_aton(ip,&local.sin_addr);//ip -> int 36 | if(bind(sock_fd,(struct sockaddr*)&local,sizeof(local)) == -1){ 37 | perror("bind");//绑定 38 | return -1; 39 | } 40 | //step 3 41 | if(listen(sock_fd,5) == -1){//监听,当我去accept新的链接时候,最多稚嫩观看到5个链接,维护系统的开销 42 | perror("listen"); 43 | return -1; 44 | } 45 | return sock_fd; 46 | } 47 | void echo_data(int new_sock) 48 | { 49 | while(1){ 50 | char buf[1024]; 51 | memset(buf,'\0',sizeof(buf)); 52 | ssize_t sz = read(new_sock,buf,sizeof(buf)-1); 53 | if(sz > 0){ 54 | buf[sz] = '\0'; 55 | write(new_sock,buf,strlen(buf)); 56 | printf("%s\n",buf); 57 | }else if(sz == 0){ 58 | printf("client is close\n"); 59 | close(new_sock); 60 | break; 61 | }else{ 62 | break; 63 | } 64 | } 65 | } 66 | static void *service(void *arg) 67 | {//方法三:线程 68 | printf("thread is create && detach success\n"); 69 | pthread_detach(pthread_self()); 70 | int new_sock = (int)arg; 71 | echo_data(new_sock); 72 | } 73 | int main(int argc,char *argv[]) 74 | { 75 | if(argc != 3){ 76 | usage(); 77 | return 1; 78 | } 79 | int port = atoi(argv[2]);//string -> int 80 | int listen_sock = start(argv[1],port); 81 | if(listen_sock == -1){ 82 | return -1; 83 | } 84 | //signal(SIGCHLD,recycle);//多进程的捕捉信号 85 | signal(SIGCHLD,SIG_IGN);//若信号SIGCHLD,则忽略它 86 | while(1) 87 | { 88 | //step 4 89 | struct sockaddr_in remote;//定义用户缓冲区 90 | memset(&remote,'\0',sizeof(remote)); 91 | socklen_t len = sizeof(remote);//用户缓冲区的大小 92 | int new_sock = accept(listen_sock,(struct sockaddr*)&remote,&len);//得到新的套接,底层已经把对端链接好了,所以取到新的套接就直接可以保证数据有序可靠的传输 93 | if(new_sock < 0) 94 | { 95 | perror("accept"); 96 | }else{ 97 | //线程使用套接 98 | printf("get a new client\n"); 99 | pthread_t tid; 100 | int ret = pthread_create(&tid,NULL,service,(void*)new_sock); 101 | if(ret == 0){ 102 | perror("pthread_create"); 103 | return -1; 104 | } 105 | //方法二:创建进程,多进程间使用套接字 106 | // printf("get a new client\n"); 107 | // pid_t id = fork(); 108 | // if(id == 0){//子进程 109 | // close(listen_sock); 110 | // while(1){ 111 | // char buf[1024]; 112 | // memset(buf,'\0',sizeof(buf)); 113 | // ssize_t sz = read(new_sock,buf,sizeof(buf)); 114 | // if(sz > 0){ 115 | // buf[sz] = '\0'; 116 | // write(new_sock,buf,strlen(buf)); 117 | // printf("%s\n",buf); 118 | // }else if(sz == 0){ 119 | // printf("client is close\n"); 120 | // close(new_sock); 121 | // break; 122 | // }else{ 123 | // 124 | // } 125 | // } 126 | // exit(0); 127 | // }else{//父进程 128 | // 129 | // } 130 | } 131 | //方法一:单进程间使用套接字 132 | // while(1){ 133 | // char buf[1024]; 134 | // memset(buf,'\0',sizeof(buf)); 135 | // ssize_t sz = read(new_sock,buf,sizeof(buf)); 136 | // if(sz > 0){ 137 | // buf[sz] = '\0'; 138 | // write(new_sock,buf,strlen(buf)); 139 | // printf("%s\n",buf); 140 | // }else if(sz == 0){ 141 | // printf("client is close\n"); 142 | // close(new_sock); 143 | // break; 144 | // }else{ 145 | // 146 | // } 147 | // } 148 | // } 149 | } 150 | return 0; 151 | } 152 | -------------------------------------------------------------------------------- /my/5class/socketpair/Makefile: -------------------------------------------------------------------------------- 1 | my_socketpair:my_socketpair.c 2 | gcc -o $@ $^ -D_DEBUG_ 3 | .PHONY:ckean 4 | clean: 5 | rm -rf my_socketpair 6 | -------------------------------------------------------------------------------- /my/5class/socketpair/my_socketpair.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() 7 | { 8 | int fd[2] = {0,0}; 9 | int ret = socketpair(AF_UNIX,SOCK_STREAM,0,fd);//创建双向通信的管道,使用unix域间套接字和面向字节流服务 10 | if( ret < 0 ){ 11 | perror("socketpair"); 12 | return 1; 13 | } 14 | #ifdef _DEBUG_ 15 | printf("fd0 : %d\n",fd[0]); 16 | printf("fd1 : %d\n",fd[1]); 17 | #endif 18 | pid_t id = fork(); 19 | if( id < 0 ){ 20 | perror("fork"); 21 | return 2; 22 | }else if( id == 0 ){//child 23 | close(fd[1]);//use fd[0] for read and write 24 | char *msg_c = "i know"; 25 | char buf[256]; 26 | while(1){ 27 | //1.write 28 | write(fd[0],msg_c,strlen(msg_c)); 29 | //2.read 30 | ssize_t sz = read(fd[0],buf, sizeof(buf)-1); 31 | buf[sz] = '\0'; 32 | //3.printf 33 | printf("child : %d , %s\n",getpid(),buf); 34 | sleep(1); 35 | } 36 | }else{//father 37 | close(fd[0]);//use fd[1] for read and write 38 | char buf[256]; 39 | char *msg_f = "i am your father"; 40 | while(1){ 41 | //1.read 42 | ssize_t sz = read(fd[1], buf, sizeof(buf)-1); 43 | buf[sz] = '\0'; 44 | //2.printf 45 | printf("father : %d , %s\n",getpid(),buf); 46 | //3.write 47 | write(fd[1], msg_f, strlen(msg_f)); 48 | sleep(1); 49 | } 50 | } 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /my/5class/tty/tty.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main() 3 | { 4 | 5 | return 0; 6 | } 7 | 8 | -------------------------------------------------------------------------------- /my/6class/FILE/Makefile: -------------------------------------------------------------------------------- 1 | file_fd.out:file_fd.c 2 | gcc -o $@ $^ 3 | PHONY:clean 4 | clean: 5 | rm -rf file_fd.out 6 | -------------------------------------------------------------------------------- /my/6class/FILE/dup_dup2.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoxiao-su/_Linux-OS-Network_/a561603918e0bd1fc57a5fb1f0b980fe5227a2de/my/6class/FILE/dup_dup2.c -------------------------------------------------------------------------------- /my/6class/FILE/file_fd.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | int main() 8 | { 9 | int fd1 = open("./log",O_RDWR); 10 | printf("fd1 = %d\n",fd1); 11 | int copyfd = dup(fd1); 12 | printf("copyfd = %d\n",copyfd); 13 | if(fd1 == -1){ 14 | printf("open error\n"); 15 | exit(1); 16 | } 17 | char *str = "hello bit\n"; 18 | int count = 0; 19 | while(count<20){ 20 | write(fd1,str,sizeof(str)); 21 | count++; 22 | } 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /my/6class/FILE/file_fd.out: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoxiao-su/_Linux-OS-Network_/a561603918e0bd1fc57a5fb1f0b980fe5227a2de/my/6class/FILE/file_fd.out -------------------------------------------------------------------------------- /my/6class/FILE/log: -------------------------------------------------------------------------------- 1 | hellhellhellhellhellhellhellhellhellhellhellhellhellhellhellhellhellhellhellhell -------------------------------------------------------------------------------- /my/6class/Gdb/SeqList.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | template 5 | class SeqList 6 | { 7 | private 8 | } 9 | -------------------------------------------------------------------------------- /my/6class/c_schedul/a.out: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoxiao-su/_Linux-OS-Network_/a561603918e0bd1fc57a5fb1f0b980fe5227a2de/my/6class/c_schedul/a.out -------------------------------------------------------------------------------- /my/6class/c_schedul/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | //基于C语言的进度条 3 | int main() 4 | { 5 | char ch[] = "hello a"; 6 | int index = 0; 7 | while(index<26) 8 | { 9 | printf("%s\r",ch); 10 | ch[6] += 1; 11 | fflush(stdout); 12 | index++; 13 | sleep(1); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /my/6class/c_schedul/main.out: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoxiao-su/_Linux-OS-Network_/a561603918e0bd1fc57a5fb1f0b980fe5227a2de/my/6class/c_schedul/main.out -------------------------------------------------------------------------------- /my/6class/c_schedul/main1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | int count = 0; 7 | const char* lable = "|/-\\"; 8 | char buf[51]; 9 | //多开辟一个字节用来存放‘\0’ 10 | memset(buf,'\0',sizeof(buf)); 11 | while(count<=50) 12 | { 13 | printf("[%-50s][%d%%][%c]\r",buf,count,lable[count%4]); 14 | fflush(stdout); 15 | usleep(100000); 16 | buf[count] = '#'; 17 | count++; 18 | } 19 | printf("\n"); 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /my/6class/c_schedul/main1.out: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoxiao-su/_Linux-OS-Network_/a561603918e0bd1fc57a5fb1f0b980fe5227a2de/my/6class/c_schedul/main1.out -------------------------------------------------------------------------------- /my/6class/ctags/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main() 3 | { 4 | fun(); 5 | return 0; 6 | } 7 | -------------------------------------------------------------------------------- /my/6class/ctags/main.c~: -------------------------------------------------------------------------------- 1 | #include 2 | int main() 3 | { 4 | fun(); 5 | return 0; 6 | } 7 | -------------------------------------------------------------------------------- /my/6class/ctags/my_test.c: -------------------------------------------------------------------------------- 1 | include "my_test.h" 2 | void fun() 3 | { 4 | printf("hello world\n"); 5 | } 6 | -------------------------------------------------------------------------------- /my/6class/ctags/my_test.h: -------------------------------------------------------------------------------- 1 | #include 2 | void fun(); 3 | -------------------------------------------------------------------------------- /my/6class/ctags/tags: -------------------------------------------------------------------------------- 1 | !_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/ 2 | !_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/ 3 | !_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/ 4 | !_TAG_PROGRAM_NAME Exuberant Ctags // 5 | !_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/ 6 | !_TAG_PROGRAM_VERSION 5.8 // 7 | fun my_test.c /^void fun()$/;" f 8 | -------------------------------------------------------------------------------- /my/6class/exec/Makefile: -------------------------------------------------------------------------------- 1 | DST:exec 2 | SOU:exec.c 3 | 4 | $(DST):$(SOU) 5 | gcc -o $@ $^ 6 | .PHONY:clean 7 | clean: 8 | rm -rf $(DST) 9 | -------------------------------------------------------------------------------- /my/6class/exec/bin/Makefile: -------------------------------------------------------------------------------- 1 | com.out:com.c 2 | gcc -o com.out com.c 3 | .PHONY:clean 4 | clean: 5 | rm -rf com.out 6 | -------------------------------------------------------------------------------- /my/6class/exec/bin/com.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | int main() 6 | { 7 | //putenv("PATH=bin/com"); 8 | printf("pid:%d,ppid:%d\n",getpid(),getppid()); 9 | printf("get PATH : %s\n",getenv("PATH"));//获取环境变量 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /my/6class/exec/bin/com.out: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoxiao-su/_Linux-OS-Network_/a561603918e0bd1fc57a5fb1f0b980fe5227a2de/my/6class/exec/bin/com.out -------------------------------------------------------------------------------- /my/6class/exec/exec.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | int main(int argc,char* argv[]) 5 | { 6 | pid_t id = fork(); 7 | if(id == 0){ 8 | execl("/bin/ls","ls","-al","../exec",NULL);//如果execl函数执行成功,就不会执行printf语句,没有返回 9 | 10 | execlp("com.out","com.out",NULL);//将从根目录起到当前文件的路径如/home/xiaoxiaosu/class/6class/exec/bin(com.out在bin目录底下)添加到PATH即可,函数名带p,表示运行时在环境变量下查找适用路径 11 | //execlp(argv[1],argv[1],argv[2],NULL);//通过命令行传参数 12 | 13 | char* argv[] = {"ls","-al","./bin",NULL}; 14 | char* my_env[] = {"PATH=/I/AM/PATH",NULL}; 15 | execle("/home/xiaoxiaosu/class/6class/exec/bin/com.out","com.out",NULL,my_env); 16 | //execle("/bin/ls","ls","-al","./bin",my_env,NULL); 17 | 18 | execv("/bin/ls",argv); 19 | 20 | execvp("/bin/ls",argv); 21 | execve("/bin/ls",argv,my_env); 22 | 23 | printf("haha,I am here...\n");//当execl执行错误才会输出这条语句 24 | perror("error"); 25 | exit(0); 26 | }else{ 27 | wait(NULL); 28 | } 29 | return 0; 30 | } 31 | 32 | //以上主函数中的execl、execlp、execle、execv、execvp、execve函数不能同存 33 | 34 | -------------------------------------------------------------------------------- /my/6class/exec/exec.out: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoxiao-su/_Linux-OS-Network_/a561603918e0bd1fc57a5fb1f0b980fe5227a2de/my/6class/exec/exec.out -------------------------------------------------------------------------------- /my/6class/fifo/Makefile: -------------------------------------------------------------------------------- 1 | SER=server 2 | CLI=client 3 | 4 | .PHONY:all 5 | all:$(SER) $(CLI) 6 | 7 | $(SER):server.c 8 | gcc -o $@ $^ 9 | $(CLI):client.c 10 | gcc -o $@ $^ 11 | .PHONY:clean 12 | clean: 13 | rm -rf $(SER) $(CLI) 14 | -------------------------------------------------------------------------------- /my/6class/fifo/client: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoxiao-su/_Linux-OS-Network_/a561603918e0bd1fc57a5fb1f0b980fe5227a2de/my/6class/fifo/client -------------------------------------------------------------------------------- /my/6class/fifo/client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | int main() 7 | { 8 | int fd = open("fifo_pipe",O_WRONLY,0);//以只写的方式打开 9 | if(fd < 0){ 10 | perror("error"); 11 | return 2; 12 | } 13 | char buf[1024]; 14 | while(1){ 15 | printf("client Enter :"); 16 | fflush(stdout); 17 | memset(buf,'\0',sizeof(buf)); 18 | fgets(buf,sizeof(buf)-1,stdin); 19 | buf[strlen(buf)-1] = '\0'; 20 | write(fd,buf,strlen(buf)); 21 | if(strcasecmp(buf,"Quit") == 0){//忽略大小写 22 | break; 23 | } 24 | } 25 | close(fd); 26 | printf("client Quit\n"); 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /my/6class/fifo/server: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoxiao-su/_Linux-OS-Network_/a561603918e0bd1fc57a5fb1f0b980fe5227a2de/my/6class/fifo/server -------------------------------------------------------------------------------- /my/6class/fifo/server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | int main() 7 | { 8 | if(mkfifo("/home/xiaoxiaosu/class/6class/fifo/fifo_pipe",0666|S_IFIFO) < 0){ 9 | perror("error"); 10 | return 1; 11 | } 12 | int fd = open("fifo_pipe",O_RDONLY,0);//以只读的方式打开命名管道 13 | printf("open file success\n"); 14 | if(fd < 0){ 15 | perror("error"); 16 | } 17 | char buf[1024]; 18 | while(1){ 19 | memset(buf,'\0',sizeof(buf)); 20 | int len = read(fd,buf,sizeof(buf)-1); 21 | if(len > 0){ 22 | printf("client say : %s\n",buf); 23 | } 24 | if(strcasecmp("Quit",buf) == 0){//忽略大小写的quit 25 | break; 26 | } 27 | } 28 | close(fd); 29 | printf("server Quit\n"); 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /my/6class/fork/Makefile: -------------------------------------------------------------------------------- 1 | #fork.out:fork.c 2 | # gcc -o fork.out fork.c -g 3 | #PHONY:clean 4 | #clean: 5 | # rm -rf fork.out 6 | 7 | 8 | vfork:vfork.c 9 | gcc -o vfork vfork.c -g 10 | PHONY:clean 11 | clean: 12 | rm -rf vfork 13 | -------------------------------------------------------------------------------- /my/6class/fork/errno.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | int i = 0; 7 | for(;i<128;i++) 8 | { 9 | //errno = i;//标准C提供给我们的一个全局变量 10 | //perror("errno:"); 11 | printf("%d,%s\n",i,strerror(i)); 12 | } 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /my/6class/fork/errno.out: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoxiao-su/_Linux-OS-Network_/a561603918e0bd1fc57a5fb1f0b980fe5227a2de/my/6class/fork/errno.out -------------------------------------------------------------------------------- /my/6class/fork/file: -------------------------------------------------------------------------------- 1 | hello bit 2 | uid:500,euid:500,gid:500,egid:500 3 | child:pid:21209,ppid:21208,val:1,&val:0xbfec7b78,g_val:1,&g_val:0x8049a48 4 | hello bit 5 | uid:500,euid:500,gid:500,egid:500 6 | father:pid:21208,ppid:20431,val:0,&val:0xbfec7b78,g_val:0,&g_val:0x8049a48 7 | -------------------------------------------------------------------------------- /my/6class/fork/fork.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | char *msg = "hello bit"; 6 | int g_val = 0;//父子进程看起来像是共享同一全局变量,实则并非如此 7 | int main() 8 | { 9 | printf("%s\n",msg); 10 | int val = 0; 11 | printf("uid:%d,euid:%d,gid:%d,egid:%d\n",getuid(),geteuid(),getgid(),getegid()); 12 | pid_t id = fork(); 13 | if(id < 0){ 14 | printf("fork error\n"); 15 | exit(1); 16 | }else if(id == 0){ 17 | val++; 18 | g_val++; 19 | printf("child:pid:%d,ppid:%d,val:%d,&val:0x%x,g_val:%d,&g_val:0x%x\n",getpid(),getppid(),val,&val,g_val,&g_val); 20 | }else{ 21 | sleep(1); 22 | printf("father:pid:%d,ppid:%d,val:%d,&val:0x%x,g_val:%d,&g_val:0x%x\n",getpid(),getppid(),val,&val,g_val,&g_val); 23 | sleep(3); 24 | } 25 | return 0; 26 | } 27 | 28 | //分析在fork前执行语句printf("%s\n",msg);重定向到文件中会出现什么结果? 29 | //gcc -o fork fork.c 后执行./fork >file,即输出重定向到文件里面,则输出缓冲由行缓冲变成全缓冲,即子进程拥有一份缓冲区的拷贝,父进程也有一份缓冲区的拷贝,当子进程执行完return后,刷新自己的缓冲区,当父进程return后也刷新自己的缓冲区,所以此时虽然只有一条printf语句,但是当输出重定向到文件里面就会出现两条hello bit语句,若程序运行输出到终端上,就只会出现一条hello bit(行缓冲) 30 | -------------------------------------------------------------------------------- /my/6class/fork/vfork: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoxiao-su/_Linux-OS-Network_/a561603918e0bd1fc57a5fb1f0b980fe5227a2de/my/6class/fork/vfork -------------------------------------------------------------------------------- /my/6class/fork/vfork.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | int g_val = 0;//父子进程共享一个全局变量 7 | int main() 8 | { 9 | int val = 0; 10 | pid_t id = vfork(); 11 | if(id < 0){ 12 | printf("vfork error\n"); 13 | exit(1); 14 | }else if(id == 0){ 15 | val++; 16 | sleep(2); 17 | g_val++; 18 | printf("child:pid:%d,ppid:%d,val:%d,&val:0x%x,g_val:%d,&g_val:0x%x\n",getpid(),getppid(),val,&val,g_val,&g_val); 19 | exit(0);//当子进程exec或者exit后,父进程才能执行相关操作 20 | }else{ 21 | sleep(5); 22 | printf("father:pid:%d,ppid:%d,val:%d,&val:0x%x,g_val:%d,&g_val:0x%x\n",getpid(),getppid(),val,&val,g_val,&g_val); 23 | } 24 | return 0; 25 | } 26 | 27 | 28 | -------------------------------------------------------------------------------- /my/6class/id/Makefile: -------------------------------------------------------------------------------- 1 | #seqlist.out:seqlist.cpp 2 | # g++ -o seqlist.out seqlist.cpp -g 3 | #PHONY:clean 4 | #clean: 5 | # rm -rf seqlist.out 6 | read_write.out:read_write.c 7 | gcc -o read_write.out read_write.c 8 | PHONY:clean 9 | clean: 10 | rm -rf read_write.out 11 | -------------------------------------------------------------------------------- /my/6class/id/id.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | int main() 5 | { 6 | pid_t id = fork(); 7 | if(id<0){ 8 | printf("fork erroe\n"); 9 | exit(1); 10 | } 11 | else if(id == 0){ 12 | printf("child:\npid:%d\nppid:%d\nuid:%d\neuid:%d\ngid:%d\negid:%d\n",getpid(),getppid(),getuid(),geteuid(),getgid(),getegid()); 13 | }else{ 14 | printf("father:\npid:%d\nppid:%d\nuid:%d\neuid:%d\ngid:%d\negid:%d\n",getpid(),getppid(),getuid(),geteuid(),getgid(),getegid()); 15 | } 16 | printf("i am a student\n"); 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /my/6class/id/id.out: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoxiao-su/_Linux-OS-Network_/a561603918e0bd1fc57a5fb1f0b980fe5227a2de/my/6class/id/id.out -------------------------------------------------------------------------------- /my/6class/id/log: -------------------------------------------------------------------------------- 1 | hello worldhello worldhello worldhello worldhello worldhello worldhello worldhello worldhello worldhello worldhello worldhello worldhello worldhello worldhello worldhello worldhello worldhello worldhello worldhello world -------------------------------------------------------------------------------- /my/6class/id/read_write.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | //int g_val = 0; 9 | //int main() 10 | //{ 11 | // FILE* fp = fopen("./log","w+");//W+是可以读也可以写,如果当前路径下没有log文件,就创建它 12 | // if(fp == NULL){ 13 | // perror("open file error\n"); 14 | // return 1; 15 | // } 16 | // char str[] = "you are a good girl"; 17 | // int count = 0; 18 | // while(count < 20){ 19 | // fwrite(str,1,strlen(str),fp); 20 | // fputc('\n',fp); 21 | // count++; 22 | // } 23 | // return 0; 24 | //} 25 | 26 | //open,write,read,close是系统调用函数,可以通过man查看各函数,是用文件描述符,查看文件指针和文件描述符的区别 27 | int main() 28 | { 29 | int fd = open("./log",O_CREAT | O_RDWR,0644); 30 | printf("1、open fd is :%d\n",fd); 31 | if( fd < 0 ){ 32 | perror("open"); 33 | return 1; 34 | } 35 | char* msg = "hello world\n"; 36 | int count = 0; 37 | fd = open("./log",O_CREAT | O_RDWR,0644); 38 | printf("1、open fd is :%d\n",fd); 39 | char buf[1024]; 40 | memset(buf,'\0',sizeof(buf)); 41 | fd = open("./log",O_CREAT | O_RDWR,0644); 42 | printf("1、open fd is :%d\n",fd); 43 | while(count < 20){ 44 | //write(fd,msg,strlen(msg)); 45 | ssize_t size = read(fd,buf,sizeof(buf)-1); 46 | if( size > 0 ) 47 | { 48 | buf[size] = '\0'; 49 | printf("%s\n",buf); 50 | }else{ //end of file 51 | perror("read:"); 52 | break; 53 | } 54 | count++; 55 | } 56 | close(fd); 57 | return 0; 58 | } 59 | 60 | int main() 61 | { 62 | //close(0);//stdin,默认通过键盘输入,一切皆文件,dup,dup2(实现文件描述符的重定向) 63 | close(1);//stdout,默认输出终端,若此时1变成了文件,那么printf打印的信息默认打印到了该文件里面,实现了输出重定向,也可以设置输出到远程网络上,运用到套接字 64 | //close(2);//stderr,默认输出终端 65 | int fd = open("./log",O_CREAT | O_RDWR,0644);//此时fd为1,先把最小序号分配出去,从0开始,类似数组下标, 66 | printf("1、open fd is :%d\n",fd); 67 | if( fd < 0 ){//打开 68 | perror("open"); 69 | return 1; 70 | } 71 | 72 | printf("open fd is:%d\n",fd); 73 | } 74 | -------------------------------------------------------------------------------- /my/6class/id/read_write.out: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoxiao-su/_Linux-OS-Network_/a561603918e0bd1fc57a5fb1f0b980fe5227a2de/my/6class/id/read_write.out -------------------------------------------------------------------------------- /my/6class/makefile/Makefile: -------------------------------------------------------------------------------- 1 | #方法一:分步生成可执行文件 2 | #test:test.o 3 | # gcc -o test test.o 4 | #test.o:test.s 5 | # gcc -c test.s -o test.o 6 | #test.s:test.i 7 | # gcc -S test.i -o test.s 8 | #test.i:test.c 9 | # gcc -E test.c -o test.i 10 | #.PHONY:clean 11 | #clean: 12 | # rm -rf test.o test.s test.i 13 | # 14 | ##方法二:一步生成可执行文件 15 | #test:test.c 16 | # gcc -o test test.c 17 | #.PHONY:clean 18 | #clean: 19 | # rm -rf test 20 | 21 | #方法三:通过定义变量生成可执行文件 22 | SOU=test 23 | DST=test.c 24 | CC=gcc 25 | FLAGS=#-static #编写线程时候:FLAGS=-lpthread 26 | 27 | $(SOU):$(DST) 28 | gcc -o $@ $^ $(FLAGS) 29 | .PHONY:clean 30 | clean: 31 | rm -rf $(SOU) 32 | -------------------------------------------------------------------------------- /my/6class/makefile/test.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main() 3 | { 4 | printf("hello bit\n"); 5 | return 0; 6 | } 7 | -------------------------------------------------------------------------------- /my/6class/makefile1/make1/Makefile: -------------------------------------------------------------------------------- 1 | #test:test.c 2 | # gcc test.c -o test 3 | #.PHONY:clean 4 | #clean: 5 | # rm -rf test 6 | 7 | test:test.o 8 | gcc test.o -o test 9 | test.o:test.s 10 | gcc -c test.s -o test.o 11 | test.s:test.i 12 | gcc -S test.i -o test.s 13 | test.i:test.c 14 | gcc -E test.c -o test.i 15 | .PHONY:clean 16 | clean: 17 | rm -rf test.o test.s test.i 18 | -------------------------------------------------------------------------------- /my/6class/makefile1/make1/test.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main() 3 | { 4 | printf("Hello World\n"); 5 | return 0; 6 | } 7 | -------------------------------------------------------------------------------- /my/6class/makefile1/make2/main.c: -------------------------------------------------------------------------------- 1 | #include"proc.h" 2 | int main() 3 | { 4 | proc(); 5 | return 0; 6 | } 7 | -------------------------------------------------------------------------------- /my/6class/makefile1/make2/makefile: -------------------------------------------------------------------------------- 1 | proc:proc.c main.c 2 | gcc -o proc proc.c main.c 3 | .PHONY:clean 4 | clean: 5 | rm -rf proc 6 | -------------------------------------------------------------------------------- /my/6class/makefile1/make2/proc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include"proc.h" 3 | int proc() 4 | { 5 | printf("HelloWorld\n"); 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /my/6class/makefile1/make2/proc.h: -------------------------------------------------------------------------------- 1 | #ifndef _PROC_ 2 | 3 | int proc(); 4 | 5 | #endif 6 | -------------------------------------------------------------------------------- /my/6class/msg/Makefile: -------------------------------------------------------------------------------- 1 | SER=server 2 | CLI=client 3 | CC=gcc 4 | 5 | .PHONY:all 6 | all:$(CLI) $(SER) 7 | 8 | $(CLI):client.c msgqueue.c 9 | $(CC) -w -o $@ $^ 10 | $(SER):server.c msgqueue.c 11 | $(CC) -w -o $@ $^ 12 | 13 | .PHONY:clean 14 | clean: 15 | rm -rf $(CLI) $(SER) 16 | 17 | -------------------------------------------------------------------------------- /my/6class/msg/client: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoxiao-su/_Linux-OS-Network_/a561603918e0bd1fc57a5fb1f0b980fe5227a2de/my/6class/msg/client -------------------------------------------------------------------------------- /my/6class/msg/client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "msgqueue.h" 3 | 4 | int client() 5 | { 6 | int msgqueue_id = get_queue(); 7 | char buf[_SIZE_]; 8 | while(1) 9 | { 10 | printf("Please Enter : "); 11 | fflush(stdout); 12 | memset(buf,'\0',sizeof(buf));//buf保存消费掉的消息 13 | gets(buf);//client从标准输出上获取信息并且存放在buf里面 14 | send_msg(msgqueue_id,CLIENT_TYPE,buf);//经buf里面的消息发送给server 15 | if(strncasecmp(buf,"Quit",4) == 0){ 16 | printf("Quit\n"); 17 | return 0; 18 | } 19 | sleep(2); 20 | memset(buf,'\0',sizeof(buf));//buf保存消费掉的消息 21 | int ret = recv_msg(msgqueue_id,SERVER_TYPE,buf,sizeof(buf));//client删除从server发送来的消息 22 | if(ret == 0) 23 | { 24 | printf("server say : %s\n",buf); 25 | } 26 | } 27 | } 28 | int main() 29 | { 30 | client(); 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /my_socketpair.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() 7 | { 8 | int fd[2] = {0,0}; 9 | int ret = socketpair(AF_UNIX,SOCK_STREAM,0,fd);//创建双向通信的管道,使用unix域间套接字和面向字节流服务 10 | if( ret < 0 ){ 11 | perror("socketpair"); 12 | return 1; 13 | } 14 | #ifdef _DEBUG_ 15 | printf("fd0 : %d\n",fd[0]); 16 | printf("fd1 : %d\n",fd[1]); 17 | #endif 18 | pid_t id = fork(); 19 | if( id < 0 ){ 20 | perror("fork"); 21 | return 2; 22 | }else if( id == 0 ){//child 23 | close(fd[1]);//use fd[0] for read and write 24 | char *msg_c = "i know"; 25 | char buf[256]; 26 | while(1){ 27 | //1.write 28 | write(fd[0],msg_c,strlen(msg_c)); 29 | //2.read 30 | ssize_t sz = read(fd[0],buf, sizeof(buf)-1); 31 | buf[sz] = '\0'; 32 | //3.printf 33 | printf("child : %d , %s\n",getpid(),buf); 34 | sleep(1); 35 | } 36 | }else{//father 37 | close(fd[0]);//use fd[1] for read and write 38 | char buf[256]; 39 | char *msg_f = "i am your father"; 40 | while(1){ 41 | //1.read 42 | ssize_t sz = read(fd[1], buf, sizeof(buf)-1); 43 | buf[sz] = '\0'; 44 | //2.printf 45 | printf("father : %d , %s\n",getpid(),buf); 46 | //3.write 47 | write(fd[1], msg_f, strlen(msg_f)); 48 | sleep(1); 49 | } 50 | } 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /pipe.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | int main() 5 | { 6 | int fd[2] = {0,0};//进行初始化,0号下标表示读端(像嘴),1号下标是写端(像笔) 7 | 8 | int ret = pipe(fd);//创建了一个管道文件 9 | if(ret == -1){ 10 | perror("error"); 11 | return 1; 12 | } 13 | #ifndef _DEBUG_ 14 | #define _DEBUG_ 15 | printf("fd[0]-> %d,fd[1]-> %d\n",fd[0],fd[1]); 16 | #endif 17 | pid_t id = fork(); 18 | if(id < 0){ 19 | perror("error"); 20 | return 2; 21 | }else if(id == 0){//子进程往管道里面写数据 22 | close(fd[0]); 23 | char* str = "haha,I am child"; 24 | char* str1 = "my count id > 5 now..."; 25 | int count = 10; 26 | while(count > 0){ 27 | if(count < 5){ 28 | sleep(1); 29 | write(fd[1],str,strlen(str)); 30 | }else{ 31 | sleep(1); 32 | write(fd[1],str1,strlen(str1)); 33 | } 34 | count--; 35 | } 36 | sleep(4); 37 | write(fd[1],"quit",4); 38 | }else{//父进程往管道里面读数据 39 | close(fd[1]); 40 | char* buf[1024]; 41 | while(1){ 42 | memset(buf,'\0',sizeof(buf)); 43 | size_t len = read(fd[0],buf,sizeof(buf)-1);//读成功返回值是读的字节数,否则返回0 44 | if( len > 0 ){ 45 | buf[len] = '\0'; 46 | if(strcmp("quit",buf) == 0){ 47 | printf("child proc Quit\n"); 48 | return; 49 | } 50 | printf("child msg is :%s\n",buf); 51 | } 52 | } 53 | wait(NULL); 54 | } 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /pthread/Condition Variable(条件变量)/Makefile: -------------------------------------------------------------------------------- 1 | BIN=cond_mutex 2 | SRC=cond_mutex.c 3 | CC=gcc 4 | FLAGS=-lpthread 5 | 6 | $(BIN):$(SRC) 7 | $(CC) -o $@ $^ $(FLAGS) 8 | .PHONY:clean 9 | clean: 10 | rm -rf $(BIN) 11 | -------------------------------------------------------------------------------- /pthread/Condition Variable(条件变量)/cond_mutex.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | pthread_mutex_t lock;//互斥锁 7 | pthread_cond_t cond; //条件变量 8 | 9 | //链表 10 | typedef int data_t; 11 | typedef struct _node{ //节点结构 12 | data_t data; 13 | struct _node *next; 14 | }node_t,*node_p,**node_pp,*list_head; 15 | 16 | list_head head = NULL; 17 | 18 | static node_p buy_node(data_t _data) //创建节点 19 | { 20 | node_p new_node = (node_p)malloc(sizeof(node_t)); 21 | if( NULL == new_node ){ 22 | perror("malloc"); 23 | exit(1); 24 | } 25 | new_node->data = _data; 26 | new_node->next = NULL; 27 | return new_node; 28 | } 29 | 30 | static void delete_node(node_p _node)//删除节点 31 | { 32 | if(_node){ 33 | free(_node); 34 | _node = NULL; 35 | } 36 | } 37 | 38 | int is_empty(list_head _head) //判断链表是否为空 39 | { 40 | if( _head && NULL == _head->next){ 41 | return 1;//yes 42 | } 43 | return 0;//no 44 | } 45 | 46 | void list_init(node_pp _head) //初始化链表 47 | { 48 | *_head = buy_node(-1); 49 | } 50 | 51 | void push_head(list_head _head,data_t _data)//头插节点 52 | { 53 | if(_head){ 54 | node_p tmp = buy_node(_data); 55 | //push 56 | tmp->next = _head->next; 57 | _head->next = tmp; 58 | } 59 | } 60 | 61 | int pop_head(list_head _head, data_t* _data)//头删节点 62 | { 63 | if(is_empty(_head)){ 64 | return 0;//fail 65 | } 66 | node_p tmp = head->next; 67 | head->next = head->next->next; 68 | *_data = tmp->data; 69 | delete_node(tmp); 70 | return 1; 71 | } 72 | 73 | void clear(list_head _head) //摧毁链表 74 | { 75 | data_t tmp = 0; 76 | while(!is_empty(_head)){ 77 | pop_head(_head,&tmp); 78 | } 79 | delete_node(_head); 80 | } 81 | 82 | void show_list(list_head _head) //打印链表 83 | { 84 | node_p ptr = _head->next; 85 | while(ptr){ 86 | printf("%d ",ptr->data); 87 | ptr = ptr->next; 88 | } 89 | } 90 | 91 | void* comsumer_data(void* arg) //消费者 92 | { 93 | int count = 50; 94 | data_t _data = -1; 95 | while(count){ 96 | pthread_mutex_lock(&lock); 97 | while(is_empty(head)){ //当没有数据的时候,阻塞等待,直到被唤醒 98 | pthread_cond_wait(&cond,&lock); 99 | } 100 | int ret = pop_head(head,&_data); 101 | pthread_mutex_unlock(&lock); 102 | if(ret == 0){ 103 | printf("consumer data failed\n"); 104 | }else{ 105 | printf("consumer data done : %d\n",_data); 106 | } 107 | sleep(1); 108 | count--; 109 | _data = -1; 110 | } 111 | } 112 | void* producter_data(void* arg) //生产者 113 | { 114 | int count = 50; 115 | while(count){ 116 | pthread_mutex_lock(&lock); 117 | push_head(head,count); 118 | pthread_mutex_unlock(&lock); 119 | pthread_cond_signal(&cond);//通知在cond条件变量下等待的消费者有数据可以消费 120 | printf("data is ready,signal consumer!\n"); 121 | printf("producter data done : %d\n",count); 122 | sleep(5); 123 | count--; 124 | } 125 | } 126 | 127 | int main() 128 | { 129 | pthread_mutex_init(&lock,NULL);//初始化互斥锁 130 | pthread_cond_init(&cond,NULL); //初始化条件变量 131 | 132 | list_init(&head); 133 | pthread_t consumer,producter; 134 | pthread_create(&consumer,NULL,comsumer_data,NULL); 135 | pthread_create(&producter,NULL,producter_data,NULL); 136 | 137 | pthread_join(consumer,NULL); 138 | pthread_join(producter,NULL); 139 | clear(head); 140 | 141 | pthread_mutex_destroy(&lock); 142 | pthread_cond_destroy(&cond); 143 | return 0; 144 | } 145 | 146 | 147 | //线程创建、终止、等待、同步、分离具体分析见:http://blog.csdn.net/SuLiJuan66/article/details/50615208 148 | 149 | 150 | 151 | 152 | 153 | -------------------------------------------------------------------------------- /pthread/线程终止/Makefile: -------------------------------------------------------------------------------- 1 | pthread:pthread.c 2 | gcc -o $@ $^ -lpthread 3 | .PHONY:clean 4 | clean: 5 | rm -rf pthread 6 | -------------------------------------------------------------------------------- /pthread/线程终止/pthread.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | void* thread_run(void* arg) 5 | { 6 | int ret = pthread_detach(pthread_self()); 7 | printf("%d,%s\n",ret,strerror(ret)); 8 | int value = (int)arg; 9 | printf("this is another thread,arg:%d,self:%lu\n",arg,pthread_self());; 10 | //return (void*)1;//方法一,从函数return返回 11 | 12 | int count = 0 13 | while(1){ 14 | printf("this is another thread,arg:%d,self:%lu\n",arg,pthread_self()); 15 | sleep(1); 16 | count++; 17 | if(count > 5){ 18 | printf("other thread done\n"); 19 | pthread_exit((void*)34);//方法二:自己终止自己 20 | } 21 | } 22 | //exit(0);//方法三:从函数exit退出 23 | } 24 | 25 | int main() 26 | { 27 | pthread_t tid; 28 | int code = pthread_create(&tid,NULL,thread_run,(void*)1); 29 | if(code != 0){ 30 | printf("%d : %s\n",code,strerror(code)); 31 | return 1; 32 | } 33 | int count = 0; 34 | int flag = 0; 35 | while(1){ 36 | printf("this is main thread,self:%lu\n",pthread_self());//返回自己的线程ID 37 | sleep(1); 38 | count++; 39 | if(count > 10){ 40 | break; 41 | }else if(count > 5 && flag == 0){ 42 | flag = 1; 43 | // pthread_cancel(tid);//终止方法四:主线程(或者任一个线程)终止其它线程,PTHREAD_CANCELED 一个宏,值为-1 44 | } 45 | } 46 | int ret = pthread_detach(tid); 47 | printf("%s",strerror(ret)); 48 | void* status = NULL; 49 | code = pthread_join(tid,&status);//status保存返回的错误码,code获取终止线程的错误码 50 | if(code == 0){ 51 | printf("pthread_join success,code:%d,%s\n",(int)status,strerror(ret)); 52 | }else{ 53 | printf("%d : %s\n",code,strerror(code)); 54 | } 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /schedul_Shell.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #shell脚本编写 3 | 4 | bar='' #定义变量不需要类型,不用分号 5 | index=0 6 | 7 | flag=("|" "/" "-" "\\") #定义数组,\ 和下面的 % 都属于特殊字符,所以需要转义 8 | 9 | while [ $index -le 100 ] #while语句进行条件判断 10 | do 11 | pos=index%4 #或者 let pos=index%4 12 | bar=${bar}# # ${bar}是取bar的值 13 | sleep 0.1 14 | printf "[%-100s][%d%%][%c]\r" "${bar}" "${index}" "${flag[pos]}"; 15 | (( index++ )) #或者用let index++ 16 | done 17 | -------------------------------------------------------------------------------- /sem/Makefile: -------------------------------------------------------------------------------- 1 | #my_sem:my_sem.h my_sem.c 2 | # gcc -o my_sem my_sem.h my_sem.c 3 | #.PHONY:clean 4 | #clean: 5 | # rm -rf my_sem 6 | 7 | #链接静态库 8 | 9 | libmy_sem.a:my_sem.o 10 | ar rcv libmy_sem.a my_sem.o 11 | my_sem.o:my_sem.c 12 | gcc -c my_sem.c -o my_sem.o 13 | .PHONY:clean 14 | clean: 15 | rm -rf libmy_sem.a lib my_sem.o 16 | .PHONY:lib 17 | lib: 18 | mkdir lib 19 | cp my_sem.h lib 20 | cp libmy_sem.a lib 21 | -------------------------------------------------------------------------------- /sem/my_sem.c: -------------------------------------------------------------------------------- 1 | #include "my_sem.h" 2 | 3 | static int com_sem(int nsems,int flag) 4 | { 5 | key_t key = ftok(_PATH_,_PROJ_ID_); 6 | if( key < 0 ){ 7 | perror("ftok"); 8 | return -1; 9 | } 10 | int sem_id = semget(key,nsems,flag);//创建信号量 11 | if(sem_id < 0){ 12 | perror("semget"); 13 | return -2; 14 | } 15 | return sem_id; 16 | } 17 | int creat_sem(int nsems) 18 | { 19 | int flag = IPC_CREAT | IPC_EXCL | 0666; 20 | return com_sem(nsems,flag); 21 | } 22 | int get_sem(int nsems) 23 | { 24 | int flag = IPC_CREAT; 25 | return com_sem(nsems,flag); 26 | } 27 | static int com_semop(int sem_id,unsigned short which,short op) 28 | {//对哪个信号量集中的哪一个信号进行op指定的操作 29 | struct sembuf semb[1];//只考虑二元信号量,所以只有一个元素 30 | semb[0].sem_num = which; 31 | semb[0].sem_op = op;//进行什么操作是由op说了算 32 | semb[0].sem_flg = 0;//UNDO,若一个进程在临界区崩溃了,那么flag就维护信号量,把信号量恢复 33 | if(semop(sem_id,semb,1) < 0) 34 | { 35 | perror("semop"); 36 | return -1; 37 | } 38 | return 0; 39 | } 40 | int p_sem(int sem_id,unsigned short which) 41 | {//进行p操作 42 | int op = -1; 43 | return com_semop(sem_id,which,op); 44 | } 45 | int v_sem(int sem_id,unsigned short which) 46 | {//进行v操作 47 | int op = 1; 48 | return com_semop(sem_id,which,op); 49 | } 50 | int init_sem(int sem_id,int which,int init_val) 51 | { 52 | semun_t sem_val; 53 | sem_val.val = init_val; 54 | int ret = semctl(sem_id,which,SETVAL,sem_val);//初始化信号量 55 | if(ret < 0) 56 | { 57 | perror("semct"); 58 | return -1; 59 | } 60 | return 0; 61 | } 62 | int destory_sem(int sem_id) 63 | { 64 | int ret = semctl(sem_id,0,IPC_RMID);//0是指定的信号量,此处讨论的是二元信号量 65 | if(ret < 0){ 66 | perror("semctl"); 67 | return -1; 68 | } 69 | printf("\ndestroy success\n"); 70 | return 0; 71 | } 72 | //链接静态库的时候,不能有main函数,因为用户会自己写一个main函数 73 | //int main() 74 | //{ 75 | // int nsems = 8; 76 | // int sem_id = creat_sem(nsems); 77 | // printf("sem_id = %d\n",sem_id); 78 | // sleep(3); 79 | // destory_sem(sem_id); 80 | // return 0; 81 | //} 82 | -------------------------------------------------------------------------------- /sem/my_sem.h: -------------------------------------------------------------------------------- 1 | #ifndef _MYSEM_ 2 | #define _MYSEM_ 3 | #include 4 | #include 5 | #include 6 | #include 7 | #define _PATH_ "." 8 | #define _PROJ_ID_ 0x0603 9 | 10 | typedef union semun { 11 | int val; /* Value for SETVAL */ 12 | struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */ 13 | unsigned short *array; /* Array for GETALL, SETALL */ 14 | struct seminfo *__buf; /* Buffer for IPC_INFO (Linux-specific) */ 15 | }semun_t; 16 | 17 | int create_sem(int nsems); 18 | int get_sem(int nsems); 19 | int init_sem(int sem_id,int which,int init_val); 20 | int p_sem(int sem_id,unsigned short which);//-1 21 | int v_sem(int sem_id,unsigned short which);//+1 22 | int destroy_sem(int sem_id); 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /sem/父子进程互斥访问stdout/Makefile: -------------------------------------------------------------------------------- 1 | sem_stdout:sem_stdout.c 2 | gcc -o sem_stdout sem_stdout.c ./lib/libmy_sem.a -I ./lib -L ./lib -lmy_sem -g 3 | .PHONY:clean 4 | clean: 5 | rm -rf sem_stdout 6 | -------------------------------------------------------------------------------- /sem/父子进程互斥访问stdout/lib/libmy_sem.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoxiao-su/_Linux-OS-Network_/a561603918e0bd1fc57a5fb1f0b980fe5227a2de/sem/父子进程互斥访问stdout/lib/libmy_sem.a -------------------------------------------------------------------------------- /sem/父子进程互斥访问stdout/lib/my_sem.h: -------------------------------------------------------------------------------- 1 | #ifndef _MYSEM_ 2 | #define _MYSEM_ 3 | #include 4 | #include 5 | #include 6 | #include 7 | #define _PATH_ "." 8 | #define _PROJ_ID_ 0x0603 9 | 10 | typedef union semun { 11 | int val; /* Value for SETVAL */ 12 | struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */ 13 | unsigned short *array; /* Array for GETALL, SETALL */ 14 | struct seminfo *__buf; /* Buffer for IPC_INFO (Linux-specific) */ 15 | }semun_t; 16 | 17 | int create_sem(int nsems); 18 | int get_sem(int nsems); 19 | int init_sem(int sem_id,int which,int init_val); 20 | int p_sem(int sem_id,unsigned short which);//-1 21 | int v_sem(int sem_id,unsigned short which);//+1 22 | int destroy_sem(int sem_id); 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /sem/父子进程互斥访问stdout/sem_stdout.c: -------------------------------------------------------------------------------- 1 | //多进程间向终端打印消息,并没有遵守互斥原则,此实现各进程对终端访问的互斥,同时引用静态库 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "my_sem.h"//链接静态库 8 | 9 | int main() 10 | { 11 | int f_sem_id = creat_sem(1);//使用互斥信号量(二元信号量)父进程先获取信号量 12 | init_sem(f_sem_id,0,1);//信号量从下标0开始,被初始化为1 13 | pid_t id = fork(); 14 | if( id == 0) 15 | {//child 16 | int c_sem_id = get_sem(1); 17 | int count = 3; 18 | while(1) 19 | { 20 | p_sem(c_sem_id,0);//对第一个信号量进行P操作 21 | printf("A"); 22 | fflush(stdout); 23 | sleep(rand()%3); 24 | printf("A"); 25 | fflush(stdout); 26 | sleep(rand()%3); 27 | v_sem(c_sem_id,0);//对第一个信号量进行V操作 28 | count--; 29 | if(count == 0){ 30 | break; 31 | } 32 | } 33 | } 34 | else 35 | {//father 36 | int count = 3; 37 | while(1) 38 | { 39 | p_sem(f_sem_id,0); 40 | printf("B"); 41 | fflush(stdout); 42 | sleep(rand()%3); 43 | printf("B"); 44 | fflush(stdout); 45 | sleep(rand()%3); 46 | v_sem(f_sem_id,0); 47 | count--; 48 | if(count == 0){ 49 | break; 50 | } 51 | } 52 | } 53 | //sleep(3); 54 | wait(NULL); 55 | destory_sem(f_sem_id); 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /sem/生成的静态库lib/libmy_sem.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoxiao-su/_Linux-OS-Network_/a561603918e0bd1fc57a5fb1f0b980fe5227a2de/sem/生成的静态库lib/libmy_sem.a -------------------------------------------------------------------------------- /sem/生成的静态库lib/my_sem.h: -------------------------------------------------------------------------------- 1 | #ifndef _MYSEM_ 2 | #define _MYSEM_ 3 | #include 4 | #include 5 | #include 6 | #include 7 | #define _PATH_ "." 8 | #define _PROJ_ID_ 0x0603 9 | 10 | typedef union semun { 11 | int val; /* Value for SETVAL */ 12 | struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */ 13 | unsigned short *array; /* Array for GETALL, SETALL */ 14 | struct seminfo *__buf; /* Buffer for IPC_INFO (Linux-specific) */ 15 | }semun_t; 16 | 17 | int create_sem(int nsems); 18 | int get_sem(int nsems); 19 | int init_sem(int sem_id,int which,int init_val); 20 | int p_sem(int sem_id,unsigned short which);//-1 21 | int v_sem(int sem_id,unsigned short which);//+1 22 | int destroy_sem(int sem_id); 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /shm/Makefile: -------------------------------------------------------------------------------- 1 | server=shm_server #shell脚本中定义变量 2 | client=shm_client 3 | CC=gcc 4 | FLAGS=#-static 5 | .PHONY:all 6 | all:$(server) $(client) 7 | 8 | #方法一: 9 | $(server):shm_server.c shm_comm.c 10 | gcc -o $@ $^ 11 | $(client):shm_client.c shm_comm.c 12 | gcc -o $@ $^ 13 | .PHONY:clean 14 | clean: 15 | rm -rf $(server) $(client) 16 | 17 | 18 | #方法二 19 | 20 | #$(server):shm_server.o shm_comm.o 21 | # $(CC) -o $@ $^ $(FLAGS) -g 22 | #$(client):shm_client.o shm_comm.o 23 | # $(CC) -o $@ $^ $(FLAGS) -g #定义为静态链接 24 | #%.o:%.c 25 | # $(CC) -c $< #从冒号后面的列表中一个一个取参数 26 | # 27 | #.PHONY:clean 28 | #clean: 29 | # rm -rf $(server) $(client) *.o 30 | 31 | #方法三:静态库的创建 32 | 33 | #libmy_shm.a:shm_comm.o 34 | # ar rcv libmy_shm.a shm_comm.o 35 | #shm_comm.o:shm_comm.c 36 | # gcc -c shm_comm.c -o shm_comm.o 37 | #.PHONY:clean 38 | #clean: 39 | # rm -rf libmy_shm.a output shm_comm.o 40 | #.PHONY:output 41 | #output: 42 | # mkdir output 43 | # cp shm_comm.h output 44 | # cp libmy_shm.a output 45 | -------------------------------------------------------------------------------- /shm/shm_client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "shm_comm.h" 3 | int main() 4 | { 5 | int _size = 1000; 6 | int shm_id = get_shm(_size); 7 | printf("sleep(5)\n"); 8 | sleep(5); 9 | char* mem = (char*)attach(shm_id); 10 | memset(mem,'\0',_size); 11 | int index = 0; 12 | //多进程往共享内存里面写数据,没有互斥访问共享内存,可以结合信号量机制互斥访问 13 | int count = 60; 14 | while(count--) 15 | {//可以再起一个client进行写,增加挂接共享内存的数目,命令:ipcs -m查看挂接数目 16 | mem[index] = 'X'; 17 | mem[index+1] = '\0'; 18 | index++; 19 | sleep(1); 20 | } 21 | detach(mem); 22 | printf("detach\n"); 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /shm/shm_comm.c: -------------------------------------------------------------------------------- 1 | #include "shm_comm.h" 2 | 3 | static int comm_shm(int _size,int flag) 4 | { 5 | key_t _key = ftok(_PATH_,_PROJ_ID_); 6 | if(_key == -1){ 7 | perror("ftok"); 8 | return -1; 9 | } 10 | int shm_id = shmget(_key,_size,flag); 11 | if(shm_id == -1) 12 | { 13 | perror("shmget"); 14 | return -2; 15 | } 16 | return shm_id; 17 | } 18 | int create_shm(int _size) //创建共享内存 19 | { 20 | int flag = IPC_CREAT|IPC_EXCL|0666; 21 | return comm_shm(_size,flag); 22 | } 23 | int get_shm(int _size) //获取共享内存 24 | { 25 | int flag = IPC_CREAT; 26 | return comm_shm(_size,flag); 27 | } 28 | int destory_shm(int shm_id)//释放共享内存 29 | { 30 | if(shmctl(shm_id,IPC_RMID,0) == -1) 31 | { 32 | perror("shmctl"); 33 | return -1; 34 | } 35 | return 0; 36 | } 37 | void* attach(int shm_id) 38 | {//挂接,当server创建出共享内存,必须挂接上共享内存后才能访问共享内存,client也是 39 | void* mem = NULL; 40 | if(mem = shmat(shm_id,NULL,0)){ 41 | return mem; 42 | } 43 | return NULL; 44 | } 45 | int detach(void* addr) 46 | {//分离,断开挂接 47 | return shmdt(addr); 48 | } 49 | -------------------------------------------------------------------------------- /shm/shm_comm.h: -------------------------------------------------------------------------------- 1 | #ifndef _COMM_ 2 | #define _COMM_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #define _PATH_ "." 10 | #define _PROJ_ID_ 0x6602 11 | 12 | int create_shm(int _size); 13 | int get_shm(int _size); 14 | int destory_shm(int shm_id); 15 | void* attach(int shm_id); 16 | int detach(void*); 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /shm/shm_server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "shm_comm.h" 3 | int main() 4 | { 5 | int _size = 4096; 6 | int shm_id = create_shm(_size); 7 | sleep(10); 8 | char* mem = (char*)attach(shm_id); 9 | memset(mem,'\0',_size); 10 | //读取共享内存数据 11 | int count = 60; 12 | while(count--){ 13 | printf("%s\n",mem); 14 | sleep(1); 15 | } 16 | 17 | detach(mem); 18 | destory_shm(shm_id); 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /wait and waitpid/different of wait and waitpid.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoxiao-su/_Linux-OS-Network_/a561603918e0bd1fc57a5fb1f0b980fe5227a2de/wait and waitpid/different of wait and waitpid.txt -------------------------------------------------------------------------------- /wait and waitpid/mywait.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | //创建多个进程,并且waitpid多个进程 6 | #define _NUM_ 10 7 | #define _INIT_VAL_ -1 8 | pid_t id_num[_NUM_]; 9 | int m = 0; 10 | static void run_proc() 11 | { 12 | int timeCount = rand()%10; 13 | //sleep(timeCount); 14 | sleep(1); 15 | printf("child wait success\n"); 16 | printf("child:pid:%d,timeCount:%d\n",getpid(),timeCount); 17 | } 18 | void init_num_proc()//初始化进程 19 | { 20 | int i = 0; 21 | int num = sizeof(id_num)/sizeof(id_num[0]); 22 | for(;i 2 | #include 3 | #include 4 | #include 5 | int main() 6 | { 7 | pid_t id = fork(); 8 | if(id == 0){ 9 | printf("child:pid:%d,ppid:%d\n",getpid(),getppid()); 10 | sleep(10); 11 | exit(3); 12 | }else{ 13 | printf("This is a father\n"); 14 | int status = 0; 15 | pid_t dead_id = wait(&status);//父进程等待子进程退出,即使父进程先运 行完,也会等待子进程运行完 16 | if(dead_id == -1){ 17 | perror("error"); 18 | }else{ 19 | printf("dead_id:%d\n",dead_id); 20 | printf("child exit code:%d\n",(status>>8)&0xff); 21 | //printf("child exit code:%d\n",WEXITSTATUS(status)); 22 | printf("child get signal:%d\n",status&0xff); 23 | //printf("child get signal:%d\n",WIFEXITED(status)); 24 | } 25 | } 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /wait and waitpid/waitpid.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | //创建多个进程,并且waitpid多个进程 6 | #define _NUM_ 10 7 | #define _INIT_VAL_ -1 8 | pid_t id_num[_NUM_]; 9 | int m = 0; 10 | static void run_proc() 11 | { 12 | int timeCount = rand()%10; 13 | //sleep(timeCount); 14 | sleep(1); 15 | printf("child wait success\n"); 16 | printf("child:pid:%d,timeCount:%d\n",getpid(),timeCount); 17 | } 18 | void init_num_proc()//初始化进程 19 | { 20 | int i = 0; 21 | int num = sizeof(id_num)/sizeof(id_num[0]); 22 | for(;i 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | static void usage(const char *proc) 10 | { 11 | printf("%s [ip] [port]",proc); 12 | } 13 | 14 | int main(int argc,char* argv[]) 15 | { 16 | if( argc != 3){ 17 | usage(argv[0]); 18 | return 1; 19 | } 20 | int sock = socket(AF_INET,SOCK_STREAM,0); 21 | if( sock < 0){ 22 | perror("socket"); 23 | return 1; 24 | } 25 | int port = atoi(argv[2]); 26 | const char *ip = argv[1]; 27 | struct sockaddr_in remote; 28 | remote.sin_family = AF_INET; 29 | remote.sin_port = htons(port); 30 | remote.sin_addr.s_addr = inet_addr(ip); 31 | 32 | //客户端不需要绑定,需要链接 33 | if(connect(sock, (struct sockaddr*)&remote, sizeof(remote)) < 0){ 34 | perror("connect"); 35 | return 0; 36 | } 37 | char buf[1024]; 38 | //while(1){ 39 | memset(buf, '\0', sizeof(buf)); 40 | printf("Please Enter : "); 41 | fflush(stdout); 42 | gets(buf); 43 | write(sock, buf, strlen(buf)); 44 | close(sock); 45 | //} 46 | 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /多路复用之select、poll、epoll/my_epoll/epoll_server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #define EVENT_SIZE 64 11 | 12 | //基于TCP协议 13 | static void usage(const char *const proc) 14 | { 15 | printf("%s [ip] [port]\n",proc); 16 | } 17 | //设置文件描述符非阻塞,保证对端没有关闭写端时,read函数不会一直阻塞 18 | static void set_nonblock(int new_sock) 19 | { 20 | int fl = fcntl(new_sock, F_GETFL); 21 | if( fl < 0 ){ 22 | perror("fcntl"); 23 | exit(1); 24 | } 25 | fcntl(new_sock, F_SETFL, fl | O_NONBLOCK); 26 | } 27 | 28 | //if 0-> read success, and write success, and remote close 29 | static int read_write_data(int fd) 30 | { 31 | char buf[10240]; 32 | int len = sizeof(buf)-1; 33 | ssize_t sz = 0; 34 | int total = 0; 35 | memset(buf, '\0', sizeof(buf)); 36 | while( (sz = recv(fd, buf+total, len, 0)) > 0 ){ 37 | total += sz; 38 | if( sz < len ){ 39 | break; 40 | } 41 | } 42 | if( total > 0 ){ 43 | buf[total] = '\0'; 44 | printf("buf : %s\n",buf); 45 | memset(buf, '\0', sizeof(buf)); 46 | sprintf(buf, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\n\r\nhello world:)",13);//回显消息 47 | send(fd, buf, sizeof(buf), 0); 48 | } 49 | return 0; 50 | } 51 | 52 | int start(const char* ip,short port) 53 | { 54 | int sock = socket(AF_INET,SOCK_STREAM,0); 55 | if(sock < 0){ 56 | perror("socket"); 57 | return -1; 58 | } 59 | //防止因为timewait情况而使得某个端口无法绑定的情况 60 | int flag = 1; 61 | setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)); 62 | //绑定前进行本地信息的填充 63 | struct sockaddr_in local; 64 | local.sin_family = AF_INET; 65 | local.sin_port = htons(port); 66 | local.sin_addr.s_addr = inet_addr(ip); 67 | //进行绑定 68 | if( bind(sock, (struct sockaddr*)&local, sizeof(local)) < 0){ 69 | perror("bind"); 70 | exit(1); 71 | } 72 | //监听链接,一次最多可以监听5个链接 73 | if( listen(sock, 5) < 0){ 74 | perror("listen"); 75 | exit(1); 76 | } 77 | return sock; 78 | } 79 | 80 | int main(int argc,char* argv[]) 81 | { 82 | if(argc != 3){ 83 | usage(argv[1]); 84 | return 0; 85 | } 86 | const char* ip = argv[1]; 87 | short port = atoi(argv[2]); 88 | int listen_sock = start(ip,port); 89 | //创建一个epoll句柄,占用一个文件描述符 90 | int epfd = epoll_create(256); 91 | if(epfd < 0){ 92 | perror("epoll_create"); 93 | exit(1); 94 | } 95 | 96 | struct epoll_event _event; 97 | _event.events = EPOLLIN;//对读事件感兴趣 98 | if(epoll_ctl(epfd,EPOLL_CTL_ADD,listen_sock,&_event) < 0)//将listen_sock添加进epfd中 99 | { 100 | perror("epoll_ctl"); 101 | exit(1); 102 | } 103 | //out -> ready fd & event 104 | struct epoll_event ready_event[EVENT_SIZE];//存放 105 | int ready_event_size = EVENT_SIZE; 106 | int timeout = 3000; 107 | 108 | int ready_num = 0; 109 | while(1){//accept 110 | switch(ready_num = epoll_wait(epfd, ready_event, ready_event_size, timeout)) 111 | { 112 | case 0://timeout 113 | perror("timeout"); 114 | break; 115 | case -1://error 116 | perror("epoll_wait"); 117 | break; 118 | default://success -> we have fd & events ready at least 1 119 | { 120 | int i = 0; 121 | for(; i < ready_num; i++){ 122 | int fd = ready_event[i].data.fd; 123 | if( fd == listen_sock && (ready_event[i].events & EPOLLIN) ){//listen socket 124 | struct sockaddr_in client; 125 | socklen_t len = sizeof(client); 126 | int new_sock = accept(fd, (struct sockaddr*)&client, &len); 127 | if( new_sock < 0 ){ 128 | perror("accept"); 129 | continue; 130 | } 131 | //accpt success 132 | set_nonblock(new_sock); 133 | _event.events = EPOLLIN | EPOLLOUT | EPOLLET; 134 | if(epoll_ctl(epfd, EPOLL_CTL_ADD, new_sock, &_event) < 0){ 135 | perror("epoll_wait"); 136 | close(new_sock); 137 | continue; 138 | } 139 | }else if( (ready_event[i].events & EPOLLIN) && (ready_event[i].events & EPOLLOUT) ){//other socket 140 | if( read_write_data(fd) == 0 ){ 141 | close(fd); 142 | epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL); 143 | } 144 | } 145 | } 146 | } 147 | break; 148 | } 149 | } 150 | return 0; 151 | } 152 | 153 | 154 | select、poll、epoll详解见:http://blog.csdn.net/SuLiJuan66/article/details/50658589 155 | 156 | -------------------------------------------------------------------------------- /多路复用之select、poll、epoll/my_epoll/server.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ./epoll_server 192.168.18.129 8080 4 | -------------------------------------------------------------------------------- /多路复用之select、poll、epoll/my_poll.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() 6 | { 7 | int timeout = 3000; //大概三秒钟 8 | char buf[1024]; 9 | struct pollfd fd_poll[1]; //设置只有一个事件 10 | while(1){ 11 | fd_poll[0].fd = 0; //关心的是读事件 12 | fd_poll[0].events = POLLIN;//保存用户感兴趣的事件 13 | fd_poll[0].revents = 0; //保存内核返回的就绪事件 14 | memset(buf, '\0', sizeof(buf)); 15 | switch( poll(fd_poll, 1, timeout) ){ 16 | case 0: 17 | perror("timeout!"); 18 | break; 19 | case -1: 20 | perror("poll"); 21 | break; 22 | default: 23 | { 24 | if( fd_poll[0].revents & POLLIN ){//read event ready,检查相同位 25 | gets(buf); 26 | printf("buf : %s\n",buf); 27 | } 28 | } 29 | break; 30 | } 31 | } 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /多路复用之select、poll、epoll/my_select/Makefile: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | .PHONY:all 5 | all:select_server select_client 6 | 7 | select_server:select_server.c 8 | gcc -o $@ $^ 9 | select_client:select_client.c 10 | gcc -o $@ $^ 11 | 12 | .PHONY:clean 13 | clean: 14 | rm -rf select_server select_client 15 | 16 | -------------------------------------------------------------------------------- /多路复用之select、poll、epoll/my_select/select_client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | static void usage(const char *proc) 10 | { 11 | printf("%s [ip] [port]",proc); 12 | } 13 | 14 | int main(int argc,char* argv[]) 15 | { 16 | if( argc != 3){ 17 | usage(argv[0]); 18 | return 1; 19 | } 20 | 21 | int sock = socket(AF_INET,SOCK_STREAM,0); 22 | if( sock < 0){ 23 | perror("socket"); 24 | return 1; 25 | } 26 | 27 | int port = atoi(argv[2]); 28 | const char *ip = argv[1]; 29 | struct sockaddr_in remote; 30 | remote.sin_family = AF_INET; 31 | remote.sin_port = htons(port); 32 | remote.sin_addr.s_addr = inet_addr(ip); 33 | 34 | //客户端进行链接,不需要绑定 35 | if(connect(sock, (struct sockaddr*)&remote, sizeof(remote)) < 0){ 36 | perror("connect"); 37 | return 0; 38 | } 39 | 40 | //模拟一次传输信息过程 41 | char buf[1024]; 42 | //while(1){ 43 | memset(buf, '\0', sizeof(buf)); 44 | printf("Please Enter : "); 45 | fflush(stdout); 46 | gets(buf); 47 | write(sock, buf, strlen(buf)); 48 | close(sock); 49 | //} 50 | 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /多路复用之select、poll、epoll/my_select/select_server.c: -------------------------------------------------------------------------------- 1 | //基于TCP协议的select 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | #define _FD_NUM_ 512 13 | #define _FD_DEFAULT_VAL_ -1 14 | 15 | typedef struct _select_fd{ 16 | int max_fd; //记录最大文件描述符 17 | int fd_arr[_FD_NUM_]; //保存放到select监控集中的fd 18 | }select_fd_t; 19 | 20 | //说明正确运行方式 21 | static void usage(const char *proc) 22 | { 23 | printf("%s [ip] [port]\n",proc); 24 | } 25 | 26 | //把fd添加进数组里面,同时更新最大文件描述符 27 | static void add_read_fd(fd_set *set, select_fd_t *select_fd) 28 | { 29 | int i = 0; 30 | for( ;i<_FD_NUM_; i++){ 31 | if( select_fd->fd_arr[i] != _FD_DEFAULT_VAL_ ){ 32 | FD_SET( select_fd->fd_arr[i], set ); 33 | if( select_fd->fd_arr[i] > select_fd->max_fd ){ 34 | select_fd->max_fd = select_fd->fd_arr[i]; 35 | } 36 | } 37 | } 38 | } 39 | 40 | //在数组中为监听到的新的文件描述符分配最小的未被使用的数组下标,来存储 41 | static int add_new_fd(select_fd_t *select_fd, int new_fd) 42 | { 43 | //当数组满了就会添加失败 44 | int i = 1; 45 | for(; i < _FD_NUM_; i++){ 46 | if(select_fd->fd_arr[i] == _FD_DEFAULT_VAL_){ 47 | select_fd->fd_arr[i] = new_fd; 48 | return 0;//yes 49 | } 50 | } 51 | return -1; 52 | } 53 | 54 | //将完成任务的文件描述符从文件描述符集中删除 55 | static void delete_new_fd(select_fd_t *select_fd, int fd ) 56 | { 57 | int i = 1; 58 | for(; i < _FD_NUM_; i++){ 59 | if(select_fd->fd_arr[i] == fd){ 60 | select_fd->fd_arr[i] = _FD_DEFAULT_VAL_; 61 | } 62 | } 63 | } 64 | 65 | //初始化结构体 66 | void init_select_set( select_fd_t *select_fd, int listen_fd ) 67 | { 68 | select_fd->max_fd = listen_fd;//监听新的链接 69 | select_fd->fd_arr[0] = listen_fd; 70 | int i = 1; 71 | for( ;i<_FD_NUM_; i++){ 72 | select_fd->fd_arr[i] = _FD_DEFAULT_VAL_; 73 | } 74 | } 75 | 76 | //读事件就绪后,对数据进行读取 77 | static int read_data_show(int new_fd) 78 | { 79 | char buf[1024]; 80 | ssize_t sz = 0; 81 | int total = 0; 82 | while((sz = read(new_fd, buf+total, 64)) > 0){ 83 | total += sz; 84 | } 85 | if(sz == 0){//success 86 | buf[total] = '\0'; 87 | printf("client data : %s\n",buf); 88 | return 0; 89 | }else if(sz < 0){ 90 | perror("read"); 91 | return -1; 92 | }else{ 93 | //do nothing 94 | } 95 | } 96 | 97 | int start(const char* ip, short port) 98 | { 99 | int sock = socket(AF_INET, SOCK_STREAM, 0); 100 | if( sock < 0 ){ 101 | perror("socket"); 102 | exit(1); 103 | } 104 | //本地信息的填充 105 | struct sockaddr_in local; 106 | local.sin_family = AF_INET; 107 | local.sin_port = htons(port); 108 | local.sin_addr.s_addr = inet_addr(ip);//把点分十进制转化成short int 109 | //绑定链接 110 | if(bind(sock, (struct sockaddr*)&local, sizeof(local)) < 0){ 111 | perror("bind"); 112 | exit(1); 113 | } 114 | //监听链接 115 | if( listen(sock,5) < 0){ 116 | perror("listen"); 117 | exit(1); 118 | } 119 | return sock; 120 | } 121 | 122 | int main(int argc, char* argv[]) 123 | { 124 | if( argc != 3 ){ 125 | usage(argv[1]); 126 | exit(1); 127 | } 128 | int port = atoi(argv[2]); 129 | 130 | int listen_sock = start(argv[1]/*ip*/,port); 131 | if( listen_sock < 0 ){ 132 | perror("start"); 133 | exit(2); 134 | } 135 | // 136 | select_fd_t select_set; 137 | init_select_set(&select_set, listen_sock ); 138 | fd_set r_set;//可读文件描述符的集合 139 | 140 | while(1){ 141 | FD_ZERO(&r_set); 142 | add_read_fd(&r_set, &select_set); 143 | struct timeval timeout={5, 0}; 144 | switch(select(select_set.max_fd+1, &r_set, NULL, NULL, &timeout)){ 145 | case 0://timeout 146 | perror("timeout!"); 147 | break; 148 | case -1://error 149 | perror("select"); 150 | break; 151 | default://success 152 | { 153 | int i = 0; 154 | //遍历数组来确定哪一个文件描述符已经就绪 155 | for(; i < _FD_NUM_; i++){ 156 | int fd = select_set.fd_arr[i]; 157 | if( i == 0 && FD_ISSET(fd, &r_set)){//listen_sock 158 | struct sockaddr_in client; 159 | socklen_t len = sizeof(client); 160 | int new_fd = accept(fd, (struct sockaddr*)&client, &len);//继续监听新的链接 161 | if(new_fd == -1){ 162 | perror("accept"); 163 | continue; 164 | } 165 | if( 0 == add_new_fd(&select_set,new_fd)){//把新的链接加入数组里面 166 | //do nothing 167 | }else{//add error,arr is full 168 | close(fd);//处理不了的链接就直接关闭这个链接 169 | } 170 | continue; 171 | } 172 | if( fd != _FD_DEFAULT_VAL_ && FD_ISSET(fd,&r_set)){ 173 | if( 0 == read_data_show(fd) ){//read success 174 | delete_new_fd(&select_set,fd); 175 | close(fd); 176 | }else{ 177 | //do nothing 178 | } 179 | } 180 | } 181 | } 182 | break; 183 | } 184 | } 185 | return 0; 186 | } 187 | --------------------------------------------------------------------------------