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

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》

转载于:https://my.oschina.net/lowkey2046/blog/693852

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值