Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2159586
  • 博文数量: 438
  • 博客积分: 3871
  • 博客等级: 中校
  • 技术积分: 6075
  • 用 户 组: 普通用户
  • 注册时间: 2011-09-10 00:11
个人简介

邮箱: wangcong02345@163.com

文章分类

全部博文(438)

文章存档

2017年(15)

2016年(119)

2015年(91)

2014年(62)

2013年(56)

2012年(79)

2011年(16)

分类: LINUX

2015-06-11 16:02:50

1. 说明
    第5章的第一个程序
   client从终端读入一行,写到socket中
   server从socket中读入一行,并将读到的data写到socket中
   client从socket中读取一行,并显示到终端
2. 源码
2.1 server.c
  1. cong@msi:/work/test/tcpip/5tcp$ cat serv1/tcpserv.c
  2. #include "utils.h"

  3. #define LISTENQ 10
  4. void str_echo(int sockfd)
  5. {
  6.     ssize_t n;
  7.     char buf[MAXLINE];
  8. again:
  9.     while( (n=read(sockfd, buf, MAXLINE)) > 0)
  10.         write(sockfd, buf, n);
  11.         
  12.     if( (n<0) && (errno==EINTR) )
  13.         goto again;
  14.     else if(n < 0)
  15.         dbmsg("read_error");
  16. }

  17. int main ( int argc, char *argv[] )
  18. {
  19.     int listenfd, connfd;
  20.     struct sockaddr_in servaddr, cliaddr;
  21.     pid_t childpid;
  22.     char buf[1024];
  23.     int len;
  24.     listenfd = socket(AF_INET, SOCK_STREAM, 0);
  25.     if(listenfd< 0)
  26.         return -1;
  27.     bzero(&servaddr, sizeof(servaddr));
  28.     servaddr.sin_family = AF_INET;
  29.     servaddr.sin_port = htons(13999);
  30.     servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  31.     //inet_pton(AF_INET, TIME_SERV_ADDR, &servaddr.sin_addr);
  32.      
  33.     bind(listenfd, (const struct sockaddr*)&servaddr, sizeof(servaddr));
  34.     listen(listenfd, LISTENQ);
  35.     while(1)
  36.     {
  37.         len = sizeof(cliaddr);
  38.         //connfd = accept(listenfd, (struct sockaddr*)NULL, NULL);
  39.         connfd = accept(listenfd, (struct sockaddr*)&cliaddr,(socklen_t*)&len);  -->打印连接的客户端
  40.         dbmsg("accept:%s,port=%d", inet_ntop(AF_INET,&cliaddr.sin_addr,buf, sizeof(buf)), ntohs(cliaddr.sin_port));
  41.         if( (childpid=fork()) == 0)
  42.         {
  43.             close(listenfd);
  44.             str_echo(connfd);
  45.             exit(0);
  46.         }
  47.         dbmsg("close connfd");
  48.         close(connfd);
  49.     }

  50.     return EXIT_SUCCESS;
  51. }
