TCP编程之一
一、基本模型(多进程\多线程)
apue.h /usr/include
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <unistd.h> 4 #include <errno.h> 5 #include <sys/wait.h> 6 #include <sys/ioctl.h> 7 #include <sys/types.h> 8 #include <fcntl.h> 9 #include <pthread.h> 10 #include<netinet/in.h> 11 #include <arpa/inet.h> 12 #include <signal.h> 13 #include <sys/socket.h> 14 #include <string.h> 15 16 #define ERR(msg) do{ \ 17 fprintf(stderr,"[%s:%d] %s:%s\n",__FILE__,__LINE__,msg,strerror(errno));\ 18 exit(-1); \ 19 }while(0) 20 21 #define STREQ(s1,s2) (strcmp(s1,s2)==0) 22 #define MAXER(n1,n2) ((n1)>(n2)?(n1):(n2)) 23 #define MINOR(n1,n2) ((n1)<(n2)?(n1):(n2)) 24 #define CLEAR(n) (memset(&n,0,sizeof(n)))
echoserver.c
1 #include <apue.h> 2 3 #define PORT 8080 4 #define IP "192.168.5.99" 5 #define BACKLOG 10 6 7 void *routine(void *arg); 8 void do_business(); 9 10 int main(int argc, char **argv) 11 { 12 int sockfd; 13 //1.创建socket 14 if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) < 0) 15 ERR("Socket failed"); 16 17 int val = 1; 18 if(setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&val,sizeof(val))<0) 19 ERR("set reuseaddr failed"); 20 #ifdef SO_REUSEPORT 21 if(setsockopt(sockfd,SOL_SOCKET,SO_REUSEPORT,&val,sizeof(val))<0) 22 ERR("set reuseaddr failed"); 23 #endif 24 25 #if 0 26 struct sockaddr_in { 27 sa_family_t sin_family; 28 in_port_t sin_port; 29 struct in_addr sin_addr; 30 unsigned char sin_zero[8]; 31 }; 32 #endif 33 //2.给socket绑定地址 34 struct sockaddr_in ipv4, peer; 35 ipv4.sin_family = AF_INET; 36 ipv4.sin_port = htons(PORT); //NBO 37 inet_pton(AF_INET, IP, &ipv4.sin_addr); //NBO 38 memset(ipv4.sin_zero, 0, sizeof(ipv4.sin_zero)); 39 if (bind(sockfd, (struct sockaddr *) &ipv4, sizeof(ipv4)) < 0) 40 ERR("bind failed"); 41 42 //3.监听 43 if (listen(sockfd, BACKLOG) < 0) 44 ERR("listen failed"); 45 46 //4.接收连接 47 socklen_t len = sizeof(peer); //value-result argument 48 int connfd; 49 for (;;) { 50 if ((connfd = accept(sockfd, (struct sockaddr *) &peer, &len)) < 0) 51 ERR("accept failed"); 52 53 unsigned short peerport = ntohs(peer.sin_port); 54 char ipstr[] = "ddd.ddd.ddd.ddd"; 55 inet_ntop(AF_INET, &peer.sin_addr, ipstr, sizeof(ipstr)); 56 57 //5.通信 58 char banner[255]; 59 sprintf(banner, "[%s:%d] welcome to echoserver!", ipstr, 60 peerport); 61 printf("Accept a new Connection: %s,%d\n",ipstr,peerport); 62 if(write(connfd, banner, strlen(banner)) < strlen(banner)) 63 ERR("write failed"); 64 65 #ifdef MODEL_THREAD 66 pthread_t tid; 67 if(pthread_create(&tid,NULL,routine,(void*)connfd)) 68 ERR("create thread failed"); 69 #elif MODEL_FORK 70 pid_t pid; 71 if((pid = fork())<0) 72 ERR("fork failed"); 73 else if(pid==0) 74 { 75 close(sockfd); //1.关闭无用描述符 76 do_business(connfd); 77 exit(0); //2.显式指定退出 78 } 79 close(connfd); 80 #endif 81 } 82 //7.关闭服务器 83 close(sockfd); 84 return 0; 85 } 86 87 void do_business() 88 { 89 sleep(20); 90 } 91 92 void *routine(void *arg) 93 { 94 int connfd = (int)arg; 95 char buf[255]; 96 int n; 97 while(1) 98 { 99 if((n = read(connfd,buf,sizeof(buf)))<0) 100 ERR("read failed"); 101 else if(n==0) 102 { 103 printf("Connection is closed by peer!\n"); 104 goto end; 105 } 106 if(write(connfd,buf,n)<0) 107 ERR("write failed"); 108 } 109 end: 110 close(connfd); 111 return NULL; 112 }
echoclient.c
1 #include <apue.h> 2 3 void do_business(int sockfd); 4 5 int main(int argc,char **argv) 6 { 7 //1.判断命令行 8 if(argc!=3) 9 { 10 printf("Usage: %s <host> <port>\n",argv[0]); 11 exit(0); 12 } 13 char *ipstr = argv[1]; 14 unsigned short port = strtol(argv[2],NULL,10); 15 16 //2.socket 17 int sockfd; 18 if((sockfd = socket(PF_INET,SOCK_STREAM,0))<0) 19 ERR("socket failed"); 20 21 //3.connect 22 struct hostent *ent; 23 if((ent=gethostbyname(ipstr))==NULL) 24 ERR("gethostbyname failed"); 25 26 struct sockaddr_in peer; 27 CLEAR(peer); 28 peer.sin_family = AF_INET; 29 peer.sin_port = htons(port); 30 //inet_pton(AF_INET,ipstr,&peer.sin_addr); 31 memcpy(&peer.sin_addr,ent->h_addr,sizeof(struct in_addr)); 32 if(connect(sockfd,(struct sockaddr*)&peer,sizeof(peer))<0) 33 ERR("connect failed"); 34 35 //4.交互 36 char banner[255]; 37 int n; 38 if((n = read(sockfd,banner,sizeof(banner)))<0) 39 ERR("read failed"); 40 else if(n==0) 41 goto end; 42 banner[n] = 0; 43 printf("%s\n",banner); 44 45 do_business(sockfd); 46 47 //5.关闭 48 end: 49 close(sockfd); 50 51 return 0; 52 } 53 54 void do_business(int sockfd) 55 { 56 int n; 57 char buf[255],msg[255]; 58 while(1) 59 { 60 printf("shell# "); 61 fflush(stdout); 62 scanf("%s",buf); 63 if(write(sockfd,buf,strlen(buf))<0) 64 ERR("write failed"); 65 if((n = read(sockfd,msg,sizeof(msg)))<0) 66 ERR("read failed"); 67 else if(n==0) 68 break; 69 msg[n] = 0; 70 printf("%s\n",msg); 71 } 72 }
Makefile
CC = gcc CPPFLAGS = -DMODEL_THREAD CFLAGS = -Wall -g LDFLAGS = -lpthread TARGETS = echoserver echoclient all:$(TARGETS) clean: $(RM) $(TARGETS) .PHONY: all clean