├── chart6 ├── readme.md ├── uecho_client.c └── uecho_server.c ├── chart1 ├── data.txt ├── fds ├── a.out ├── hclient ├── hserver ├── lopen ├── lread ├── fd_seri.c ├── low_open.c ├── low_read.c ├── hello_client.c └── hello_server.c ├── chart3 ├── addr ├── aton ├── conv ├── ntoa ├── endian_conv.c ├── inet_aton.c ├── inet_addr.c ├── inet_ntoa.c └── readme.md ├── chart10 ├── fork ├── zombie ├── zombie.c ├── fork.c └── readme.md ├── chart2 ├── hclient ├── hserver ├── readme.md ├── tcp_client.c └── tcp_server.c ├── chart4 ├── eclient ├── eserver ├── readme.md ├── hello_client.c ├── echo_client.c ├── hello_server.c └── echo_server.c ├── chart5 ├── eclient ├── eserver ├── readme.md ├── echo_server.c └── echo_client.c ├── .uecho_client.c.swp ├── chart19 └── windows平台下线程的使用.md ├── chart20 └── windows线程同步.md └── chart18 ├── chat_clnt.c └── chat_server.c /chart6/readme.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /chart6/uecho_client.c: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /chart1/data.txt: -------------------------------------------------------------------------------- 1 | Let's go! 2 | -------------------------------------------------------------------------------- /chart1/fds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jameswang1016/tcpip/HEAD/chart1/fds -------------------------------------------------------------------------------- /chart3/addr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jameswang1016/tcpip/HEAD/chart3/addr -------------------------------------------------------------------------------- /chart3/aton: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jameswang1016/tcpip/HEAD/chart3/aton -------------------------------------------------------------------------------- /chart3/conv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jameswang1016/tcpip/HEAD/chart3/conv -------------------------------------------------------------------------------- /chart3/ntoa: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jameswang1016/tcpip/HEAD/chart3/ntoa -------------------------------------------------------------------------------- /chart1/a.out: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jameswang1016/tcpip/HEAD/chart1/a.out -------------------------------------------------------------------------------- /chart1/hclient: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jameswang1016/tcpip/HEAD/chart1/hclient -------------------------------------------------------------------------------- /chart1/hserver: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jameswang1016/tcpip/HEAD/chart1/hserver -------------------------------------------------------------------------------- /chart1/lopen: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jameswang1016/tcpip/HEAD/chart1/lopen -------------------------------------------------------------------------------- /chart1/lread: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jameswang1016/tcpip/HEAD/chart1/lread -------------------------------------------------------------------------------- /chart10/fork: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jameswang1016/tcpip/HEAD/chart10/fork -------------------------------------------------------------------------------- /chart10/zombie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jameswang1016/tcpip/HEAD/chart10/zombie -------------------------------------------------------------------------------- /chart2/hclient: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jameswang1016/tcpip/HEAD/chart2/hclient -------------------------------------------------------------------------------- /chart2/hserver: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jameswang1016/tcpip/HEAD/chart2/hserver -------------------------------------------------------------------------------- /chart4/eclient: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jameswang1016/tcpip/HEAD/chart4/eclient -------------------------------------------------------------------------------- /chart4/eserver: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jameswang1016/tcpip/HEAD/chart4/eserver -------------------------------------------------------------------------------- /chart5/eclient: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jameswang1016/tcpip/HEAD/chart5/eclient -------------------------------------------------------------------------------- /chart5/eserver: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jameswang1016/tcpip/HEAD/chart5/eserver -------------------------------------------------------------------------------- /.uecho_client.c.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jameswang1016/tcpip/HEAD/.uecho_client.c.swp -------------------------------------------------------------------------------- /chart2/readme.md: -------------------------------------------------------------------------------- 1 | 说明: 2 | 面向连接的套接字:TCP套接字示例 3 | hello_server.c---->tcp_server.c: 无变化! 4 | hello_client.c---->tcp_client.c: 更改read函数调用方式 5 | 6 | 代码为了验证TCP套接字的如下特性: 7 | “传输的数据不存在数据边界”:为了验证这一点,需要让weite函数的调用次数不同于read函数的调用次数。 8 | 9 | -------------------------------------------------------------------------------- /chart5/readme.md: -------------------------------------------------------------------------------- 1 | chart5:基于TCP的服务器端/客户端(2): 2 | 3 | 5.1回声客户端的完美实现: 4 | - 为了解决之前回声客户端存在的问题: 5 | - 问题1:由于客户端是基于TCP的,因此,多次调用write函数传递的字符串有可能一次性传递到服务端。此时客户端有可能从服务器端收到多个字符串!! 6 | - 问题2:服务端希望通过调用1次write函数传输数据,但如果数据太大,操作系统就有可能把数据包分成多个数据包发送到客户端。另外,在此过程中,客户端有可能在尚未收到全部数据包时就调用read函数。 7 | 8 | echo_client:改进后的客户端 9 | echo_server:相较chart4没有变化。 10 | 11 | ## 5.2TCP原理 12 | 13 | - TCP套接字中的I/O缓存: 14 | 15 | - TCP内部工作原理1:与对方套接字的连接(三次握手) 16 | 17 | - TCP内部工作原理2:与对方主机的数据交换 18 | 19 | - TCP内部工作原理3:断开与套接字的连接(四次挥手) 20 | -------------------------------------------------------------------------------- /chart1/fd_seri.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main(void) 7 | { 8 | int fd1,fd2,fd3; 9 | fd1=socket(PF_INET,SOCK_STREAM,0); 10 | fd2=open("test.dat", O_CREAT|O_WRONLY|O_TRUNC); 11 | fd3=socket(PF_INET,SOCK_DGRAM,0); 12 | 13 | printf("file descriptor 1: %d\n",fd1); 14 | printf("file descriptor 2: %d\n",fd2); 15 | printf("file descriptor 3: %d\n",fd3); 16 | 17 | close(fd1); 18 | close(fd2); 19 | close(fd3); 20 | return 0; 21 | } 22 | 23 | 24 | -------------------------------------------------------------------------------- /chart10/zombie.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | int gval=10; 4 | 5 | int main(int argc, char *argv[]) 6 | { 7 | pid_t pid =fork(); 8 | 9 | if(pid==0) 10 | { 11 | puts("Hi, I am a child process"); 12 | } 13 | else 14 | { 15 | printf("Child Process ID: %d \n", pid); 16 | sleep(30);//Sleep 30 sec 17 | } 18 | 19 | if(pid==0) 20 | { 21 | puts("End child process"); 22 | } 23 | else 24 | { 25 | puts("End parent process"); 26 | } 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /chart3/endian_conv.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char *argv[]) 5 | { 6 | unsigned short host_port=0x1234; 7 | unsigned short net_port; 8 | unsigned long host_addr=0x12345678; 9 | unsigned long net_addr; 10 | 11 | net_port=htons(host_port); 12 | net_addr=htonl(host_addr); 13 | printf("Host ordered port: %#x \n", host_port); 14 | printf("Network ordered port: %#x \n", net_port); 15 | printf("Host ordered address: %#lx \n", host_addr); 16 | printf("Network ordered address: %#lx \n", net_addr); 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /chart4/readme.md: -------------------------------------------------------------------------------- 1 | 4.2:实现基于TCP的服务端/客户端 2 | 3 | tcp服务器端的默认函数调用顺序: 4 | socket创建套接字-->bind分配套接字地址-->listen等待连接请求状态-->accept允许连接-->read/write数据交换-->close断开连接 5 | 6 | hello_server.c 回顾hello world服务器端 7 | 8 | tcp客户端的默认函数调用顺序: 9 | 10 | socket创建套接字-->connect请求连接-->read/write交换数据-->close断开连接 11 | 12 | 13 | 问题: serv_addr.sin_port=htons(atoi(argv[1]));//??argv[1]是啥子意思?? 14 | 回答:读取命令行输入的参数 15 | server里面 socket产生的套接字与accept的套接字到底啥子区别 16 | 回答:https://blog.csdn.net/sinat_24368229/article/details/90264941 17 | 18 | 4.3实现迭代服务器端/客户端 19 | 20 | echo_server.c:回声服务器端 21 | echo_client.c:回声客户端 22 | 23 | -------------------------------------------------------------------------------- /chart10/fork.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int gval=10; 5 | 6 | int main(int argc, char *argv[]) 7 | { 8 | pid_t pid; 9 | int lval=20; 10 | gval++,lval+=5; 11 | 12 | pid=fork(); 13 | 14 | if(pid==0) 15 | { 16 | gval+=2; 17 | lval+=2; 18 | } 19 | else 20 | { 21 | gval-=2; 22 | lval-=2; 23 | } 24 | 25 | if(pid==0) 26 | { 27 | printf("Child Proc: [%d,%d] \n", gval,lval); 28 | } 29 | else 30 | { 31 | printf("Parent Proc: [%d,%d] \n", gval,lval); 32 | } 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /chart3/inet_aton.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | void error_handling(char *message); 5 | 6 | int main(int argc, char *argv[]) 7 | { 8 | char *addr="127.232.124.79"; 9 | struct sockaddr_in addr_inet; 10 | 11 | if(!inet_aton(addr,&addr_inet.sin_addr)) 12 | { 13 | error_handling("Conversion error"); 14 | } 15 | else 16 | { 17 | printf("Network ordered interger addr: %#x \n",addr_inet.sin_addr.s_addr); 18 | } 19 | return 0; 20 | } 21 | 22 | void error_handling(char *message) 23 | { 24 | fputs(message,stderr); 25 | fputc('\n',stderr); 26 | exit(1); 27 | } 28 | 29 | -------------------------------------------------------------------------------- /chart3/inet_addr.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char *argv[]) 5 | { 6 | char *addr1="1.2.3.4"; 7 | char *addr2="1.2.3.256"; 8 | 9 | unsigned long conv_addr=inet_addr(addr1); 10 | if(conv_addr==INADDR_NONE) 11 | { 12 | printf("Error occured! \n"); 13 | } 14 | else 15 | { 16 | printf("Network ordered interger addr: %#lx \n", conv_addr); 17 | } 18 | 19 | conv_addr=inet_addr(addr2); 20 | if(conv_addr==INADDR_NONE) 21 | { 22 | printf("Error occured! \n"); 23 | } 24 | else 25 | { 26 | printf("Network ordered interger addr: %#lx \n\n", conv_addr); 27 | } 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /chart3/inet_ntoa.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | void error_handling(char *message); 5 | 6 | int main(int argc, char *argv[]) 7 | { 8 | char *str_ptr; 9 | struct sockaddr_in addr1,addr2; 10 | char str_arr[20]; 11 | 12 | addr1.sin_addr.s_addr=htonl(0x1020304); 13 | addr2.sin_addr.s_addr=htonl(0x1010101); 14 | 15 | str_ptr=inet_ntoa(addr1.sin_addr); 16 | strcpy(str_arr,str_ptr); 17 | printf("Dotted-Decimal notation1: %s \n", str_ptr); 18 | 19 | inet_ntoa(addr2.sin_addr); 20 | printf("Dotted-Decimal notation2: %s \n", str_ptr); 21 | printf("Dotted-Decimal notation3: %s \n", str_arr); 22 | return 0; 23 | } 24 | 25 | -------------------------------------------------------------------------------- /chart1/low_open.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | void error_handling(char* message); 6 | 7 | int main(void) 8 | { 9 | int fd; 10 | char buf[]="Let's go!\n"; 11 | 12 | fd=open("data.txt", O_CREAT|O_WRONLY|O_TRUNC); 13 | if(fd==-1) 14 | { 15 | error_handling("open() error!"); 16 | } 17 | printf("file descriptor: %d \n", fd); 18 | 19 | if(write(fd,buf,sizeof(buf))==-1) 20 | { 21 | error_handling("write() error!"); 22 | } 23 | close(fd); 24 | return 0; 25 | } 26 | 27 | void error_handling(char *message) 28 | { 29 | fputs(message,stderr); 30 | fputc('\n',stderr); 31 | exit(1); 32 | } 33 | 34 | -------------------------------------------------------------------------------- /chart1/low_read.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #define BUF_SIZE 100 6 | void error_handling(char* message); 7 | 8 | int main(void) 9 | { 10 | int fd; 11 | char buf[BUF_SIZE]; 12 | 13 | fd=open("data.txt", O_RDONLY); 14 | if(fd==-1) 15 | { 16 | error_handling("open() error!"); 17 | } 18 | printf("file descriptor: %d \n", fd); 19 | 20 | if(read(fd,buf,sizeof(buf))==-1) 21 | { 22 | error_handling("read() error!"); 23 | } 24 | printf("file data: %s", buf); 25 | close(fd); 26 | return 0; 27 | } 28 | 29 | void error_handling(char *message) 30 | { 31 | fputs(message,stderr); 32 | fputc('\n',stderr); 33 | exit(1); 34 | } 35 | -------------------------------------------------------------------------------- /chart3/readme.md: -------------------------------------------------------------------------------- 1 | 字节序转换: 2 | endian_conv.c展示的是主机字节序与网络字节序之间的转换: 3 | ubuntu@ubuntu:~/jameswang/code/tcpip/chart3$ gcc endian_conv.c -o conv 4 | ubuntu@ubuntu:~/jameswang/code/tcpip/chart3$ ./conv 5 | Host ordered port: 0x1234 6 | Network ordered port: 0x3412 7 | Host ordered address: 0x12345678 8 | Network ordered address: 0x78563412 9 | 10 | 11 | 12 | 3.4网络地址的初始化与分配 13 | 14 | inet_addr.c:点分十进制格式的字符串转换为32为整形数据并返回: 15 | 运行结果: 16 | ubuntu@ubuntu:~/jameswang/code/tcpip/chart3$ ./addr 17 | Network ordered interger addr: 0x4030201 18 | Error occured! 19 | 从运行结果看出:inet_addr函数不仅可以把ip地址转化为32位整数型,而且可以检测无效的ip地址 20 | 21 | inet_aton.c跟上面的功能相同,只不过该函数利用了in_addr结构体,且其使用频率更高! 22 | 运行结果: 23 | ubuntu@ubuntu:~/jameswang/code/tcpip/chart3$ ./aton 24 | Network ordered interger addr: 0x4f7ce87f 25 | 26 | inet_ntoa.c:网络字节序整数型IP地址转化为我们熟悉的点分十进制字符串形式。 27 | 运行结果: 28 | ubuntu@ubuntu:~/jameswang/code/tcpip/chart3$ ./ntoa 29 | Dotted-Decimal notation1: 1.2.3.4 30 | Dotted-Decimal notation2: 1.1.1.1 31 | Dotted-Decimal notation3: 1.2.3.4 32 | -------------------------------------------------------------------------------- /chart19/windows平台下线程的使用.md: -------------------------------------------------------------------------------- 1 | # 19.1 内核对象 2 | 3 | # 19.2基于windows的线程创建 4 | 5 | - CreateThread函数 6 | - _beginthreadex函数(线程安全的) 7 | 8 | - uintptr_t _beginthreadex (void * security, unsigned stack_size,unsigned(* start_address)(void *),void * arglist,unsigned initflag,unsigned * thrdaddr); 9 | 10 | - 重点关注一下3,4,6形参 11 | - start_address:传递线程的main函数信息 12 | 13 | - arglist:调用main函数时传递的参数信息 14 | 15 | - thrdaddr:用于保存线程ID的变量地址值 16 | 17 | 18 | # 内核对象的2种状态 19 | ## 内核对象的状态以及状态查看 20 | 21 | - 线程内核对象中需要重点关注线程是否终止: 22 | - 终止:signaled状态 23 | - 未终止:non_signaled状态 24 | 25 | - 进程或线程终止时,操作系统会把相应的内核对象改为signaled状态 26 | 27 | ## WaitForSingleObject & WaitForMultipleObject 28 | 29 | - DWORD WaitForSingleObject(HANDLE hHandle,DWORD dwMilliseconds); 30 | 31 | - hHandle:查看状态的内核对象句柄 32 | - dwMilliseconds: 以1/1000秒为单位指定超时,传递INFINITE时函数不会返回,直到内核对象变成signaled状态 33 | - 返回值:进入signaled状态返回 WAIT_OBJECT_0,超时返回WAIT——TIMEOUT 34 | 35 | 内核对象的两种模式 36 | - auto_reset模式:该函数由于发生时间(变为signaled状态)返回时,有时会把相应内核对象再次改为non-signaled状态。这种可以再次进入non-signaled状态的内核对象称为auto_reset模式。 37 | 38 | - manual-reset模式:该函数由于发生时间(变为signaled状态)返回时,不会自动将内核对象改为non-signaled状态。这种内核对象称为auto_reset模式。 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /chart1/hello_client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | void error_handling(char *message); 8 | 9 | int main(int argc,char *argv[]) 10 | { 11 | int sock; 12 | struct sockaddr_in serv_addr; 13 | char message[30]; 14 | int str_len; 15 | if(argc!=3) 16 | { 17 | printf("Usag : %s \n",argv[0]); 18 | exit(1); 19 | } 20 | 21 | sock=socket(PF_INET,SOCK_STREAM, 0); 22 | if(sock ==-1) 23 | { 24 | error_handling("socket() error"); 25 | } 26 | 27 | memset(&serv_addr, 0, sizeof(serv_addr)); 28 | serv_addr.sin_family=AF_INET; 29 | serv_addr.sin_addr.s_addr=inet_addr(argv[1]); 30 | serv_addr.sin_port=htons(atoi(argv[2])); 31 | 32 | if(connect(sock,(struct sockaddr*) &serv_addr,sizeof(serv_addr))==-1) 33 | { 34 | error_handling("connect() error"); 35 | } 36 | 37 | str_len=read(sock,message, sizeof(message)-1); 38 | if(str_len==-1) 39 | { 40 | error_handling("read() error"); 41 | } 42 | 43 | printf("Message from server : %s \n", message); 44 | close(sock); 45 | return 0; 46 | } 47 | 48 | void error_handling(char *message) 49 | { 50 | fputs(message,stderr); 51 | fputc('\n',stderr); 52 | exit(1); 53 | } 54 | 55 | -------------------------------------------------------------------------------- /chart4/hello_client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | void error_handling(char *message); 8 | 9 | int main(int argc,char *argv[]) 10 | { 11 | int sock; 12 | struct sockaddr_in serv_addr; 13 | char message[30]; 14 | int str_len; 15 | if(argc!=3) 16 | { 17 | printf("Usag : %s \n",argv[0]); 18 | exit(1); 19 | } 20 | 21 | sock=socket(PF_INET,SOCK_STREAM, 0); 22 | if(sock ==-1) 23 | { 24 | error_handling("socket() error"); 25 | } 26 | 27 | memset(&serv_addr, 0, sizeof(serv_addr)); 28 | serv_addr.sin_family=AF_INET; 29 | serv_addr.sin_addr.s_addr=inet_addr(argv[1]); 30 | serv_addr.sin_port=htons(atoi(argv[2])); 31 | 32 | if(connect(sock,(struct sockaddr*) &serv_addr,sizeof(serv_addr))==-1) 33 | { 34 | error_handling("connect() error"); 35 | } 36 | 37 | str_len=read(sock,message, sizeof(message)-1); 38 | if(str_len==-1) 39 | { 40 | error_handling("read() error"); 41 | } 42 | 43 | printf("Message from server : %s \n", message); 44 | close(sock); 45 | return 0; 46 | } 47 | 48 | void error_handling(char *message) 49 | { 50 | fputs(message,stderr); 51 | fputc('\n',stderr); 52 | exit(1); 53 | } 54 | 55 | -------------------------------------------------------------------------------- /chart2/tcp_client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | void error_handling(char *message); 8 | 9 | int main(int argc,char *argv[]) 10 | { 11 | int sock; 12 | struct sockaddr_in serv_addr; 13 | int idx=0,read_len=0; 14 | char message[30]; 15 | int str_len=0; 16 | if(argc!=3) 17 | { 18 | printf("Usag : %s \n",argv[0]); 19 | exit(1); 20 | } 21 | 22 | sock=socket(PF_INET,SOCK_STREAM, 0); 23 | if(sock ==-1) 24 | { 25 | error_handling("socket() error"); 26 | } 27 | 28 | memset(&serv_addr, 0, sizeof(serv_addr)); 29 | serv_addr.sin_family=AF_INET; 30 | serv_addr.sin_addr.s_addr=inet_addr(argv[1]); 31 | serv_addr.sin_port=htons(atoi(argv[2])); 32 | 33 | if(connect(sock,(struct sockaddr*) &serv_addr,sizeof(serv_addr))==-1) 34 | { 35 | error_handling("connect() error"); 36 | } 37 | 38 | while(read_len=read(sock,&message[idx++], 1)) 39 | { 40 | if(str_len==-1) 41 | { 42 | error_handling("read() error"); 43 | } 44 | str_len+=read_len; 45 | } 46 | printf("Message from server : %s \n", message); 47 | printf("function read call count : %d \n", str_len); 48 | close(sock); 49 | return 0; 50 | } 51 | 52 | void error_handling(char *message) 53 | { 54 | fputs(message,stderr); 55 | fputc('\n',stderr); 56 | exit(1); 57 | } 58 | 59 | -------------------------------------------------------------------------------- /chart20/windows线程同步.md: -------------------------------------------------------------------------------- 1 | ## 2 | # 20.2内核模式的同步方式 3 | 4 | ## 基于互斥量对象的同步 5 | 6 | - 互斥量被某一线程获取时为non-signaled,释放的时候进入signaled状态。可以使用WaitSingleObject函数验证互斥量是否已分配。该函数调用结果有两种: 7 | 8 | - 调用后进入阻塞状态:互斥量对象已被其他线程获取,现在处于non-signaled 9 | - 调用后直接返回:其他线程未占用互斥量对象,现处于signaled状态。 **注意互斥量在WaitSingleObject函数返回后进入non-signaled** 10 | 11 | - HANDLE Createmutex(LPSECURITY_ATTRIBUTES lpMutexAttributes,BOOL bInitialOwner,LPCTSTR lpName); 12 | - 成功时返回创建的互斥量对象句柄,失败时返回NULL。 13 | -lpMutexAttributes:传递安全相关的配置信息 14 | - bInitialOwner:如果为TRUE,则创建出的互斥量对象属于调用该函数的线程,同事进入non-signaled状态;如果为FALSE,那么此时状态为signaled 15 | - lpName: 16 | 17 | - CloseHandle:销毁内核对象 18 | 19 | - BOOL ReleaseMutex(HANDLE hMutex):释放互斥量的函数 20 | 21 | 22 | 23 | -基于互斥量的临界区保护代码 24 | 25 | WaitSingleObject(hMutex,INFINITE); 26 | //临界区的开始 27 | //..... 28 | //临界区的结束 29 | ReleaseMutex(hMutex); 30 | 31 | WaitSingleObject函数使互斥量进入non-signaled状态,限制访问临界区,所以相当于临界区的门禁系统。相反,ReleaseMutex函数使互斥量重新进入signaled状态,所以相当于临界区的出口 32 | 33 | 34 | 35 | 36 | ## 基于事件的同步 37 | - 事件同步与互斥量同步相比有很大不同,区别在于,该方式下创建的对象,可以在auto-reset模式以及manual-reset模式中任选其一 38 | - CreateEvent(LPSECURITY_ATTRIBUTES lpMutexAttributes,BOOL bManualReset,BOOL bInitialState,LPCTSTR lpName); 39 | 40 | - bManualReset:传入TRUE时创建manual-reset模式的事件对象,传入FALSE时创建auto-reset模式的事件对象 41 | - bInitialState:传入TRUE时创建signaled状态的事件对象,传入FALSE时创建non-signaled状态的事件对象 42 | 43 | - manual-reset模式下常用的两个函数:(这两个函数也是配合WaitSingleObject函数一起实现同步的) 44 | - ResetEvent//to the non-signaled 45 | - SetEvent //to the signaled 46 | -------------------------------------------------------------------------------- /chart6/uecho_server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define BUF_SIZE 30 9 | void error_handling(char *message); 10 | 11 | int main(int argc,char *argv[]) 12 | { 13 | int serv_sock; 14 | int str_len; 15 | struct sockaddr_in serv_adr; 16 | struct sockaddr_in clnt_adr; 17 | socklen_t clnt_adr_sz; 18 | 19 | char message[BUF_SIZE]; 20 | 21 | if(argc!=2) 22 | { 23 | printf("Usag : %s \n",argv[0]); 24 | exit(1); 25 | } 26 | 27 | serv_sock=socket(PF_INET,SOCK_DGRAM, 0); 28 | if(serv_sock ==-1) 29 | { 30 | error_handling("UDP socket creation error"); 31 | } 32 | 33 | memset(&serv_adr, 0, sizeof(serv_adr)); 34 | serv_adr.sin_family=AF_INET; 35 | serv_adr.sin_addr.s_addr=htonl(INADDR_ANY); 36 | serv_adr.sin_port=htons(atoi(argv[1])); 37 | if(bind(serv_sock,(struct sockaddr*) &serv_adr,sizeof(serv_adr))==-1) 38 | { 39 | error_handling("bind() error"); 40 | } 41 | while(1) 42 | { 43 | clnt_adr_sz=sizeof(clnt_adr); 44 | str_len=recvfrom(serv_sock,message,BUF_SIZE,O,(struct sockaddr*)&clnt_adr,&clnt_adr_sz); 45 | sendto(serv_sock,message,str_len,0,(struct sockaddr*)&clnt_adr,clnt_adr_sz); 46 | } 47 | close(serv_sock); 48 | return 0; 49 | 50 | } 51 | 52 | void error_handling(char *message) 53 | { 54 | fputs(message,stderr); 55 | fputc('\n',stderr); 56 | exit(1); 57 | } 58 | 59 | -------------------------------------------------------------------------------- /chart1/hello_server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | void error_handling(char *message); 8 | 9 | int main(int argc,char *argv[]) 10 | { 11 | int serv_sock; 12 | int clnt_sock; 13 | 14 | struct sockaddr_in serv_addr; 15 | struct sockaddr_in clnt_addr; 16 | socklen_t clnt_addr_size; 17 | 18 | char message[]="Hello World"; 19 | 20 | if(argc!=2) 21 | { 22 | printf("Usag : %s \n",argv[0]); 23 | exit(1); 24 | } 25 | 26 | serv_sock=socket(PF_INET,SOCK_STREAM, 0); 27 | if(serv_sock ==-1) 28 | { 29 | error_handling("socket() error"); 30 | } 31 | 32 | memset(&serv_addr, 0, sizeof(serv_addr)); 33 | serv_addr.sin_family=AF_INET; 34 | serv_addr.sin_addr.s_addr=htonl(INADDR_ANY); 35 | serv_addr.sin_port=htons(atoi(argv[1])); 36 | 37 | if(bind(serv_sock,(struct sockaddr*) &serv_addr,sizeof(serv_addr))==-1) 38 | { 39 | error_handling("bind() error"); 40 | } 41 | 42 | if(listen(serv_sock,5)==-1) 43 | { 44 | error_handling("listen() error"); 45 | } 46 | 47 | clnt_addr_size=sizeof(clnt_addr); 48 | clnt_sock=accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size); 49 | if(clnt_sock==-1) 50 | { 51 | error_handling("accpt() error"); 52 | } 53 | 54 | write(clnt_sock,message,sizeof(message)); 55 | close(clnt_sock); 56 | close(serv_sock); 57 | return 0; 58 | } 59 | 60 | void error_handling(char *message) 61 | { 62 | fputs(message,stderr); 63 | fputc('\n',stderr); 64 | exit(1); 65 | } 66 | -------------------------------------------------------------------------------- /chart2/tcp_server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | void error_handling(char *message); 8 | 9 | int main(int argc,char *argv[]) 10 | { 11 | int serv_sock; 12 | int clnt_sock; 13 | 14 | struct sockaddr_in serv_addr; 15 | struct sockaddr_in clnt_addr; 16 | socklen_t clnt_addr_size; 17 | 18 | char message[]="Hello World"; 19 | 20 | if(argc!=2) 21 | { 22 | printf("Usag : %s \n",argv[0]); 23 | exit(1); 24 | } 25 | 26 | serv_sock=socket(PF_INET,SOCK_STREAM, 0); 27 | if(serv_sock ==-1) 28 | { 29 | error_handling("socket() error"); 30 | } 31 | 32 | memset(&serv_addr, 0, sizeof(serv_addr)); 33 | serv_addr.sin_family=AF_INET; 34 | serv_addr.sin_addr.s_addr=htonl(INADDR_ANY); 35 | serv_addr.sin_port=htons(atoi(argv[1])); 36 | 37 | if(bind(serv_sock,(struct sockaddr*) &serv_addr,sizeof(serv_addr))==-1) 38 | { 39 | error_handling("bind() error"); 40 | } 41 | 42 | if(listen(serv_sock,5)==-1) 43 | { 44 | error_handling("listen() error"); 45 | } 46 | 47 | clnt_addr_size=sizeof(clnt_addr); 48 | clnt_sock=accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size); 49 | if(clnt_sock==-1) 50 | { 51 | error_handling("accpt() error"); 52 | } 53 | 54 | write(clnt_sock,message,sizeof(message)); 55 | close(clnt_sock); 56 | close(serv_sock); 57 | return 0; 58 | } 59 | 60 | void error_handling(char *message) 61 | { 62 | fputs(message,stderr); 63 | fputc('\n',stderr); 64 | exit(1); 65 | } 66 | 67 | -------------------------------------------------------------------------------- /chart4/echo_client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #define BUF_SIZE 1024 8 | void error_handling(char *message); 9 | 10 | int main(int argc,char *argv[]) 11 | { 12 | int sock; 13 | struct sockaddr_in serv_adr; 14 | char message[BUF_SIZE]; 15 | int str_len; 16 | if(argc!=3) 17 | { 18 | printf("Usag : %s \n",argv[0]); 19 | exit(1); 20 | } 21 | 22 | sock=socket(PF_INET,SOCK_STREAM, 0); 23 | if(sock ==-1) 24 | { 25 | error_handling("socket() error"); 26 | } 27 | 28 | memset(&serv_adr, 0, sizeof(serv_adr)); 29 | serv_adr.sin_family=AF_INET; 30 | serv_adr.sin_addr.s_addr=inet_addr(argv[1]); 31 | serv_adr.sin_port=htons(atoi(argv[2])); 32 | 33 | if(connect(sock,(struct sockaddr*)&serv_adr,sizeof(serv_adr))==-1) 34 | { 35 | error_handling("connect() error"); 36 | } 37 | else 38 | { 39 | puts("Connected........"); 40 | } 41 | while(1) 42 | { 43 | fputs("Input message(Q to quit): ", stdout); 44 | fgets(message,BUF_SIZE, stdin); 45 | 46 | if(!strcmp(message,"q\n") || !strcmp(message,"Q\n")) 47 | { 48 | break; 49 | } 50 | write(sock,message,strlen(message)); 51 | str_len=read(sock,message, BUF_SIZE-1); 52 | message[str_len]=0; 53 | printf("Message from server : %s", message); 54 | 55 | } 56 | 57 | 58 | close(sock); 59 | return 0; 60 | } 61 | 62 | void error_handling(char *message) 63 | { 64 | fputs(message,stderr); 65 | fputc('\n',stderr); 66 | exit(1); 67 | } 68 | 69 | -------------------------------------------------------------------------------- /chart10/readme.md: -------------------------------------------------------------------------------- 1 | #10.1进程概念及应用 2 | 3 | ##通过调用fork函数创建进程:fork.c 4 | 5 | - 父进程:fork函数返回子进程ID。 6 | - 子进程:fork函数返回0; 7 | 8 | ## 10.2进程和僵尸进程 9 | 10 | - 产生僵尸进程的原因 11 | 12 | 调用fork函数产生子进程的终止方式:1.传递参数并调用exit函数 13 | 2.main函数中执行return语句并返回值 14 | 向exit函数传递的参数值和main函数的return语句返回的值都会传递给操作系统。而操作系统不会销毁子进程,××直到把这些值传递给产生该子进程的父进程×。处于这个状态下的进程就是僵尸进程。将子进程变成僵尸进程的正是操作系统。 15 | 16 | - 如何销毁: 17 | 应该向创建子进程的父进程传递子进程的exit参数值或return语句的返回值。 18 | 操作系统不会主动把这些参数传递给父进程。只有父进程主动发起请求(函数调用)时,操作系统才会传递该值。即如果父进程未主动要求获得子进程的结束状态值,操作系统将一直保存,并让子进程长时间处于僵尸进程状态。 19 | 20 | zombie.c是僵尸进程的原因:运行之后的结果如下所示: 21 | ubuntu@ubuntu:~/code/tcpip/chart10$ ./zombie 22 | Child Process ID: 77260 23 | Hi, I am a child process 24 | End child process 25 | 26 | 程序开始运行后,将在如上所示的状态暂停,跳出这种状态前(30秒内),应验证子进程是否为僵尸进程,如下所示: 27 | ubuntu@ubuntu:~$ ps au 28 | USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND 29 | root 3791 0.0 0.0 23008 252 tty1 Ss+ 5月29 0:00 /sbin/age 30 | root 3799 0.0 3.3 498680 66984 tty7 Ssl+ 5月29 0:54 /usr/lib/ 31 | ubuntu 75574 0.0 0.1 29832 3744 pts/4 Ss+ 10:29 0:00 /bin/bash 32 | ubuntu 75584 0.0 0.1 29796 3820 pts/18 Ss 10:29 0:00 /bin/bash 33 | ubuntu 75594 0.0 0.1 29768 2576 pts/19 Ss 10:29 0:00 /bin/bash 34 | ubuntu 75604 0.0 0.1 29768 2668 pts/20 Ss+ 10:29 0:00 /bin/bash 35 | ubuntu 77259 0.0 0.0 4356 724 pts/18 S+ 14:34 0:00 ./zombie 36 | ubuntu 77260 0.0 0.0 0 0 pts/18 Z+ 14:34 0:00 [zombie] < 37 | ubuntu 77261 0.0 0.1 44432 3052 pts/19 R+ 14:34 0:00 ps au 38 | 39 | 可以看出PID为77260的进程为僵尸进程(Z+)。另外,经过30秒的等待后,PID为10976的父进程和之前的僵尸子进程同时销毁。 40 | 41 | -------------------------------------------------------------------------------- /chart4/hello_server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | void error_handling(char *message); 8 | 9 | int main(int argc,char *argv[]) 10 | { 11 | int serv_sock; 12 | int clnt_sock; 13 | 14 | struct sockaddr_in serv_addr; 15 | struct sockaddr_in clnt_addr; 16 | socklen_t clnt_addr_size; 17 | 18 | char message[]="Hello World"; 19 | 20 | if(argc!=2) 21 | { 22 | printf("Usag : %s \n",argv[0]); 23 | exit(1); 24 | } 25 | //服务端实现过程中先要创建套接字,但此时的套接字并非真正的服务器端套接字 26 | serv_sock=socket(PF_INET,SOCK_STREAM, 0); 27 | if(serv_sock ==-1) 28 | { 29 | error_handling("socket() error"); 30 | } 31 | 32 | memset(&serv_addr, 0, sizeof(serv_addr)); 33 | serv_addr.sin_family=AF_INET; 34 | serv_addr.sin_addr.s_addr=htonl(INADDR_ANY); 35 | serv_addr.sin_port=htons(atoi(argv[1]));//??argv[1]是啥子意思?? 36 | 37 | if(bind(serv_sock,(struct sockaddr*) &serv_addr,sizeof(serv_addr))==-1) 38 | { 39 | error_handling("bind() error"); 40 | } 41 | //调用listen函数进入等待连接请求状态。连接请求等待队列的长度设置为5.此时的套接字才是真正的服务器端套接字! 42 | if(listen(serv_sock,5)==-1) 43 | { 44 | error_handling("listen() error"); 45 | } 46 | 47 | clnt_addr_size=sizeof(clnt_addr); 48 | clnt_sock=accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size); 49 | if(clnt_sock==-1) 50 | { 51 | error_handling("accpt() error"); 52 | } 53 | 54 | write(clnt_sock,message,sizeof(message)); 55 | close(clnt_sock); 56 | close(serv_sock); 57 | return 0; 58 | } 59 | 60 | void error_handling(char *message) 61 | { 62 | fputs(message,stderr); 63 | fputc('\n',stderr); 64 | exit(1); 65 | } 66 | -------------------------------------------------------------------------------- /chart4/echo_server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define BUF_SIZE 1024 9 | void error_handling(char *message); 10 | int main(int argc,char *argv[]) 11 | { 12 | int serv_sock; 13 | int clnt_sock; 14 | int str_len,i; 15 | struct sockaddr_in serv_adr; 16 | struct sockaddr_in clnt_adr; 17 | socklen_t clnt_adr_sz; 18 | 19 | char message[BUF_SIZE]; 20 | 21 | if(argc!=2) 22 | { 23 | printf("Usag : %s \n",argv[0]); 24 | exit(1); 25 | } 26 | 27 | serv_sock=socket(PF_INET,SOCK_STREAM, 0); 28 | if(serv_sock ==-1) 29 | { 30 | error_handling("socket() error"); 31 | } 32 | 33 | memset(&serv_adr, 0, sizeof(serv_adr)); 34 | serv_adr.sin_family=AF_INET; 35 | serv_adr.sin_addr.s_addr=htonl(INADDR_ANY); 36 | serv_adr.sin_port=htons(atoi(argv[1])); 37 | 38 | if(bind(serv_sock,(struct sockaddr*) &serv_adr,sizeof(serv_adr))==-1) 39 | { 40 | error_handling("bind() error"); 41 | } 42 | 43 | if(listen(serv_sock,5)==-1) 44 | { 45 | error_handling("listen() error"); 46 | } 47 | 48 | clnt_adr_sz=sizeof(clnt_adr); 49 | for(i=0;i<5;i++) 50 | { 51 | clnt_sock=accept(serv_sock, (struct sockaddr*)&clnt_adr, &clnt_adr_sz); 52 | if(clnt_sock==-1) 53 | { 54 | error_handling("accpt() error"); 55 | } 56 | else 57 | { 58 | printf("Connected client %d \n", i+1); 59 | } 60 | while((str_len=read(clnt_sock,message,BUF_SIZE))!=0) 61 | { 62 | write(clnt_sock,message,str_len); 63 | printf("Connected client %d \n", i+1); 64 | } 65 | close(clnt_sock); 66 | } 67 | close(serv_sock); 68 | return 0; 69 | } 70 | 71 | void error_handling(char *message) 72 | { 73 | fputs(message,stderr); 74 | fputc('\n',stderr); 75 | exit(1); 76 | } 77 | 78 | -------------------------------------------------------------------------------- /chart5/echo_server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define BUF_SIZE 1024 9 | void error_handling(char *message); 10 | int main(int argc,char *argv[]) 11 | { 12 | int serv_sock; 13 | int clnt_sock; 14 | int str_len,i; 15 | struct sockaddr_in serv_adr; 16 | struct sockaddr_in clnt_adr; 17 | socklen_t clnt_adr_sz; 18 | 19 | char message[BUF_SIZE]; 20 | 21 | if(argc!=2) 22 | { 23 | printf("Usag : %s \n",argv[0]); 24 | exit(1); 25 | } 26 | 27 | serv_sock=socket(PF_INET,SOCK_STREAM, 0); 28 | if(serv_sock ==-1) 29 | { 30 | error_handling("socket() error"); 31 | } 32 | 33 | memset(&serv_adr, 0, sizeof(serv_adr)); 34 | serv_adr.sin_family=AF_INET; 35 | serv_adr.sin_addr.s_addr=htonl(INADDR_ANY); 36 | serv_adr.sin_port=htons(atoi(argv[1])); 37 | 38 | if(bind(serv_sock,(struct sockaddr*) &serv_adr,sizeof(serv_adr))==-1) 39 | { 40 | error_handling("bind() error"); 41 | } 42 | 43 | if(listen(serv_sock,5)==-1) 44 | { 45 | error_handling("listen() error"); 46 | } 47 | 48 | clnt_adr_sz=sizeof(clnt_adr); 49 | for(i=0;i<5;i++) 50 | { 51 | clnt_sock=accept(serv_sock, (struct sockaddr*)&clnt_adr, &clnt_adr_sz); 52 | if(clnt_sock==-1) 53 | { 54 | error_handling("accpt() error"); 55 | } 56 | else 57 | { 58 | printf("Connected client %d \n", i+1); 59 | } 60 | while((str_len=read(clnt_sock,message,BUF_SIZE))!=0) 61 | { 62 | write(clnt_sock,message,str_len); 63 | printf("Connected client %d \n", i+1); 64 | } 65 | close(clnt_sock); 66 | } 67 | close(serv_sock); 68 | return 0; 69 | } 70 | 71 | void error_handling(char *message) 72 | { 73 | fputs(message,stderr); 74 | fputc('\n',stderr); 75 | exit(1); 76 | } 77 | 78 | -------------------------------------------------------------------------------- /chart5/echo_client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #define BUF_SIZE 1024 8 | void error_handling(char *message); 9 | 10 | int main(int argc,char *argv[]) 11 | { 12 | int sock; 13 | struct sockaddr_in serv_adr; 14 | char message[BUF_SIZE]; 15 | int str_len,recv_len,recv_cnt; 16 | if(argc!=3) 17 | { 18 | printf("Usag : %s \n",argv[0]); 19 | exit(1); 20 | } 21 | 22 | sock=socket(PF_INET,SOCK_STREAM, 0); 23 | if(sock ==-1) 24 | { 25 | error_handling("socket() error"); 26 | } 27 | 28 | memset(&serv_adr, 0, sizeof(serv_adr)); 29 | serv_adr.sin_family=AF_INET; 30 | serv_adr.sin_addr.s_addr=inet_addr(argv[1]); 31 | serv_adr.sin_port=htons(atoi(argv[2])); 32 | 33 | if(connect(sock,(struct sockaddr*)&serv_adr,sizeof(serv_adr))==-1) 34 | { 35 | error_handling("connect() error"); 36 | } 37 | else 38 | { 39 | puts("Connected........"); 40 | } 41 | while(1) 42 | { 43 | fputs("Input message(Q to quit): ", stdout); 44 | fgets(message,BUF_SIZE, stdin); 45 | 46 | if(!strcmp(message,"q\n") || !strcmp(message,"Q\n")) 47 | { 48 | break; 49 | } 50 | str_len= write(sock,message,strlen(message)); 51 | recv_len=0; 52 | while(recv_len 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #define BUF_SIZE 100 9 | #define NAME_SIZE 20 10 | 11 | void send_msg(char *msg); 12 | void recv_msg(void *arg); 13 | void error_handling(char *msg); 14 | 15 | char name[NAME_SIZE]="[DEFAULT]"; 16 | char msg[BUF_SIZE]; 17 | 18 | 19 | int main(int argc,char *argv[]) 20 | { 21 | int sock; 22 | struct sockaddr_in serv_addr; 23 | pthread_t snd_thread,rcv_thread; 24 | void * thread_return; 25 | if(argc!=4) 26 | { 27 | printf("Usage: %s \n",argv[0]); 28 | exit(1); 29 | } 30 | 31 | sprintf(name,"[%s]",argv[3]); 32 | sock=socket(PF_INET,SOCK_STREAM,0); 33 | 34 | memset(&serv_adr,0,sizeof(serv_addr)); 35 | serv_addr.sin_family=AF_INET; 36 | serv_addr.sin_addr.s_addr=inet_addr(argv[1]); 37 | serv_addr.sin_port=htons(atoi(argv[2])); 38 | 39 | if(connect(sock,(struct sockaddr*)&serv_addr),sizeof(serv_addr))==-1) 40 | { 41 | error_handling("connect() error"); 42 | } 43 | pthread_create(&snd_thread,NULL,send_msg,(void*)&sock); 44 | pthread_create(&rcv_thread,NULL,recv_msg,(void*)&sock); 45 | pthread_join(snd_thread,&thread_return); 46 | pthread_join(rcv_thread,&thread_return); 47 | 48 | close(sock); 49 | return 0; 50 | } 51 | 52 | 53 | 54 | void * send_msg(char * msg) 55 | { 56 | int sock=*((int *)arg); 57 | char name_msg[NAME_SIZE+BUF_SIZE]; 58 | while(1) 59 | { 60 | fgets(msg,BUF_SIZE,stdin); 61 | if(!strcmp(msg,"q\n")|| !strcmp(msg,"Q\n")) 62 | { 63 | close(sock); 64 | exit(0); 65 | } 66 | sprintf(name_msg,"%s %s",name,msg); 67 | write(sock,name_msg,strlen(name_msg)); 68 | } 69 | 70 | void * recv_msg(void * arg) 71 | { 72 | int sock=*((int *)arg); 73 | char name_msg[NAME_SIZE+BUF_SIZE]; 74 | int str_len; 75 | while(1) 76 | { 77 | str_len=read(sock,name_msg,NAME_SIZE+BUF_SIZE-1); 78 | if(str_len==-1) 79 | { 80 | return (void*)-1; 81 | } 82 | name_msg[str_len]=0; 83 | fputs(name_msg,stdout); 84 | } 85 | 86 | return NULL; 87 | } 88 | void error_handling(char *message) 89 | { 90 | fputs(message,stderr); 91 | fputc('\n',stderr); 92 | exit(1); 93 | } 94 | -------------------------------------------------------------------------------- /chart18/chat_server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #define BUF_SIZE 100 8 | #DEFINE MAX_CLNT 256 9 | 10 | void * handle_clnt(void * arg); 11 | void send_msg(char *msg,int len); 12 | void error_handling(char *msg); 13 | 14 | int clnt_cnt=0; 15 | int clnt_socks[MAX_CLNT]; 16 | PTHREAD_MUTEX_T MUTX; 17 | 18 | 19 | int main(int argc,char *argv[]) 20 | { 21 | int serv_sock,clnt_sock; 22 | struct sockaddr_in serv_adr,clnt_adr; 23 | int clnt_adr_sz; 24 | pthread_t t_id; 25 | if(argc!=2) 26 | { 27 | printf("Usage: %s \n",argv[0]); 28 | exit(1); 29 | } 30 | 31 | pthread_mutex_init(&mutx,NULL); 32 | serv_sock=socket(PF_INET,SOCK_STREAM,0); 33 | 34 | memset(&serv_adr,0,sizeof(serv_adr)); 35 | serv_adr.sin_family=AF_INET; 36 | serv_adr.sin_addr.s_addr=htonl(INADDR_ANY); 37 | serv_adr.sin_port=htons(atoi(argv[1])); 38 | 39 | if(bind(serv_sock,(struct sockaddr*)&serv_adr),sizeof(serv_adr))==-1) 40 | { 41 | error_handling("bind() error"); 42 | } 43 | if(listen(serv_sock,5)==-1) 44 | { 45 | error_handling("listen() error"); 46 | } 47 | 48 | while(1) 49 | { 50 | clnt_adr_sz=sizeof(clnt_adr); 51 | clnt_sock=accept(serv_sock,(struct sockaddr*)&clnt_adr,&clnt_adr_sz); 52 | 53 | pthread_mutxe_lock(&mutx); 54 | clnt_socks[clnt_cnt++]=clnt_sock; 55 | pthread_mutex_unlock(&mutx); 56 | 57 | pthread_create(&t_id,NULL,handle_clnt,(void*)&clnt_sock); 58 | pthread_detach(t_id); 59 | printf(); 60 | } 61 | close(serv_sock); 62 | return 0; 63 | } 64 | 65 | 66 | void * handle_clnt(void *arg) 67 | { 68 | int clnt_sock=*((int*)arg); 69 | int str_len=0,i; 70 | char msg[BUF_SIZE]; 71 | 72 | while((str_len=read(clnt_sock,msg,sizeof(msg)))!=0) 73 | send_msg(msg,str_len); 74 | pthread_mutex_lock(&mutx); 75 | for(i=0;i