zoukankan      html  css  js  c++  java
  • linux网络编程框架

     

    OSI七层模型与TCP四层模型

    OSI七层模型与TCP四层模型

    BS和CS服务器架构

    (1)CS架构介绍(client server,客户端服务器架构)
    (2)BS架构介绍(broswer server,浏览器服务器架构)

    TCP协议

    (1)建立连接需要三次握手
    (2)建立连接的条件:服务器listen时客户端主动发起connect
    (3)关闭连接需要四次握手
    (4)服务器或者客户端都可以主动发起关闭

    注:这些握手协议已经封装在TCP协议内部,socket编程接口平时不用管

    TCP如何保证可靠传输
    (1)TCP在传输有效信息前要求通信双方必须先握手,建立连接才能通信
    (2)TCP的接收方收到数据包后会ack给发送方,若发送方未收到ack会丢包重传
    (3)TCP的有效数据内容会附带校验,以防止内容在传递过程中损坏
    (4)TCP会根据网络带宽来自动调节适配速率滑动窗口技术
    (5)发送方会给各分割报文编号,接收方会校验编号,一旦顺序错误即会重传。

    基于socket编程

    1、建立连接
    (1)socket。socket函数类似于open,用来打开一个网络连接,如果成功则返回一个网络文件描述符(int类型),之后我们操作这个网络连接都通过这个网络文件描述符。
    (2)bind
    (3)listen
    (4)connect
    2、发送和接收
    (1)send和write
    (2)recv和read
    3、辅助性函数
    (1)inet_aton、inet_addr、inet_ntoa
    (2)inet_ntop、inet_pton
    4、表示IP地址相关数据结构
    (1)都定义在 netinet/in.h
    (2)struct sockaddr,这个结构体是网络编程接口中用来表示一个IP地址的,注意这个IP地址是不区分IPv4和IPv6的(或者说是兼容IPv4和IPv6的)
    (3)typedef uint32_t in_addr_t; 网络内部用来表示IP地址的类型
    (4)

    struct in_addr
    {
    in_addr_t s_addr;
    };
    (5)struct sockaddr_in
    {
    __SOCKADDR_COMMON (sin_);
    in_port_t sin_port; /* Port number. */
    struct in_addr sin_addr; /* Internet address. */
    
    /* Pad to size of `struct sockaddr'. */
    unsigned char sin_zero[sizeof (struct sockaddr) -
    __SOCKADDR_COMMON_SIZE -
    sizeof (in_port_t) -
    sizeof (struct in_addr)];
    };

    (6)struct sockaddr 这个结构体是linux的网络编程接口中用来表示IP地址的标准结构体,bind、connect等函数中都需要这个结构体,这个结构体是兼容IPV4和IPV6的。在实际编程中这个结构体会被一个struct sockaddr_in或者一个struct sockaddr_in6所填充。

     

    客户端流程

    服务器流程

    htons函数为将主机序转为网络序
    网络字节顺序NBO(Network Byte Order): 按从高到低的顺序存储,在网络上使用统一的网络字节顺序,可以避免兼容性问题。(大端模式)

    主机字节顺序(HBO,Host Byte Order): 不同的机器HBO不相同,与CPU设计有关,数据的顺序是由cpu决定的,而与操作系统无关。

    客户端与服务器代码

    #include <stdio.h>
    #include <sys/socket.h>
    #include <sys/types.h>          /* See NOTES */
    #include <arpa/inet.h>
    #include <string.h>
    
    #define SERVER_IP     "192.168.149.137"
    #define SERVER_PORT  5005
    #define BACKLOG  100
    #define DEBUF(X) printf(X)
    
    typedef struct commu
    {
        char name[20];
        int age;
    }info;
    
    int main()
    {
        int sock_fd = -1;//socket 描述符
        int server_fd = -1;//连接描述符
        struct sockaddr_in server_addr;
        struct sockaddr_in client_addr;//客户地址
        socklen_t len = 0;//接收长度
        int ret = -1;
        char send_buf[100];
        char recv_buf[100];
        //1,打开socket
        sock_fd = socket(AF_INET,SOCK_STREAM,0);
        if(-1 == sock_fd)
        {
            perror("socket");
            return -1;
        }
        printf("sock_fd = %d.
    ",sock_fd);
        //2、connect 连接服务器
        server_addr.sin_family = AF_INET;//IPV4
        server_addr.sin_port = htons(SERVER_PORT);//设置端口模式
        server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);//设置IP
        ret = connect(sock_fd,(struct  sockaddr  *)&server_addr,sizeof(server_addr));
        if(-1 == ret)
        {
            perror("connect");
            return -1;
        }
        DEBUF("成功简历连接
    ");
        info st1;
        while(1)
        {
            printf("请输入学生姓名
    ");
            scanf("%s",st1.name);
            printf("请输入学生年龄
    ");
            scanf("%d",&st1.age);
            //1.发送
            ret = send(sock_fd,&st1,sizeof(info),0);
            memset(send_buf,0,strlen(send_buf)); 
            printf("发送了一个学生信息
    ");
            //2.等待回复
            recv(sock_fd,recv_buf,sizeof(recv_buf),0);    
            printf("%s
    ",recv_buf);    
            memset(recv_buf,0,sizeof(recv_buf));
            //3.信息处理
        }
        return 0;
    }
    //服务器
    #include <stdio.h> #include <sys/socket.h> #include <sys/types.h> /* See NOTES */ #include <arpa/inet.h> #include <string.h> #define MY_IP "192.168.149.137" #define MY_PORT 5005 #define BACKLOG 100 #define DEBUF(X) printf(X) typedef struct commu { char name[20]; int age; int cmd; }info; int main() { int sock_fd = -1;//监听描述符 int client_fd = -1;//连接fd struct sockaddr_in server_addr; struct sockaddr_in client_addr;//客户地址 socklen_t len = 0;//接收长度 int ret = -1; char recv_buf[100]; char send_buf[100]; //1,打开socket sock_fd = socket(AF_INET,SOCK_STREAM,0); if(-1 == sock_fd) { perror("socket"); return -1; } printf("sock_fd = %d. ",sock_fd); //2.bind绑定socket 和本机IP 端口 server_addr.sin_family = AF_INET;//IPV4 server_addr.sin_port = htons(MY_PORT);//设置端口模式 server_addr.sin_addr.s_addr = inet_addr(MY_IP);//设置IP ret = bind(sock_fd,(struct sockaddr *)&server_addr,sizeof(server_addr)); if(-1 == ret) { perror("bind"); return -1; } DEBUF("bind ok "); //3.listen 设 置监听端口 ret = listen(sock_fd, BACKLOG);//BACKLOG为排队处理 if(-1 == ret) { perror("listen"); return -1; } DEBUF("listen ok "); //4.阻塞等待连接 client_fd = accept(sock_fd, (struct sockaddr *)&client_addr, &len); if(-1 == client_fd) { perror("listen"); return -1; } DEBUF("成功简历连接 "); //简历完成后可以通信 memset(recv_buf,0,sizeof(recv_buf)); info st1; while(1) { //1、 服务器收 recv(client_fd,&st1,sizeof(st1),0); printf("学生名字为:%s ",st1.name); printf("学生年龄为:%d ",st1.age); memset(recv_buf,0,sizeof(recv_buf)); //2、 服务器处理数据 //3、 回复客户端 send(client_fd,"OK",2,0); } return 0; }
  • 相关阅读:
    Java并发问题--乐观锁与悲观锁以及乐观锁的一种实现方式-CAS
    什么情况下Java程序会产生死锁?
    正确重写hashCode的办法
    浅析JVM类加载机制
    JVM中的新生代和老年代(Eden空间、两个Survior空间)
    解释循环中的递归调用
    get和post方法功能类似的,使用建议
    微信开发(五)微信消息加解密 (EncodingAESKey)
    PostgreSQL远程连接,发生致命错误:没有用于主机“…”,用户“…”,数据库“…”,SSL关闭的pg_hba.conf记录
    struts原理
  • 原文地址:https://www.cnblogs.com/PengfeiSong/p/6582998.html
Copyright © 2011-2022 走看看