• socket 网络编程


    1.osi(Open System Interconnect)  开放式系统互联 7层模型

    2.TCP/IP五层协议和OSI的七层协议对应关系如下。

    3.tcp/ip与http的差别

    http协议的报文要通过tcp/ip来传输

    4.什么是 socket?

    socket 的原意是“插座”,在计算机通信领域,socket 被翻译为“套接字”,它是计算机之间进行通信的一种约定或一种方式。通过 socket 这种约定,一台计算机可以接收其他计算机的数据,也可以向其他计算机发送数据。为了与远程计算机进行数据传输,需要连接到因特网,而 socket 就是用来连接到因特网的工具。

    Socket起源于Unix,而Unix基本哲学之一就是“一切皆文件”,都可以用“打开open –> 读写write/read –> 关闭close”模式来操作。Socket就是该模式的一个实现,网络的Socket数据传输是一种特殊的I/O,Socket也是一种文件描述符。Socket也具有一个类似于打开文件的函数调用:Socket(),该函数返回一个整型的Socket描述符,随后的连接建立、数据传输等操作都是通过该Socket实现的。

    常用的Socket类型有两种:流式Socket(SOCK_STREAM)和数据报式Socket(SOCK_DGRAM)。流式是一种面向连接的Socket,针对于面向连接的TCP服务应用;数据报式Socket是一种无连接的Socket,对应于无连接的UDP服务应用。

    socket 的典型应用就是 Web 服务器和浏览器

    5.socket通信实例

    Linux 下的代码,server.cpp 是服务器端代码,client.cpp 是客户端代码,要实现的功能是:客户端从服务器读取一个字符串并打印出来。

    服务器端代码 server.cpp:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <arpa/inet.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    int main(){
        //创建套接字
        int serv_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        //将套接字和IP、端口绑定
        struct sockaddr_in serv_addr;
        memset(&serv_addr, 0, sizeof(serv_addr));  //每个字节都用0填充
        serv_addr.sin_family = AF_INET;  //使用IPv4地址
        serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");  //具体的IP地址
        serv_addr.sin_port = htons(1234);  //端口
        bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
        //进入监听状态,等待用户发起请求
        listen(serv_sock, 20);
        //接收客户端请求
        struct sockaddr_in clnt_addr;
        socklen_t clnt_addr_size = sizeof(clnt_addr);
        int clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size);
        //向客户端发送数据
        char str[] = "http://c.tesla.cn/socket/";
        write(clnt_sock, str, sizeof(str));
       
        //关闭套接字
        close(clnt_sock);
        close(serv_sock);
        return 0;
    }

    客户端代码 client.cpp:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <arpa/inet.h>
    #include <sys/socket.h>
    int main(){
        //创建套接字
        int sock = socket(AF_INET, SOCK_STREAM, 0);
        //向服务器(特定的IP和端口)发起请求
        struct sockaddr_in serv_addr;
        memset(&serv_addr, 0, sizeof(serv_addr));  //每个字节都用0填充
        serv_addr.sin_family = AF_INET;  //使用IPv4地址
        serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");  //具体的IP地址
        serv_addr.sin_port = htons(1234);  //端口
        connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
       
        //读取服务器传回的数据
        char buffer[40];
        read(sock, buffer, sizeof(buffer)-1);
       
        printf("Message form server: %s
    ", buffer);
       
        //关闭套接字
        close(sock);
        return 0;
    }

    6.使用socket函数实现套接字

    Linux 下的 socket() 函数

    在 Linux 下使用 <sys/socket.h> 头文件中 socket() 函数来创建套接字,原型为:

    int socket(int af, int type, int protocol);

    1) af 为地址族(Address Family),也就是 IP 地址类型,常用的有 AF_INET 和 AF_INET6。AF 是“Address Family”的简写,INET是“Inetnet”的简写。AF_INET 表示 IPv4 地址,例如 127.0.0.1;AF_INET6 表示 IPv6 地址,例如 1030::C9B4:FF12:48AA:1A2B。

    大家需要记住127.0.0.1,它是一个特殊IP地址,表示本机地址,后面的教程会经常用到。

    你也可以使用 PF 前缀,PF 是“Protocol Family”的简写,它和 AF 是一样的。例如,PF_INET 等价于 AF_INET,PF_INET6 等价于 AF_INET6。

    2) type 为数据传输方式/套接字类型,常用的有 SOCK_STREAM(流格式套接字/面向连接的套接字) 和 SOCK_DGRAM(数据报套接字/无连接的套接字)
    3) protocol 表示传输协议,常用的有 IPPROTO_TCP 和 IPPTOTO_UDP,分别表示 TCP 传输协议和 UDP 传输协议。

    有了地址类型和数据传输方式,还不足以决定采用哪种协议吗?为什么还需要第三个参数呢?

    正如大家所想,一般情况下有了 af 和 type 两个参数就可以创建套接字了,操作系统会自动推演出协议类型,除非遇到这样的情况:有两种不同的协议支持同一种地址类型和数据传输类型。如果我们不指明使用哪种协议,操作系统是没办法自动推演的。

    本教程使用 IPv4 地址,参数 af 的值为 PF_INET。如果使用 SOCK_STREAM 传输数据,那么满足这两个条件的协议只有 TCP,因此可以这样来调用 socket() 函数:

    int tcp_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);  //IPPROTO_TCP表示TCP协议

    这种套接字称为 TCP 套接字。

    如果使用 SOCK_DGRAM 传输方式,那么满足这两个条件的协议只有 UDP,因此可以这样来调用 socket() 函数:

    int udp_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);  //IPPROTO_UDP表示UDP协议

    这种套接字称为 UDP 套接字。

    上面两种情况都只有一种协议满足条件,可以将 protocol 的值设为 0,系统会自动推演出应该使用什么协议,如下所示:

    int tcp_socket = socket(AF_INET, SOCK_STREAM, 0);  //创建TCP套接字
    int udp_socket = socket(AF_INET, SOCK_DGRAM, 0);  //创建UDP套接字

     7.tcp的三次握手

    TCP建立连接时要传输三个数据包,俗称三次握手(Three-way Handshaking)。可以形象的比喻为下面的对话:

    • [Shake 1] 套接字A:“你好,套接字B,我这里有数据要传送给你,建立连接吧。”
    • [Shake 2] 套接字B:“好的,我这边已准备就绪。”
    • [Shake 3] 套接字A:“谢谢你受理我的请求。”
  • 相关阅读:
    Python
    Python
    Python
    Django REST framework
    Django REST framework
    Django REST framework
    Django REST framework
    jquery.unobtrusive-ajax.js的扩展,做到片段式加载
    jquery.unobtrusive-ajax.js单独的用法
    不复杂的Autofac注入
  • 原文地址:https://www.cnblogs.com/peteremperor/p/13920909.html
Copyright © 2020-2023  润新知