一、TCP C/S:客户端、服务器程序示例

原创
2016/06/18 13:25
阅读数 919

1. 客户端程序

客户端程序从标准输入读取用户输入,发送给服务器,然后读取服务器响应,并将响应打印到标准输出。

以阻塞方式读写套接字。

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>

#define MAXBUF      1024
#define SERV_PORT   9000

void str_cli(FILE *fp, int sockfd)
{
    char    sendbuf[MAXBUF], recvbuf[MAXBUF];
    int recvn;

    while (fgets(sendbuf, MAXBUF, fp) != NULL) {
        if (write(sockfd, sendbuf, strlen(sendbuf)) < 0) {
            perror("write");
            return;
        }
        if ((recvn = read(sockfd, recvbuf, sizeof(recvbuf)-1)) < 0) {
            fprintf(stderr, "str_cli: server terminated prematurely");
            return;
        } else if(recvn == 0) {
            fprintf(stderr, "str_cli: read EOF\n");
            return;
        }
        recvbuf[recvn] = '\0';

        fputs(recvbuf, stdout);
    }
}

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

    if (argc != 2) {
        fprintf(stderr, "usage: tcpcli <IPaddress>\n");
        return 0;
    }

    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("socket");
        exit(EXIT_FAILURE);
    }

    memset(&servaddr, 0x00, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(SERV_PORT);
    if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) < 0) {
        perror("inet_pton");
        exit(EXIT_FAILURE);
    }

    if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
        perror("connect");
        exit(EXIT_FAILURE);
    }

    str_cli(stdin, sockfd);

    exit(EXIT_SUCCESS);
}

2. 服务器程序

服务器接收到客户端连接请求,fork 一个子进程进行处理。

处理过程为,读取客户端数据,然后又将其发送给客户端。

以阻塞方式读写套接字。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/wait.h>

#define SERV_PORT   9000
#define LISTENQ     5
#define MAXBUF      1024 

void sig_chld(int signo)
{
    pid_t   pid;
    int     stat;

    while ((pid = waitpid(-1, &stat, WNOHANG)) > 0) {
        fprintf(stderr, "child %d terminated\n", pid);
    }
}

void str_echo(int sockfd)
{
    ssize_t n;
    char    buf[MAXBUF];

    while ((n = read(sockfd, buf, MAXBUF)) > 0) {
        if (write(sockfd, buf, n) < 0) {
            perror("write");
            break;
        }
    }
}

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

    if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("socket");
        exit(EXIT_FAILURE);
    }

    memset(&servaddr, 0x00, 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)) < 0) {
        perror("bind");
        exit(EXIT_FAILURE);
    }

    if (listen(listenfd, LISTENQ)) {
        perror("listen");
        exit(EXIT_FAILURE);
    }

    signal(SIGCHLD, sig_chld);

    for ( ; ; ) {
        clilen = sizeof(cliaddr);
        connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen);
        if (connfd < 0) {
            perror("connfd");
            continue;
        }

        if ((childpid = fork()) < 0) {
            perror("fork");
            exit(EXIT_FAILURE);
        } else if (childpid == 0) {
            close(listenfd);
            str_echo(connfd);
            exit(0);
        }
        close(connfd);
    }

    return 0;
}

参考资料

《UNP v1》

展开阅读全文
打赏
0
2 收藏
分享
加载中
更多评论
打赏
0 评论
2 收藏
0
分享
返回顶部
顶部