Socket通信原理简介

作者: 人世间 | 来源:发表于2015-05-15 14:29 被阅读15667次

    何谓socket

    计算机,顾名思义即是用来做计算。因而也需要输入和输出,输入需要计算的条件,输出计算结果。这些输入输出可以抽象为I/O(input output)。

    Unix的计算机处理IO是通过文件的抽象。计算机不同的进程之间也有输入输出,也就是通信。因此这这个通信也是通过文件的抽象文件描述符来进行。

    在同一台计算机,进程之间可以这样通信,如果是不同的计算机呢?网络上不同的计算机,也可以通信,那么就得使用网络套接字(socket)。socket就是在不同计算机之间进行通信的一个抽象。他工作于TCP/IP协议中应用层和传输层之间的一个抽象。如下图:

    socket.jpg

    服务器通信

    socket保证了不同计算机之间的通信,也就是网络通信。对于网站,通信模型是客户端服务器之间的通信。两个端都建立一个socket对象,然后通过socket对象对数据进行传输。通常服务器处于一个无线循环,等待客户端连接:

    socket3.jpg

    socket 通信实例

    socket接口是操作系统提供的,调用操作系统的接口。当然高级语言一般也封装了好用的函数接口,下面用python代码写一个简单的socket服务端例子:

    server.py

    import socket
    
    HOST = 'localhost'      # 服务器主机地址
    PORT = 5000             # 服务器监听端口
    BUFFER_SIZE = 2048      # 读取数据大小
    
    # 创建一个套接字
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  
    # 绑定主机和端口
    sock.bind((HOST, PORT))
    # 开启socket监听
    sock.listen(5)
    
    
    print 'Server start, listening {}'.format(PORT)
    
    
    while True:
        # 建立连接,连接为建立的时候阻塞
        conn, addr = sock.accept()
        while True:
            # 读取数据,数据还没到来阻塞
            data = conn.recv(BUFFER_SIZE)
            if len(data):
                print 'Server Recv Data: {}'.format(data)
                conn.send(data)
                print 'Server Send Data: {}'.format(data)
            else:
                print 'Server Recv Over'
                break
        conn.close()
    sock.close()
    
    

    client.py

    import socket
    
    HOST = 'localhost'
    PORT = 5000
    BUFFER_SIZE = 1024
    
    # 创建客户端套接字
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 连接到服务器
    sock.connect((HOST, PORT))
    
    try:
        message = "Hello"
        # 发起数据给服务器
        sock.sendall(message)
        amount_received = 0
        amount_expected = len(message)
        while amount_received < amount_expected:
            # 接收服务器返回的数据
            data = sock.recv(10)
            amount_received += len(data)
            print 'Client Received: {}'.format(data)
    
    except socket.errno, e:
        print 'Socket error: {}'.format(e)
    except Exception, e:
        print 'Other exception: %s'.format(e)
    finally:
        print 'Closing connection to the server'
        sock.close()
    

    TCP 三次握手

    python代码写套接字很简单。传说的TCP三次握手又是如何体现的呢?什么是三次握手呢?

    • 第一握:首先客户端发送一个syn,请求连接,
    • 第二握:服务器收到之后确认,并发送一个 syn ack应答
    • 第三握:客户端接收到服务器发来的应答之后再给服务器发送建立连接的确定。

    用下面的比喻就是

    C:约么?

    S:约

    C:好的

    约会

    这样就建立了一个TCP连接会话。如果是要断开连接,大致过程是:

    tcp.png

    上图也很清晰的表明了三次握手的socket具体过程。

    1. 客户端socket对象connect调用之后进行阻塞,此过程发送了一个syn。
    2. 服务器内核完成三次握手,即发送syn和ack应答。
    3. 客户端socket对象收到服务端发送的应答之后,再发送一个ack给服务器,并返回connect调用,建立连接。
    4. 服务器socket对象接受客户端最后一次握手确定ack建立连接。
    5. 此时服务端调用accept,则从连接队列中将之前建立的连接取出返回。

    至此,客户端和服务器的socket通信连接建立完成,剩下的就是两个端的连接对象收发数据,从而完成网络通信。

    文中图片来源网络

    更多细节,可以阅读 TCP握手与socket通信细节

    相关文章

      网友评论

      • 龙少侠linux:写的很清晰 那几张图片很形象
      • diandiandidi:GoEasy web三步轻松实现web实时推送
        1. 引入goeasy.js
        2. 客户端订阅,
        Var goeasy = new GoEasy({appkey:’your appkey’});
        goeasy.subscribe(channel:”your channel”, onMessage:function(message){alert(‘received message’+ message.content)})
        3. 三种推送方式
        Javascript: goeasy.publish({channel:’your channel’, message:’your publish msg’});
        Java SDK: GoEasy goeasy = new GoEasy(“appkey”); goeasy.publish(“your channel”,”your msg”);
        RestAPI: https://goeasy.io/goeasy/publish
        三步轻松实现web推送及接收。官网:https://goeasy.io,文档齐全
      • terrylmay:其实博主的三次握手那个图并没有真正讲清楚握手的本质,只是讲了握手的流程!说明syn以及ack表示什么,以及为什么会有三次握手才是理解tcp的关键
        人世间:@terrylmay 确实如您所说 握手的细节和设计握手的初衷以及断开的方面都没有详细介绍 在我看来 这些内容可以单独拿出来再写一篇

      本文标题:Socket通信原理简介

      本文链接:https://www.haomeiwen.com/subject/hkfkqttx.html