├── .client.c.swp ├── .server.c.swp ├── 03-p2p ├── p2pClient ├── p2pServer ├── .Makefile.swp ├── .p2pClient.c.swp ├── .p2pServer.c.swp ├── Makefile ├── common.h ├── p2pClient.c └── p2pServer.c ├── 01-echo ├── echoClient ├── echoServer ├── Makefile ├── common.h ├── echoClient.c └── echoServer.c ├── 02-echo ├── echoClient ├── echoServer ├── .Makefile.swo ├── .Makefile.swp ├── .echoClient.c.swo ├── .echoClient.c.swp ├── .echoServer.c.swo ├── .echoServer.c.swp ├── Makefile ├── common.h ├── echoClient.c └── echoServer.c ├── 04-packetSplic ├── p2pClient ├── p2pServer ├── selectP2pCli ├── selectP2pSer ├── .p2pClient.c.swp ├── Makefile ├── p2pClient.c ├── selectP2pCli.c ├── p2pServer.c ├── common.h └── selectP2pSer.c ├── Makefile └── common.h /.client.c.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huanzheWu/Socket-Programming/HEAD/.client.c.swp -------------------------------------------------------------------------------- /.server.c.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huanzheWu/Socket-Programming/HEAD/.server.c.swp -------------------------------------------------------------------------------- /03-p2p/p2pClient: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huanzheWu/Socket-Programming/HEAD/03-p2p/p2pClient -------------------------------------------------------------------------------- /03-p2p/p2pServer: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huanzheWu/Socket-Programming/HEAD/03-p2p/p2pServer -------------------------------------------------------------------------------- /01-echo/echoClient: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huanzheWu/Socket-Programming/HEAD/01-echo/echoClient -------------------------------------------------------------------------------- /01-echo/echoServer: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huanzheWu/Socket-Programming/HEAD/01-echo/echoServer -------------------------------------------------------------------------------- /02-echo/echoClient: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huanzheWu/Socket-Programming/HEAD/02-echo/echoClient -------------------------------------------------------------------------------- /02-echo/echoServer: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huanzheWu/Socket-Programming/HEAD/02-echo/echoServer -------------------------------------------------------------------------------- /02-echo/.Makefile.swo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huanzheWu/Socket-Programming/HEAD/02-echo/.Makefile.swo -------------------------------------------------------------------------------- /02-echo/.Makefile.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huanzheWu/Socket-Programming/HEAD/02-echo/.Makefile.swp -------------------------------------------------------------------------------- /03-p2p/.Makefile.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huanzheWu/Socket-Programming/HEAD/03-p2p/.Makefile.swp -------------------------------------------------------------------------------- /03-p2p/.p2pClient.c.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huanzheWu/Socket-Programming/HEAD/03-p2p/.p2pClient.c.swp -------------------------------------------------------------------------------- /03-p2p/.p2pServer.c.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huanzheWu/Socket-Programming/HEAD/03-p2p/.p2pServer.c.swp -------------------------------------------------------------------------------- /04-packetSplic/p2pClient: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huanzheWu/Socket-Programming/HEAD/04-packetSplic/p2pClient -------------------------------------------------------------------------------- /04-packetSplic/p2pServer: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huanzheWu/Socket-Programming/HEAD/04-packetSplic/p2pServer -------------------------------------------------------------------------------- /02-echo/.echoClient.c.swo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huanzheWu/Socket-Programming/HEAD/02-echo/.echoClient.c.swo -------------------------------------------------------------------------------- /02-echo/.echoClient.c.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huanzheWu/Socket-Programming/HEAD/02-echo/.echoClient.c.swp -------------------------------------------------------------------------------- /02-echo/.echoServer.c.swo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huanzheWu/Socket-Programming/HEAD/02-echo/.echoServer.c.swo -------------------------------------------------------------------------------- /02-echo/.echoServer.c.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huanzheWu/Socket-Programming/HEAD/02-echo/.echoServer.c.swp -------------------------------------------------------------------------------- /04-packetSplic/selectP2pCli: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huanzheWu/Socket-Programming/HEAD/04-packetSplic/selectP2pCli -------------------------------------------------------------------------------- /04-packetSplic/selectP2pSer: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huanzheWu/Socket-Programming/HEAD/04-packetSplic/selectP2pSer -------------------------------------------------------------------------------- /04-packetSplic/.p2pClient.c.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huanzheWu/Socket-Programming/HEAD/04-packetSplic/.p2pClient.c.swp -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY:clean all 2 | BIN = echoServer echoClient 3 | OBJECTS = server.o 4 | CC = gcc 5 | GFLAGS = -Wall -g 6 | all : $(BIN) 7 | .o .c: 8 | $(CC) $(CFLAGS) $< -o $@ 9 | clean : 10 | rm -f *.o $(BIN) 11 | 12 | -------------------------------------------------------------------------------- /03-p2p/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY:clean all 2 | BIN = p2pServer p2pClient 3 | OBJECTS = server.o 4 | CC = gcc 5 | GFLAGS = -Wall -g 6 | all : $(BIN) 7 | .o .c: 8 | $(CC) $(CFLAGS) $< -o $@ 9 | clean : 10 | rm -f *.o $(BIN) 11 | 12 | -------------------------------------------------------------------------------- /01-echo/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY:clean all 2 | BIN = echoServer echoClient 3 | OBJECTS = server.o 4 | CC = gcc 5 | GFLAGS = -Wall -g 6 | all : $(BIN) 7 | .o .c: 8 | $(CC) $(CFLAGS) $< -o $@ 9 | clean : 10 | rm -f *.o $(BIN) 11 | 12 | -------------------------------------------------------------------------------- /02-echo/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY:clean all 2 | BIN = echoServer echoClient 3 | OBJECTS = server.o 4 | CC = gcc 5 | GFLAGS = -Wall -g 6 | all : $(BIN) 7 | .o .c: 8 | $(CC) $(CFLAGS) $< -o $@ 9 | clean : 10 | rm -f *.o $(BIN) 11 | 12 | -------------------------------------------------------------------------------- /common.h: -------------------------------------------------------------------------------- 1 | #ifndef __COMMON__ 2 | #define __COMMON__ 3 | #include 4 | #include 5 | 6 | # define err_exit(m)\ 7 | do\ 8 | {\ 9 | perror(m);\ 10 | exit(EXIT_FAILURE);\ 11 | }while(0) 12 | 13 | #endif //__COMMON__ 14 | 15 | -------------------------------------------------------------------------------- /03-p2p/common.h: -------------------------------------------------------------------------------- 1 | #ifndef __COMMON__ 2 | #define __COMMON__ 3 | #include 4 | #include 5 | 6 | # define err_exit(m)\ 7 | do\ 8 | {\ 9 | perror(m);\ 10 | exit(EXIT_FAILURE);\ 11 | }while(0) 12 | 13 | #endif //__COMMON__ 14 | 15 | -------------------------------------------------------------------------------- /01-echo/common.h: -------------------------------------------------------------------------------- 1 | #ifndef __COMMON__ 2 | #define __COMMON__ 3 | #include 4 | #include 5 | 6 | # define err_exit(m)\ 7 | do\ 8 | {\ 9 | perror(m);\ 10 | exit(EXIT_FAILURE);\ 11 | }while(0) 12 | 13 | #endif //__COMMON__ 14 | 15 | -------------------------------------------------------------------------------- /02-echo/common.h: -------------------------------------------------------------------------------- 1 | #ifndef __COMMON__ 2 | #define __COMMON__ 3 | #include 4 | #include 5 | 6 | # define err_exit(m)\ 7 | do\ 8 | {\ 9 | perror(m);\ 10 | exit(EXIT_FAILURE);\ 11 | }while(0) 12 | 13 | #endif //__COMMON__ 14 | 15 | -------------------------------------------------------------------------------- /04-packetSplic/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY:clean all 2 | BIN = p2pServer p2pClient selectP2pCli selectP2pSer 3 | OBJECTS = server.o 4 | CC = gcc 5 | GFLAGS = -Wall -g 6 | all : $(BIN) 7 | .o .c: 8 | $(CC) $(CFLAGS) $< -o $@ 9 | clean : 10 | rm -f *.o $(BIN) 11 | 12 | -------------------------------------------------------------------------------- /01-echo/echoClient.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include"common.h" 10 | int main() 11 | { 12 | int sock ; 13 | sock = socket(PF_INET,SOCK_STREAM,0); 14 | if(sock <0) 15 | { 16 | err_exit("socket"); 17 | } 18 | 19 | struct sockaddr_in addr; 20 | memset(&addr,0,sizeof(addr)); 21 | addr.sin_family = AF_INET; 22 | addr.sin_port = htons(5888); 23 | addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 24 | 25 | int ret ; 26 | ret = connect (sock , (struct sockaddr*)&addr,sizeof(addr)); 27 | if(ret < 0) 28 | { 29 | err_exit("connect"); 30 | } 31 | 32 | char buf[512]; 33 | while(fgets(buf,sizeof(buf),stdin)!=NULL) 34 | { 35 | write(sock , buf , sizeof(buf)); 36 | memset(buf,0,sizeof(buf)); 37 | int readBytes = read(sock , buf , sizeof(buf)); 38 | if(readBytes>0) 39 | { 40 | printf("echo:"); 41 | fputs(buf,stdout); 42 | } 43 | memset(buf,0,sizeof(buf)); 44 | } 45 | close(sock); 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /02-echo/echoClient.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include"common.h" 10 | int main() 11 | { 12 | int sock ; 13 | sock = socket(PF_INET,SOCK_STREAM,0); 14 | if(sock <0) 15 | { 16 | err_exit("socket"); 17 | } 18 | 19 | struct sockaddr_in addr; 20 | memset(&addr,0,sizeof(addr)); 21 | addr.sin_family = AF_INET; 22 | addr.sin_port = htons(5888); 23 | addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 24 | 25 | int ret ; 26 | ret = connect (sock , (struct sockaddr*)&addr,sizeof(addr)); 27 | if(ret < 0) 28 | { 29 | err_exit("connect"); 30 | } 31 | 32 | char buf[512]; 33 | while(fgets(buf,sizeof(buf),stdin)!=NULL) 34 | { 35 | write(sock , buf , sizeof(buf)); 36 | memset(buf,0,sizeof(buf)); 37 | int readBytes = read(sock , buf , sizeof(buf)); 38 | if(readBytes>0) 39 | { 40 | printf("echo:"); 41 | fputs(buf,stdout); 42 | } 43 | memset(buf,0,sizeof(buf)); 44 | } 45 | close(sock); 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /01-echo/echoServer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include"common.h" 11 | 12 | int main() 13 | { 14 | int listenfd; 15 | listenfd = socket(PF_INET , SOCK_STREAM, 0); 16 | if(listenfd <0) 17 | { 18 | err_exit("socket"); 19 | } 20 | 21 | struct sockaddr_in addr; 22 | addr.sin_family = PF_INET; 23 | addr.sin_port = htons(5888); 24 | addr.sin_addr.s_addr = htonl(INADDR_ANY); 25 | 26 | //设置地址可重复利用 27 | int on = 1; 28 | setsockopt(listenfd, SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)); 29 | 30 | int ret = bind(listenfd , (const struct sockaddr *)&addr,sizeof(addr)); 31 | if(ret == -1) 32 | { 33 | err_exit("bind"); 34 | } 35 | 36 | ret = listen(listenfd , SOMAXCONN); 37 | if(ret < 0) 38 | { 39 | err_exit("listen"); 40 | } 41 | 42 | struct sockaddr_in peerAddr ; 43 | socklen_t peerlen = sizeof(peerAddr);//peerlen一定要有初始值 44 | 45 | int conn; 46 | conn = accept (listenfd ,(struct sockaddr *)&peerAddr,&peerlen); 47 | if(conn <0) 48 | { 49 | err_exit("accept"); 50 | } 51 | 52 | printf("客户端的IP地址是:%s,端口号是:%d\n", 53 | inet_ntoa(peerAddr.sin_addr),ntohs(peerAddr.sin_port)); 54 | 55 | //定义一个应用层的缓冲区,用于接收数据 56 | char buf[512]; 57 | while(1) 58 | { 59 | memset(buf,0,sizeof(buf)); 60 | int readByes = read(conn , buf , sizeof(buf)); 61 | fputs(buf,stdout); 62 | write ( conn , buf, sizeof(buf)); 63 | } 64 | close(listenfd); 65 | close(conn); 66 | return 0; 67 | } 68 | 69 | -------------------------------------------------------------------------------- /03-p2p/p2pClient.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include"common.h" 10 | int main() 11 | { 12 | int sock ; 13 | sock = socket(PF_INET,SOCK_STREAM,0); 14 | if(sock <0) 15 | { 16 | err_exit("socket"); 17 | } 18 | 19 | struct sockaddr_in addr; 20 | memset(&addr,0,sizeof(addr)); 21 | addr.sin_family = AF_INET; 22 | addr.sin_port = htons(5888); 23 | addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 24 | 25 | int ret ; 26 | ret = connect (sock , (struct sockaddr*)&addr,sizeof(addr)); 27 | if(ret < 0) 28 | { 29 | err_exit("connect"); 30 | } 31 | 32 | char readBuf[512]; 33 | char writeBuf[512]; 34 | pid_t pid ; 35 | pid = fork(); 36 | if(pid == 0)//子进程复制读取 37 | { 38 | 39 | while(1) 40 | { 41 | 42 | memset(writeBuf,0,sizeof(writeBuf)); 43 | fgets(writeBuf,sizeof(writeBuf),stdin); 44 | write(sock,writeBuf,sizeof(writeBuf)); 45 | } 46 | } 47 | else if( pid >0)//父进程 48 | { 49 | while(1) 50 | { 51 | 52 | memset(readBuf,0,sizeof(readBuf)); 53 | int readBytes = read(sock,readBuf,sizeof(readBuf)); 54 | if(readBytes == 0) 55 | { 56 | printf("client close\n"); 57 | break; 58 | } 59 | if(readBytes<0) 60 | { 61 | err_exit("read"); 62 | } 63 | fputs(readBuf,stdout); 64 | } 65 | exit(EXIT_SUCCESS); 66 | } 67 | 68 | close(sock); 69 | return 0; 70 | } 71 | -------------------------------------------------------------------------------- /02-echo/echoServer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include"common.h" 10 | 11 | /* 12 | 服务器端多线程,可以接受多个客户端的连接 13 | */ 14 | 15 | int main() 16 | { 17 | int listenfd; 18 | listenfd = socket(PF_INET , SOCK_STREAM, 0); 19 | if(listenfd <0) 20 | { 21 | err_exit("socket"); 22 | } 23 | 24 | struct sockaddr_in addr; 25 | addr.sin_family = PF_INET; 26 | addr.sin_port = htons(5888); 27 | addr.sin_addr.s_addr = htonl(INADDR_ANY); 28 | 29 | //设置地址可重复利用 30 | int on = 1; 31 | setsockopt(listenfd, SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)); 32 | 33 | int ret = bind(listenfd , (const struct sockaddr *)&addr,sizeof(addr)); 34 | if(ret == -1) 35 | { 36 | err_exit("bind"); 37 | } 38 | 39 | ret = listen(listenfd , SOMAXCONN); 40 | if(ret < 0) 41 | { 42 | err_exit("listen"); 43 | } 44 | 45 | struct sockaddr_in peerAddr ; 46 | socklen_t peerlen = sizeof(peerAddr);//peerlen一定要有初始值 47 | 48 | int conn; 49 | while(1) 50 | { 51 | conn = accept (listenfd ,(struct sockaddr *)&peerAddr,&peerlen); 52 | if(conn <0) 53 | { 54 | err_exit("accept"); 55 | } 56 | 57 | pid_t pid ; 58 | pid = fork(); 59 | if(pid == 0) //子进程负责进行与客户端交互 60 | { 61 | close(listenfd); //子进程不需要监听套接字 62 | printf("客户端的IP地址是:%s,端口号是:%d\n", 63 | inet_ntoa(peerAddr.sin_addr),ntohs(peerAddr.sin_port)); 64 | 65 | //定义一个应用层的缓冲区,用于接收数据 66 | char buf[512]; 67 | while(1) 68 | { 69 | memset(buf,0,sizeof(buf)); 70 | int readBytes = read(conn , buf , sizeof(buf)); 71 | if(readBytes==0) //说明客户端已经关闭 72 | { 73 | printf("clinent close\n"); 74 | break; 75 | } 76 | fputs(buf,stdout); 77 | write ( conn , buf, sizeof(buf)); 78 | } 79 | //能够执行到这里说明客户端已经关闭 80 | exit(EXIT_SUCCESS);//退出进程 81 | } 82 | close(conn); 83 | } 84 | 85 | return 0; 86 | } 87 | -------------------------------------------------------------------------------- /03-p2p/p2pServer.c: -------------------------------------------------------------------------------- 1 | /* 2 | 单进程服务器 3 | 实现简单点到点的聊天功能 4 | */ 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include"common.h" 14 | 15 | int main() 16 | { 17 | int listenfd; 18 | listenfd = socket(PF_INET , SOCK_STREAM, 0); 19 | if(listenfd <0) 20 | { 21 | err_exit("socket"); 22 | } 23 | 24 | struct sockaddr_in addr; 25 | addr.sin_family = PF_INET; 26 | addr.sin_port = htons(5888); 27 | addr.sin_addr.s_addr = htonl(INADDR_ANY); 28 | 29 | //设置地址可重复利用 30 | int on = 1; 31 | setsockopt(listenfd, SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)); 32 | 33 | int ret = bind(listenfd , (const struct sockaddr *)&addr,sizeof(addr)); 34 | if(ret == -1) 35 | { 36 | err_exit("bind"); 37 | } 38 | 39 | ret = listen(listenfd , SOMAXCONN); 40 | if(ret < 0) 41 | { 42 | err_exit("listen"); 43 | } 44 | 45 | struct sockaddr_in peerAddr ; 46 | socklen_t peerlen = sizeof(peerAddr);//peerlen一定要有初始值 47 | 48 | int conn; 49 | conn = accept (listenfd ,(struct sockaddr *)&peerAddr,&peerlen); 50 | if(conn <0) 51 | { 52 | err_exit("accept"); 53 | } 54 | 55 | printf("客户端的IP地址是:%s,端口号是:%d\n", 56 | inet_ntoa(peerAddr.sin_addr),ntohs(peerAddr.sin_port)); 57 | 58 | pid_t pid ; 59 | pid = fork(); 60 | //需要两个进程,一个负责读取键盘输入 61 | //另一个进程负责读取 62 | 63 | char writebuf[512]; 64 | char readbuf[512]; 65 | if(pid == 0) //子进程复制从键盘读取 66 | { 67 | while(1) 68 | { 69 | 70 | memset(writebuf,0,sizeof(writebuf)); 71 | fgets(writebuf,sizeof(writebuf),stdin); 72 | write(conn,writebuf,sizeof(writebuf)); 73 | } 74 | } 75 | else if(pid>0) //父进程负责接收 76 | { 77 | while(1) 78 | { 79 | 80 | memset(readbuf,0,sizeof(readbuf)); 81 | int readBytes = read(conn,readbuf,sizeof(readbuf)); 82 | if(readBytes == 0) 83 | { 84 | printf("client close\n"); 85 | break; 86 | } 87 | if(readBytes<0) 88 | { 89 | err_exit("read"); 90 | } 91 | fputs(readbuf,stdout); 92 | } 93 | close(conn); 94 | exit(EXIT_SUCCESS); 95 | } 96 | //定义一个应用层的缓冲区,用于接收数据 97 | close(listenfd); 98 | close(conn); 99 | return 0; 100 | } 101 | 102 | -------------------------------------------------------------------------------- /04-packetSplic/p2pClient.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include"common.h" 11 | int main() 12 | { 13 | int sock ; 14 | sock = socket(PF_INET,SOCK_STREAM,0); 15 | if(sock <0) 16 | { 17 | err_exit("socket"); 18 | } 19 | 20 | struct sockaddr_in addr; 21 | memset(&addr,0,sizeof(addr)); 22 | addr.sin_family = AF_INET; 23 | addr.sin_port = htons(5888); 24 | addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 25 | 26 | int ret ; 27 | ret = connect (sock , (struct sockaddr*)&addr,sizeof(addr)); 28 | if(ret < 0) 29 | { 30 | err_exit("connect"); 31 | } 32 | 33 | //char readBuf[512]; 34 | //char writeBuf[512]; 35 | pid_t pid ; 36 | pid = fork(); 37 | if(pid == 0)//子进程从键盘输入 38 | { 39 | struct packet writeBuf; 40 | 41 | 42 | while(fgets(writeBuf.data,sizeof(writeBuf.data),stdin)!=NULL) 43 | { 44 | int n = strlen(writeBuf.data); 45 | writeBuf . msgLen =htonl(n); 46 | 47 | writen(sock,&writeBuf,4+n); 48 | memset(&writeBuf,0,sizeof(writeBuf)); 49 | } 50 | //子进程结束输入,此时应该通知父进程也结束,使用信号 51 | kill(getppid(),SIGUSR1); 52 | exit(EXIT_SUCCESS); 53 | } 54 | else if( pid >0)//父进程 55 | { 56 | signal (SIGUSR1,handler); //信号,收到SIGUSR1信号后调用handler处理函数 57 | while(1) 58 | { 59 | struct packet readBuf; 60 | 61 | memset(&readBuf,0,sizeof(readBuf)); 62 | int ret = readn(sock,&readBuf.msgLen ,4); //先读取前4个字节 ,获得data长度 63 | if(ret == -1) 64 | { 65 | err_exit("readn"); 66 | } 67 | else if(ret == 0) 68 | { 69 | printf("peer close\n"); 70 | break; 71 | } 72 | 73 | int dataBytes = ntohl(readBuf.msgLen); //注意字节序的转换 74 | int readBytes = readn(sock,readBuf.data,dataBytes); //读取data 75 | 76 | if(readBytes == 0)//对方关闭,则应该退出该进程 77 | { 78 | printf("peer close\n"); 79 | break; 80 | } 81 | if(readBytes<0) 82 | { 83 | err_exit("read"); 84 | } 85 | fputs(readBuf.data,stdout); 86 | } 87 | } 88 | close(sock); 89 | return 0; 90 | } 91 | -------------------------------------------------------------------------------- /04-packetSplic/selectP2pCli.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include"common.h" 11 | int main() 12 | { 13 | int sock ; 14 | sock = socket(PF_INET,SOCK_STREAM,0); 15 | if(sock <0) 16 | { 17 | err_exit("socket"); 18 | } 19 | 20 | struct sockaddr_in addr; 21 | memset(&addr,0,sizeof(addr)); 22 | addr.sin_family = AF_INET; 23 | addr.sin_port = htons(5888); 24 | addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 25 | 26 | int ret ; 27 | ret = connect (sock , (struct sockaddr*)&addr,sizeof(addr)); 28 | if(ret < 0) 29 | { 30 | err_exit("connect"); 31 | } 32 | 33 | //char readBuf[512]; 34 | //char writeBuf[512]; 35 | pid_t pid ; 36 | pid = fork(); 37 | if(pid == 0)//子进程从键盘输入 38 | { 39 | struct packet writeBuf; 40 | 41 | 42 | while(fgets(writeBuf.data,sizeof(writeBuf.data),stdin)!=NULL) 43 | { 44 | int n = strlen(writeBuf.data); 45 | writeBuf . msgLen =htonl(n); 46 | 47 | writen(sock,&writeBuf,4+n); 48 | memset(&writeBuf,0,sizeof(writeBuf)); 49 | } 50 | //子进程结束输入,此时应该通知父进程也结束,使用信号 51 | kill(getppid(),SIGUSR1); 52 | exit(EXIT_SUCCESS); 53 | } 54 | else if( pid >0)//父进程 55 | { 56 | signal (SIGUSR1,handler); //信号,收到SIGUSR1信号后调用handler处理函数 57 | while(1) 58 | { 59 | struct packet readBuf; 60 | 61 | memset(&readBuf,0,sizeof(readBuf)); 62 | int ret = readn(sock,&readBuf.msgLen ,4); //先读取前4个字节 ,获得data长度 63 | if(ret == -1) 64 | { 65 | err_exit("readn"); 66 | } 67 | else if(ret == 0) 68 | { 69 | printf("peer close\n"); 70 | break; 71 | } 72 | 73 | int dataBytes = ntohl(readBuf.msgLen); //注意字节序的转换 74 | int readBytes = readn(sock,readBuf.data,dataBytes); //读取data 75 | 76 | if(readBytes == 0)//对方关闭,则应该退出该进程 77 | { 78 | printf("peer close\n"); 79 | break; 80 | } 81 | if(readBytes<0) 82 | { 83 | err_exit("read"); 84 | } 85 | fputs(readBuf.data,stdout); 86 | } 87 | } 88 | close(sock); 89 | return 0; 90 | } 91 | -------------------------------------------------------------------------------- /04-packetSplic/p2pServer.c: -------------------------------------------------------------------------------- 1 | /* 2 | 单进程服务器 3 | 实现简单点到点的聊天功能 4 | */ 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include"common.h" 15 | 16 | int main() 17 | { 18 | int listenfd; 19 | listenfd = socket(PF_INET , SOCK_STREAM, 0); 20 | if(listenfd <0) 21 | { 22 | err_exit("socket"); 23 | } 24 | 25 | struct sockaddr_in addr; 26 | addr.sin_family = PF_INET; 27 | addr.sin_port = htons(5888); 28 | addr.sin_addr.s_addr = htonl(INADDR_ANY); 29 | 30 | //设置地址可重复利用 31 | int on = 1; 32 | setsockopt(listenfd, SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)); 33 | 34 | int ret = bind(listenfd , (const struct sockaddr *)&addr,sizeof(addr)); 35 | if(ret == -1) 36 | { 37 | err_exit("bind"); 38 | } 39 | 40 | ret = listen(listenfd , SOMAXCONN); 41 | if(ret < 0) 42 | { 43 | err_exit("listen"); 44 | } 45 | 46 | struct sockaddr_in peerAddr ; 47 | socklen_t peerlen = sizeof(peerAddr);//peerlen一定要有初始值 48 | 49 | int conn; 50 | conn = accept (listenfd ,(struct sockaddr *)&peerAddr,&peerlen); 51 | if(conn <0) 52 | { 53 | err_exit("accept"); 54 | } 55 | 56 | printf("客户端的IP地址是:%s,端口号是:%d\n", 57 | inet_ntoa(peerAddr.sin_addr),ntohs(peerAddr.sin_port)); 58 | 59 | pid_t pid ; 60 | pid = fork(); 61 | //需要两个进程,一个负责读取键盘输入 62 | //另一个进程负责读取 63 | 64 | if(pid == 0) //子进程复制从键盘读取 65 | { 66 | signal(SIGUSR1,handler); 67 | struct packet writebuf; 68 | memset(&writebuf,0,sizeof(writebuf)); 69 | while(fgets(writebuf.data,sizeof(writebuf.data),stdin)!=NULL) 70 | { 71 | int n = strlen(writebuf.data); 72 | writebuf.msgLen =htonl(n); 73 | writen(conn,&writebuf,4+n);//发送 74 | memset(&writebuf,0,sizeof(writebuf)); 75 | } 76 | } 77 | else if(pid>0) //父进程负责接收 78 | { 79 | struct packet readbuf ; 80 | 81 | while(1) 82 | { 83 | 84 | memset(&readbuf,0,sizeof(readbuf)); 85 | int ret = readn(conn,&readbuf.msgLen,4); //先读取四个字节,确定后续数据的长度 86 | if(ret == -1) 87 | { 88 | err_exit("readn"); 89 | } 90 | else if(ret == 0) 91 | { 92 | printf("peer1 close\n"); 93 | break; 94 | } 95 | 96 | int dataBytes = ntohl(readbuf.msgLen); //字节序的转换 97 | int readBytes = readn(conn,readbuf.data,dataBytes); //读取出后续的数据 98 | 99 | if(readBytes == 0) 100 | { 101 | printf("peer2 close\n"); 102 | break; 103 | } 104 | if(readBytes<0) 105 | { 106 | err_exit("read"); 107 | } 108 | fputs(readbuf.data,stdout); 109 | } 110 | kill(pid,SIGUSR1); 111 | close(conn); 112 | close(listenfd); 113 | exit(EXIT_SUCCESS); 114 | } 115 | //定义一个应用层的缓冲区,用于接收数据 116 | close(listenfd); 117 | close(conn); 118 | return 0; 119 | } 120 | 121 | -------------------------------------------------------------------------------- /04-packetSplic/common.h: -------------------------------------------------------------------------------- 1 | #ifndef __COMMON__ 2 | #define __COMMON__ 3 | #include 4 | #include 5 | #include 6 | # define err_exit(m)\ 7 | do\ 8 | {\ 9 | perror(m);\ 10 | exit(EXIT_FAILURE);\ 11 | }while(0) 12 | 13 | void handler(int sig) 14 | { 15 | printf("recv a sig = %d \n",sig); 16 | exit(EXIT_SUCCESS); 17 | } 18 | 19 | 20 | struct packet 21 | { 22 | unsigned int msgLen ; 23 | char data [1024]; 24 | }; 25 | /* 26 | readn 函数 27 | 读取count字节数据 28 | */ 29 | ssize_t readn(int fd,void *buf, size_t count) 30 | { 31 | int left = count ; //剩下的字节 32 | char * ptr = (char*)buf ; 33 | while(left>0) 34 | { 35 | int readBytes = read(fd,ptr,left); 36 | if(readBytes< 0)//read函数小于0有两种情况:1中断 2出错 37 | { 38 | if(errno == EINTR)//读被中断 39 | { 40 | continue; 41 | } 42 | return -1; 43 | } 44 | if(readBytes == 0)//读到了EOF 45 | { 46 | return count - left; 47 | } 48 | left -= readBytes; 49 | ptr += readBytes ; 50 | } 51 | return count ; 52 | } 53 | 54 | /* 55 | writen 函数 56 | 写入count字节的数据 57 | */ 58 | ssize_t writen(int fd, void *buf, size_t count) 59 | { 60 | int left = count ; 61 | char * ptr = (char *)buf; 62 | while(left >0) 63 | { 64 | int writeBytes = write(fd,ptr,left); 65 | if(writeBytes<0) 66 | { 67 | if(errno == EINTR) 68 | continue; 69 | return -1; 70 | } 71 | else if(writeBytes == 0) 72 | continue; 73 | left -= writeBytes; 74 | ptr += writeBytes; 75 | } 76 | return count; 77 | } 78 | 79 | /* 80 | 从缓冲区中读取指定长度的数据,但不清楚缓冲区内容 81 | */ 82 | ssize_t read_peek(int sockfd, void *buf, size_t len ) 83 | { 84 | while(1) 85 | { 86 | int ret = recv (sockfd , buf ,len ,MSG_PEEK); 87 | if(ret == -1) 88 | { 89 | if(errno ==EINTR) //出现中断 90 | continue ; 91 | } 92 | return ret ; 93 | } 94 | } 95 | 96 | /* 97 | 按行读取数据 98 | 参数说明: 99 | sockfd:套接字 100 | buf :应用层缓冲区,保存读取到的数据 101 | maxline:所规定的一行的长度 102 | 返回值说明: 103 | */ 104 | ssize_t readLine (int sockfd , void *buf ,size_t maxline) 105 | { 106 | int ret; 107 | int nRead = 0; 108 | int left = maxline ; //剩下的字节数 109 | char * pbuf = (char *) buf ; 110 | int count = 0; 111 | while(1) 112 | { 113 | ret = read_peek ( sockfd, pbuf, left); //读取长度为left的socket缓冲区内容 114 | if(ret <0) 115 | { 116 | return ret; 117 | } 118 | nRead = ret; 119 | for(int i = 0;i 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include"common.h" 20 | 21 | int main() 22 | { 23 | int listenfd; 24 | listenfd = socket(PF_INET , SOCK_STREAM, 0); 25 | if(listenfd <0) 26 | { 27 | err_exit("socket"); 28 | } 29 | 30 | struct sockaddr_in addr; 31 | addr.sin_family = PF_INET; 32 | addr.sin_port = htons(5888); 33 | addr.sin_addr.s_addr = htonl(INADDR_ANY); 34 | 35 | //设置地址可重复利用 36 | int on = 1; 37 | setsockopt(listenfd, SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)); 38 | 39 | int ret = bind(listenfd , (const struct sockaddr *)&addr,sizeof(addr)); 40 | if(ret == -1) 41 | { 42 | err_exit("bind"); 43 | } 44 | 45 | ret = listen(listenfd , SOMAXCONN); 46 | if(ret < 0) 47 | { 48 | err_exit("listen"); 49 | } 50 | 51 | struct sockaddr_in peerAddr ; 52 | socklen_t peerlen = sizeof(peerAddr);//peerlen一定要有初始值 53 | 54 | int conn; 55 | conn = accept (listenfd ,(struct sockaddr *)&peerAddr,&peerlen); 56 | if(conn <0) 57 | { 58 | err_exit("accept"); 59 | } 60 | 61 | printf("客户端的IP地址是:%s,端口号是:%d\n", 62 | inet_ntoa(peerAddr.sin_addr),ntohs(peerAddr.sin_port)); 63 | 64 | 65 | fd_set fds ; 66 | FD_ZERO(&fds); 67 | int maxfds ; 68 | if(STDIN_FILENO >conn) 69 | maxfds = STDIN_FILENO; 70 | else 71 | maxfds = conn; 72 | 73 | while(1) 74 | { 75 | FD_SET(STDIN_FILENO,&fds); 76 | FD_SET(conn,&fds); 77 | int nready = select(maxfds+1,&fds, NULL,NULL,NULL); 78 | if(nready == -1) 79 | err_exit("select"); 80 | else if(nready == 0) 81 | continue; 82 | 83 | if(FD_ISSET(STDIN_FILENO,&fds))//键盘有数据可读 84 | { 85 | 86 | struct packet writebuf; 87 | memset(&writebuf,0,sizeof(writebuf)); 88 | fgets(writebuf.data,sizeof(writebuf.data),stdin); 89 | int n = strlen(writebuf.data); 90 | writebuf.msgLen =htonl(n); 91 | writen(conn,&writebuf,4+n);//发送 92 | memset(&writebuf,0,sizeof(writebuf)); 93 | 94 | } 95 | if(FD_ISSET(conn,&fds)) //有数据读 96 | { 97 | struct packet readbuf ; 98 | memset(&readbuf,0,sizeof(readbuf)); 99 | int ret = readn(conn,&readbuf.msgLen,4); //先读取四个字节,确定后续数据的长度 100 | if(ret == -1) 101 | { 102 | err_exit("readn"); 103 | } 104 | else if(ret == 0) 105 | { 106 | printf("peer1 close\n"); 107 | break; 108 | } 109 | 110 | int dataBytes = ntohl(readbuf.msgLen); //字节序的转换 111 | int readBytes = readn(conn,readbuf.data,dataBytes); //读取出后续的数据 112 | if(readBytes<0) 113 | { 114 | err_exit("read"); 115 | } 116 | fputs(readbuf.data,stdout); 117 | } 118 | 119 | } 120 | close(listenfd); 121 | close(conn); 122 | return 0; 123 | } 124 | 125 | --------------------------------------------------------------------------------