TCP编程实现双工通信

流程:

服务器:

socket:创建一个用与链接的套接字(用于链接)

填充结构体:填充服务器的ip和端口

bind:绑定自己的ip地址和端口

listen:监听,将主动套接字转为被动套接字

accept:阻塞等待客户端链接,链接成功返回一个用于通信套接字

recv:接收消息

send:发送消息

close:关闭文件描述符

客户端:

socket:创建一个套接字

填充结构体:填充服务器的ip和端口

connect:阻塞等待链接服务器

recv/send:接收/发送消息

close:关闭

服务器端:
int main(int argc, char const *argv[])
{
    if (argc != 2)
    {
        printf("please input:%s  <port>\n", argv[0]);
        return -1;
    }
    //1.创建套接字
    int sockfd, acceptfd;
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
        perror("socket err");
        return -1;
    }
    printf("sockfd=%d\n", sockfd);

    //填充ipv4的通信结构体
    struct sockaddr_in serveraddr, caddr;
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(atoi(argv[1])); //将主机小端转换为网络大端
    //serveraddr.sin_addr.s_addr = inet_addr(argv[1]);  //将ip地址转为机器使用的32位无符号整数

    //自动获取IP
    //serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
    //serveraddr.sin_addr.s_addr = INADDR_ANY;
    serveraddr.sin_addr.s_addr = inet_addr("0.0.0.0");

    //2.绑定套接字
    if (bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0)
    {
        perror("bind err");
        return -1;
    }
    printf("bind ok\n");

    //3.监听套接字,将主动套接字转为被动套接字
    if (listen(sockfd, 5) < 0)
    {
        perror("listen err");
        return -1;
    }

    socklen_t len = sizeof(caddr);
    //4.阻塞等待客户端连接,连接成功返回一个用于通信的文件描述符
    //循环等待客户端
    while (1)
    {
        acceptfd = accept(sockfd, (struct sockaddr *)&caddr, &len);
        if (acceptfd < 0)
        {
            perror("accept err");
            return -1;
        }
        printf("client:ip=%s  port=%d\n", inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port));
        char buf[128];
        pid_t pid = fork();
        if (pid < 0)
        {
            perror("fork err");
            return -1;
        }
        else if (pid == 0)
        {
            int sendbyte;
            while (1)
            {
                fgets(buf, sizeof(buf), stdin);
                if (buf[strlen(buf) - 1] == '\n')
                    buf[strlen(buf) - 1] = '\0';
                sendbyte = send(acceptfd, buf, sizeof(buf), 0);
                if (sendbyte < 0)
                {
                    perror("send err");
                    return -1;
                }
            }
        }
        //5.循环接收消息  通信
        else
        {
            int recvbyte;
            while (1)
            {
                recvbyte = recv(acceptfd, buf, sizeof(buf), 0);
                if (recvbyte < 0)
                {
                    perror("recv err");
                    return -1;
                }
                else if (recvbyte == 0)
                {
                    printf("client exit\n");
                    kill(pid,SIGKILL);
                    wait(NULL);
                    break;
                }
                else
                {
                    printf("buf:%s\n", buf);
                }
            }
            close(acceptfd);
        }
    }
    close(sockfd);
    return 0;
}
客户端:
int main(int argc, char const *argv[])
{
    if (argc != 3)
    {
        printf("please input %s <ip> <port>\n", argv[0]);
        return -1;
    }
    //1.创建套接子
    int sockfd;
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
        perror("socket error.");
        return -1;
    }
    printf("sockfd=%d\n", sockfd);
    //填充ipv4的通信结构体  服务器的ip和端口
    struct sockaddr_in serveraddr;
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(atoi(argv[2]));
    serveraddr.sin_addr.s_addr = inet_addr(argv[1]);

    //2.请求链接服务器
    if (connect(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0)
    {
        perror("connect error.");
        return -1;
    }

    //5.循环发送消息  通信
    char buf[128];
    pid_t pid = fork();
    if (pid < 0)
    {
        perror("fork err.");
        return -1;
    }
    else if (pid == 0)
    {
        int recvbyte;
        while (1)
        {
            recvbyte = recv(sockfd, buf, sizeof(buf), 0);
            if (recvbyte < 0)
            {
                perror("recv err.");
                return -1;
            }
            printf("buf:%s\n", buf);
        }
    }
    else
    {
        int sendbyte;
        while (1)
        {
            fgets(buf, sizeof(buf), stdin);
            if (buf[strlen(buf) - 1] == '\n')
                buf[strlen(buf) - 1] = '\0';
            sendbyte = send(sockfd, buf, sizeof(buf), 0);
            if (sendbyte < 0)
            {
                perror("send error.");
                return -1;
            }
            if (strncmp(buf, "quit", 4) == 0)
            {
                kill(pid, SIGKILL);
                wait(NULL);
                exit(-1);
            }
        }
    }
    close(sockfd);
    return 0;
}
运行结果显示:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值