TCP编程之二

二 文件传输模型  

util.c

 1 #include <apue.h>
 2 
 3 /**
 4  * return value:ret
 5  * ret<0          @error
 6  * ret ==0         @success
 7  * ret<len && ret>0  @socket is closed by peer
 8  */
 9 int readn(int fd,void *buf,size_t len)
10 {
11     int total = 0,n;
12     while(total<len)
13     {
14 again:
15         if((n = read(fd,buf+total,len-total))<0)
16         {
17             if(errno==EINTR)
18                 goto again;
19             return -1;
20         }
21         else if(n==0)
22             break;
23         total += n;
24     }
25     return total;
26 }
27 
28 /**
29  * return value:ret
30  * ret<0          @error
31  * ret>=0         @success
32  */
33 int writen(int fd,const void *buf,size_t len)
34 {
35     int total = 0,n;
36     while(total<len)
37     {
38 again:
39         if((n = write(fd,buf+total,len-total))<0)
40         {
41             if(errno==EINTR)
42                 goto again;
43             return -1;
44         }
45         total += n;
46     }
47     return 0;
48 }

server.c

  1 #include <apue.h>
  2 #include "common.h"
  3 #include "util.h"
  4 
  5 #define PORT 8080
  6 #define IP "192.168.5.99"
  7 #define BACKLOG 10
  8 
  9 #define FILENAME "passwd"
 10 
 11 void *routine(void *arg);
 12 void do_business();
 13 
 14 int main(int argc, char **argv)
 15 {
 16     int sockfd;
 17     //1.创建socket
 18     if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
 19         ERR("Socket failed");
 20 
 21 #if 0
 22     struct sockaddr_in {
 23         sa_family_t sin_family;
 24         in_port_t sin_port;
 25         struct in_addr sin_addr;
 26         unsigned char sin_zero[8];
 27     };
 28 #endif
 29     //2.给socket绑定地址
 30     struct sockaddr_in ipv4, peer;
 31     ipv4.sin_family = AF_INET;
 32     ipv4.sin_port = htons(PORT);    //NBO
 33     inet_pton(AF_INET, IP, &ipv4.sin_addr);    //NBO
 34     memset(ipv4.sin_zero, 0, sizeof(ipv4.sin_zero));
 35     if (bind(sockfd, (struct sockaddr *) &ipv4, sizeof(ipv4)) < 0)
 36         ERR("bind failed");
 37 
 38     //3.监听
 39     if (listen(sockfd, BACKLOG) < 0)
 40         ERR("listen failed");
 41 
 42     //4.接收连接
 43     socklen_t len = sizeof(peer);    //value-result argument
 44     int connfd;
 45     for (;;) {
 46         if ((connfd = accept(sockfd, (struct sockaddr *) &peer, &len)) < 0)
 47             ERR("accept failed");
 48 
 49         unsigned short peerport = ntohs(peer.sin_port);
 50         char ipstr[] = "ddd.ddd.ddd.ddd";
 51         inet_ntop(AF_INET, &peer.sin_addr, ipstr, sizeof(ipstr));
 52 
 53         //5.通信
 54         char banner[255];
 55         sprintf(banner, "[%s:%d] welcome to echoserver!", ipstr,
 56             peerport);
 57         printf("Accept a new Connection: %s,%d
",ipstr,peerport);
 58         if(write(connfd, banner, strlen(banner)) < strlen(banner))
 59             ERR("write failed");
 60 
 61 #ifdef MODEL_THREAD
 62         pthread_t tid;
 63         if(pthread_create(&tid,NULL,routine,(void*)connfd))
 64             ERR("create thread failed");
 65 #elif MODEL_FORK
 66         pid_t pid;
 67         if((pid = fork())<0)
 68             ERR("fork failed");
 69         else if(pid==0)
 70         {
 71             close(sockfd);        //1.关闭无用描述符
 72             do_business(connfd);
 73             exit(0);            //2.显式指定退出
 74         }
 75         close(connfd);    
 76 #endif
 77     }
 78     //7.关闭服务器
 79     close(sockfd);
 80     return 0;
 81 }
 82 
 83 void do_business()
 84 {
 85     sleep(20);
 86 }
 87 
 88 void *routine(void *arg)
 89 {
 90     int n,fd,connfd = (int)arg;
 91 
 92     struct stat st;
 93     if(stat(FILENAME,&st)<0)
 94         ERR("stat failed");
 95     size_t filesize = st.st_size;
 96 
 97     //1.send filename
 98     if(writen(connfd,FILENAME,LEN_FILENAME)<0)
 99         ERR("write fialed");
100     //2.send filesize
101     int filesize_nbo = htonl(filesize);
102     if(writen(connfd,&filesize_nbo,LEN_FILESIZE)<0)
103         ERR("write failed");
104     //3.send filecontent <loop>
105     if((fd = open(FILENAME,O_RDONLY))<0)
106         ERR("open failed");
107     char buf[LEN_BUF];
108     while(1)
109     {
110         if((n = read(fd,buf,LEN_BUF))<0)
111             ERR("read failed");
112         else if(n==0)    //EOF
113             break;
114         if(writen(connfd,buf,n)<0)
115             ERR("write failed");
116     }
117     close(fd);
118     close(connfd);
119 
120     return NULL;
121 }

client.c

 1 #include <apue.h>
 2 #include "common.h"
 3 #include "util.h"
 4 
 5 void do_business(int sockfd);
 6 
 7 int main(int argc,char **argv)
 8 {    
 9     //1.判断命令行
10     if(argc!=3)
11     {
12         printf("Usage: %s <host> <port>
",argv[0]);
13         exit(0);
14     }
15     char *ipstr = argv[1];
16     unsigned short port = strtol(argv[2],NULL,10);
17 
18     //2.socket
19     int sockfd;
20     if((sockfd = socket(PF_INET,SOCK_STREAM,0))<0)
21         ERR("socket failed");
22 
23     //3.connect
24     struct sockaddr_in peer;
25     CLEAR(peer);
26     peer.sin_family = AF_INET;
27     peer.sin_port = htons(port);
28     inet_pton(AF_INET,ipstr,&peer.sin_addr);
29     if(connect(sockfd,(struct sockaddr*)&peer,sizeof(peer))<0)
30         ERR("connect failed");
31 
32     //4.交互
33     char banner[255];
34     int n;
35     if((n = read(sockfd,banner,sizeof(banner)))<0)
36         ERR("read failed");
37     else if(n==0)
38         goto end;
39     banner[n] = 0;
40     printf("%s
",banner);
41 
42     do_business(sockfd);
43 
44     //5.关闭
45 end:
46     close(sockfd);
47 
48     return 0;
49 }
50 
51 void do_business(int sockfd)
52 {
53     int n;
54     char filename[LEN_FILENAME];
55     //1.read filename
56     if((n=readn(sockfd,filename,LEN_FILENAME))<0)
57         ERR("read failed");
58     else if(n<LEN_FILENAME)
59     {
60         fprintf(stderr,"Connection is closed by peer!
");
61         return;
62     }
63 
64     //2.read filesize
65     size_t filesize_nbo,filesize;
66     if((n=readn(sockfd,&filesize_nbo,LEN_FILESIZE))<0)
67         ERR("read failed");
68     else if(n<LEN_FILESIZE)
69     {
70         fprintf(stderr,"Connection is closed by peer!
");
71         return;
72     }
73     filesize = ntohl(filesize_nbo);
74 
75     //3.read filecontent
76     int fd,total = 0;
77     if((fd = open(filename,O_WRONLY|O_CREAT,0644))<0)
78         ERR("Open file failed");
79     char buf[LEN_BUF];
80     while(total<filesize)
81     {
82         if((n=read(sockfd,buf,LEN_BUF))<0)
83             ERR("read failed");
84         else if(n==0)
85         {
86             fprintf(stderr,"Connection is closed by peer!
");
87             return;
88         }
89         if(writen(fd,buf,n)<0)
90             ERR("write failed");
91         total += n;
92     }
93 }
原文地址:https://www.cnblogs.com/xiaoying1245970347/p/3791008.html