Liunx的socket通讯的流程图分析

一, socket服务端和客户的通信流程

这里写图片描述

二,分析代码的实现

1,这边我说的转换网络的ip地址其实是01010的数字封装在网络层的

  1. int inet_pton(int af, const char *src, void *dst); // 转换网络的ip地址
  2. uint32_t htonl(uint32_t hostlong); //ip地址数字转换成网络ip地址的
  3. uint16_t htons(uint16_t hostshort); //端口号数字转换成网络信息的端口号地址
  4. uint32_t ntohl(uint32_t netlong);
  5. uint16_t ntohs(uint16_t netshort);

代码的实现

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <ctype.h>
#include "wrap.h"
#include <sys/wait.h>

void wait_child(void * signo)
{
    while ( waitpid(0, NULL, WNOHANG) > 0);
    return;
}

#define SERV_PORT 8888

int main(int argc, char *argv[])
{
    //id进程
    pid_t pid;
    //socket的描述符
    int lfd, cfd;
    int i, n;
    char buf[BUFSIZ], clie_IP[BUFSIZ];
    struct sockaddr_in  serv_addr, clie_addr;

    socklen_t clie_addr_len;

    //创建一个socket
    lfd = Socket(AF_INET, SOCK_STREAM, 0); 

    bzero(&serv_addr, sizeof(serv_addr));
    //初始化操作

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(SERV_PORT);
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    //固定ip地址的操作
    // inet_pton(AF_INET, "127.0.0.1", serv_addr.sin_addr.s_addr);



    //绑定ip地址和端口号
    Bind(lfd,(struct sockaddr *) &serv_addr, sizeof(serv_addr));

    //连数量 
    Listen(lfd, 128);

    while (1)
    {
        clie_addr_len = sizeof(clie_addr);

        cfd = Accept(lfd,(struct sockaddr *) &clie_addr, &clie_addr_len);

        printf("client IP:%s, port:%d\n", 
                inet_ntop(AF_INET, &clie_addr.sin_addr.s_addr, clie_IP, sizeof(clie_IP)), 
                ntohs(clie_addr.sin_port));
        //开启子 进程    
        pid = fork();
        if (pid < 0)
        {
            perror("fork error");
            exit(1);
        }else if (pid == 0)
        {
            close(lfd);
            break;
        } else 
        {
            //父进程的处理
            close(cfd);
            //注册
            signal(SIGCHLD, wait_child);
        }
    }


    if (pid == 0)
    {

        while (1)
        {
            //读取数据
            n =  Read(cfd, buf, sizeof(buf));
            if ( n == 0) // client close
            {
                Close(cfd);
                return 0; 
            } else if(n == -1)
            {
                //信号打断
                perror("read error");
                exit(1);
            } 
            else{
                for (i = 0; i < n; i++)
                    buf[i] = toupper(buf[i]);
                write(cfd, buf, n);
                printf("客户端:", buf);
            }
        }
    }
    //关闭连接
    Close(lfd);
    return 0;
}

这里写图片描述

三,客户端client

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
//socket 的结构体
#include <arpa/inet.h>
#include <ctype.h>


/**
 *   client 端
 **/
#define SERV_IP "127.0.0.1"
#define SERV_PORT 8888

int main(int argc, char *argv[])
{

    // socket 描述符
    int cfd;
    //服务器的ip地址
    struct sockaddr_in serv_addr;
    //socklen_t serv_addr_len;
    //缓冲区 
    char buf[BUFSIZ];

    //创建一个socket
    cfd = socket(AF_INET, SOCK_STREAM, 0);

    memset(&serv_addr, 0, sizeof(serv_addr));

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(SERV_PORT);
    //serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    inet_pton(AF_INET, SERV_IP, &serv_addr.sin_addr.s_addr);


    //链接
    connect(cfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
    while (1)
    {
        //获取键盘内容
        fgets(buf, sizeof(buf), stdin);
        //写数据
        write(cfd, buf, strlen(buf)); // fgets ---> hello \n\0 
        //读取服务器的数据
        int n = (int)read(cfd, buf, sizeof(buf));
        //strncat("服务器发送的数据:", buf, n);
        //write(STDOUT_FILENO, buf, n);
        printf("服务器发送的数据:%s", buf);
    }
    //绑定
    //bind();
    close(cfd); 
    return 0;
}

效果图

这里写图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值