Chinaunix首页 | 论坛 | 博客
  • 博客访问: 206904
  • 博文数量: 38
  • 博客积分: 2060
  • 博客等级: 大尉
  • 技术积分: 388
  • 用 户 组: 普通用户
  • 注册时间: 2009-03-17 10:10
文章分类

全部博文(38)

文章存档

2011年(1)

2009年(37)

我的朋友

分类: LINUX

2009-07-15 16:18:03

/************************

 * client

 ************************/

#include <stdio.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>

#define SERV_ADDR "127.0.0.1"
#define SERV_PORT 5358
#define BUF_LEN 1024

void str_cli(FILE *fp, int sockfd)
{
    char sendbuf[BUF_LEN] = {0};
    char recvbuf[BUF_LEN] = {0};

    while(1) {
        bzero(sendbuf, BUF_LEN);
        bzero(recvbuf, BUF_LEN);
        scanf("%s", sendbuf);
        write(sockfd, sendbuf, strlen(sendbuf));
        read(sockfd, recvbuf, strlen(sendbuf));
        printf("recieve: %s\n", recvbuf);
    }
    return;
}

int main(int argc, char **argv)
{
    int fd;
    struct sockaddr_in servaddr;

    fd = socket(AF_INET, SOCK_STREAM, 0);

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = inet_addr(SERV_ADDR);
    servaddr.sin_port = htons(SERV_PORT);

    if (connect(fd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1) {
        printf("connect error: %s\n", strerror(errno));
        return 0;
    }

    str_cli(stdin, fd);
    return 0;
}


/**********************

 * server

 **********************/
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <string.h>
#include <stdlib.h>

#define SERV_PORT 5358
#define MAX_CONN 10
#define BUF_LEN 1024

void str_echo(FILE *fp, int sockfd){
    ssize_t nread;
    char buf[BUF_LEN] = {0};
    while(1) {
        bzero(buf, BUF_LEN);
        if((nread = read(sockfd, buf, BUF_LEN)) == -1) {
            if(errno == EINTR) {
                continue;
            }
            else {
                printf("readn error: %s\n", strerror(errno));
                continue;
            }
        }
        else if (nread == 0) {
            break;
        }
        else {
            printf("%s\n", buf);
            write(sockfd, buf, nread);
        }
    }
}

void sig_chld(int sig){
    pid_t pid;
    int state;
    while((pid = waitpid(-1, &state, WNOHANG)) > 0){
        printf("child process %d exited.", pid);
    }
    return;
}

int main(int argc, char **argv)
{
    int listenfd, connfd, cliaddrlen;
    pid_t childpid;
    struct sockaddr_in servaddr, cliaddr;

    if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
        printf("socket error: %s\n", strerror(errno));
        return 0;
    }

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(SERV_PORT);
    if(bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1){
        printf("bind error: %s\n", strerror(errno));
        return 0;
    }

    if(listen(listenfd, MAX_CONN) == -1){
        printf("listen error: %s\n", strerror(errno));
        return 0;
    }

    signal(SIGCHLD, sig_chld);

    while(1){
        cliaddrlen = sizeof(cliaddr);
        if((connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddrlen)) == -1){
            if(errno == EINTR){
                continue;
            }
            else{
                printf("accept error: %s\n", strerror(errno));
                continue;
            }
        }

        if((childpid = fork()) == 0){
            close(listenfd);
            str_echo(stdin, connfd);
            exit(0);
        }
        else if(childpid > 0){
            close(connfd);
        }
        else{
            printf("fork error!\n");
            continue;
        }
    }
}

 

需要注意的问题:

1、必须对僵死子进程进行处理

unp上说到处理僵死子进程应当在信号处理函数里面调用waitpid而不是wait,原因在于unix信号不排队,从而导致信号处理函数调用次数不够,不能保证处理完所有僵死进程。个人认为问题的本质在于接收到一个SUGCHLD应该调用多少次wait或者waitpid,wait(&status)和waitpid(-1, &status, WNOHANG)的唯一区别在于前者是阻塞的,但是既然是收到SIGCHLD信号就证明有子进程结束,这样阻塞与不阻塞就没有什么区别。而unp上在调用二者时一个最大的区别在于wait只调用了一次,但是waitpid是放在一个循环中的,直到处理完所有的僵死子进程,问题的关键应在这个循环里。

2、服务器进程终止,客户端不能立即收到正确信息

参考<<服务器的几种异常终止>>

3、read和write函数存在一些问题

read函数有可能读不够期望的字节数就返回,原因在于内核中buf的字节数不足,为此,unp上专门写了个readn函数来解决。

write函数同样可能出现一次无法写完期望的字节数,原因在于内核的buf已满或被信号中断,unp上同样也给出了writen处理这个问题。

处理这些情况本身也确实比较麻烦,具体情况具体分析吧。

 

阅读(1321) | 评论(0) | 转发(0) |
0

上一篇:没有了

下一篇:服务器的几种异常终止

给主人留下些什么吧!~~