2.2 client.c
  1. #include "utils.h"

  2. //#define TIME_SERV_ADDR "192.168.4.98"
  3. #define TIME_SERV_ADDR "127.0.0.1"

  4. ssize_t readline(int fd, void* vptr, size_t maxlen)
  5. {
  6.     ssize_t n, rc;
  7.     char c,*ptr;
  8.     ptr = vptr;
  9.     for(n=0; n<maxlen; n++)
  10.     {
  11. again:
  12.         if((rc=read(fd,&c,1)) == 1)
  13.         {
  14.             *ptr++ = c;
  15.             if(c == '\n')
  16.                 break;
  17.         } else if(rc == 0) {
  18.             *ptr = 0;
  19.             return n;
  20.         }else {
  21.             if( errno == EINTR)
  22.                 goto again;
  23.             return -1;
  24.         }
  25.     }
  26.     *ptr = '\0';   //末尾补0
  27.     return n;
  28. }

  29. void str_cli(FILE* fp, int sockfd)
  30. {
  31.     char sendline[MAXLINE], recvline[MAXLINE];
  32.     while(fgets(sendline, MAXLINE, fp) != NULL)
  33.     {
  34.         write(sockfd, sendline, strlen(sendline));
  35.         if(readline(sockfd, recvline, MAXLINE) == 0)
  36.             dbmsg("server terminated");
  37.         fputs(recvline, stdout);
  38.     }
  39. }

  40. int main ( int argc, char *argv[] )
  41. {
  42.     int sockfd, n;
  43.     struct sockaddr_in servaddr;
  44.     char recvline[1024];
  45.     sockfd = socket(AF_INET, SOCK_STREAM, 0);
  46.     if(sockfd < 0)
  47.         return -1;
  48.     bzero(&servaddr, sizeof(servaddr));
  49.     servaddr.sin_family = AF_INET;
  50.     servaddr.sin_port = htons(13999);
  51.     inet_pton(AF_INET, TIME_SERV_ADDR, &servaddr.sin_addr);
  52.     dbmsg("next connect");
  53.     connect(sockfd, (const struct sockaddr*)&servaddr, sizeof(servaddr));
  54.     dbmsg("connect success");

  55.     str_cli(stdin, sockfd);
  56.     return EXIT_SUCCESS;
  57. }
2.3 utils.h
client与server共用一个
  1. cong@msi:/work/test/tcpip/3tcp$ cat utils.h
  2. #ifndef UTILS_H__
  3. #define UTILS_H__
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <sys/types.h> /* See NOTES */
  7. #include <sys/socket.h>
  8. #include <netinet/in.h>
  9. #include <arpa/inet.h>
  10. #include <time.h>
  11. #include <string.h>
  12. #include <errno.h>

  13. #define MAXLINE 1024

  14. #define dbmsg(fmt, args ...) printf("%s:%s[%d]: "fmt"\n", __FILE__,__FUNCTION__, __LINE__,##args)

  15. #endif
3. 状态说明
3.1 当client与server都启动时,client执行connect连接上了server,
     server的accept从阻塞中返回,三次握手结束,此时状态如下
  1. cong@msi:/work/test/tcpip/5tcp/client1$ netstat -a | grep "13999"
  2. tcp 0 0     *:13999                *:*                LISTEN      -->serv端

  3. tcp 0 0     localhost:41283        localhost:13999    ESTABLISHED  -->serv端的fork子进制

  tcp 0 0     localhost:13999        localhost:41283    ESTABLISHED   --> client端

3.2当client退出时,执行ps命令查看
  1. cong@msi:/work/test/tcpip/5tcp/client1$ ps -u
  2. USER   PID    STAT  START   TIME  COMMAND
  3. cong   12079  S+    15:31   0:00  ./tcpserv
  4. cong   12081  Z+    15:31   0:00  [tcpserv] <defunct>
发现server的child进制处于Z,僵死状态。下一篇解决
3.2.1
ps命令
  1. ps参数:
  2. -A: 等同于-f列出所有的进制
  3. -a: 显示其他用户启动的进程
  4. -x: 查看系统中属于自己的进程
  5. -u: 按用户名和启动时间的顺序显示进程
  6. -j: 用任务格式来显示进程
  7. -f: 用树形格式来显示进制

  8. 状态码:
  9.   D --> 不可中断 --> uninterruptible sleep (usually IO)
  10.   R --> 运行 --> running or runnable (on run queue)
  11.   S --> 中断 --> interruptible sleep (waiting for an event to complete)
  12.   T --> 停止 --> stopped, either by a job control signal or because it is being traced
  13.   Z --> 僵死 --> defunct ("zombie") process, terminated but not reaped by its parent

(下载后改名为client.tar.gz)
client.rar

(下载后改名为serv.tar.gz)
serv.rar



阅读(990) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~