Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2150598
  • 博文数量: 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 17:52:50

1. 说明
1.1 功能
  第5章的第一个程序
   client从终端读入一行,写到socket中
   server从socket中读入一行,并将读到的data写到socket中
   client从socket中读取一行,并显示到终端
1.2 问题
unix网络编程笔记---4.时间获取server与client 中ps命令显示server有僵死进程,
同时对慢系统调用函数accept的EINTR没有处理
1.3 主要修改了server端,client端没有变化
2. 源码
server.c
  1. cong@msi:/work/test/tcpip/6tcp/serv1$ cat tcpserv.c
  2. #include "utils.h"

  3. #define LISTENQ 10
  4. void sig_chld(int signo)     //问题1.处理sigchld
  5. {
  6.     pid_t pid;
  7.     int stat;
  8.     pid = wait(&stat);
  9.     dbmsg("child %d terminated", pid);
  10.     return ;
  11. }
  12. void str_echo(int sockfd)
  13. {
  14.     ssize_t n;
  15.     char buf[MAXLINE];
  16. again:
  17.     while( (n=read(sockfd, buf, MAXLINE)) > 0)
  18.         write(sockfd, buf, n);
  19.         
  20.     if( (n<0) && (errno==EINTR) )
  21.         goto again;
  22.     else if(n < 0)
  23.         dbmsg("read_error");
  24. }

  25. int main ( int argc, char *argv[] )
  26. {
  27.     int listenfd, connfd;
  28.     struct sockaddr_in servaddr, cliaddr;
  29.     signal(SIGCHLD, sig_chld);     //问题1.捕获信号sigchld
  30.     pid_t childpid;
  31.     char buf[1024];
  32.     int len;
  33.     listenfd = socket(AF_INET, SOCK_STREAM, 0);
  34.     if(listenfd< 0)
  35.         return -1;
  36.     bzero(&servaddr, sizeof(servaddr));
  37.     servaddr.sin_family = AF_INET;
  38.     servaddr.sin_port = htons(13999);
  39.     servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  40.     //inet_pton(AF_INET, TIME_SERV_ADDR, &servaddr.sin_addr);
  41.      
  42.     bind(listenfd, (const struct sockaddr*)&servaddr, sizeof(servaddr));
  43.     listen(listenfd, LISTENQ);
  44.     while(1)
  45.     {
  46.         len = sizeof(cliaddr);
  47.         //connfd = accept(listenfd, (struct sockaddr*)NULL, NULL);
  48.         connfd = accept(listenfd, (struct sockaddr*)&cliaddr,(socklen_t*)&len);
  49.         dbmsg("accept:%s,port=%d", inet_ntop(AF_INET,&cliaddr.sin_addr,buf, sizeof(buf)), ntohs(cliaddr.sin_port));
  50.         if(errno == EINTR)           //问题2.慢系统调用accept返回eintr时,需要重启accept
  51.         {
  52.             dbmsg("EINTR");
  53.             continue;
  54.         }
  55.         if( (childpid=fork()) == 0)
  56.         {
  57.             close(listenfd);
  58.             str_echo(connfd);
  59.             exit(0);                  //问题1.子进程exit时会产生信号sigchld
  60.         }
  61.         dbmsg("close connfd");
  62.         close(connfd);
  63.     }

  64.     return EXIT_SUCCESS;
  65. }

client.c
  1. cong@msi:/work/test/tcpip/6tcp/client$ cat client.c
  2. #include "utils.h"

  3. //#define TIME_SERV_ADDR "192.168.4.98"
  4. #define TIME_SERV_ADDR "127.0.0.1"
  5. #if 0 
  6. //这段readline有bug
  7. //buf的末尾没有加'\0',导致显示时出错
  8. ssize_t readline(int fd, void* vptr, size_t maxlen)
  9. {
  10.     ssize_t n, rc;
  11.     char c,*ptr;
  12.     ptr = vptr;
  13.     for(n=1; n<maxlen; n++)
  14.     {
  15. again:
  16.         if((rc=read(fd,&c,1)) == 1)
  17.         {
  18.             *ptr++ = c;
  19.             if(c == '\n')
  20.                 break;
  21.         } else if(rc == 0) {
  22.             *ptr = 0;
  23.             return (n-1);
  24.         }else {
  25.             if( errno == EINTR)
  26.                 goto again;
  27.             return -1;
  28.         }
  29.     }
  30. }
  31. #endif
  32. ssize_t readline(int fd, void* vptr, size_t maxlen)
    {
        ssize_t n, rc;
        char c,*ptr;
        ptr = vptr;
        for(n=0; n again:
            if((rc=read(fd,&c,1)) == 1)
            {
                *ptr++ = c;
                if(c == '\n')
                    break;
            } else if(rc == 0) {
                *ptr = 0;
                return n;
            }else {
                if( errno == EINTR)
                    goto again;
                return -1;
            }
        }   
        *ptr = '\0';
        return n;
    }
  33. void str_cli(FILE* fp, int sockfd)
  34. {
  35.     char sendline[MAXLINE], recvline[MAXLINE];
  36.     while(fgets(sendline, MAXLINE, fp) != NULL)
  37.     {
  38.         write(sockfd, sendline, strlen(sendline));
  39.         if(readline(sockfd, recvline, MAXLINE) == 0)
  40.             dbmsg("server terminated");
  41.         fputs(recvline, stdout);
  42.     }

  43. }

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

  59.     str_cli(stdin, sockfd);
  60.     return EXIT_SUCCESS;
  61. }

utils.h
  1. cong@msi:/work/test/tcpip/6tcp/serv$ 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. #include <signal.h>

  14. #define MAXLINE 1024

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

  16. #endif

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

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