大白话说懂,“六字真诀”socket

我们看到的所有的通信软件和网络游戏,都必须要实现两个终端之间的网络通信,比如:

1.网页冲浪,是操作网页的人与网页部署的服务器通信;

2.王者荣耀,是10个玩家分别与游戏服务器两两通信,若当玩家1用技能,则玩家1的电脑先通过网络告诉服务器,服务器再告诉2345678910;

3.微信,是所有用户分别与微信服务器两两通信,服务器收到你发的消息,再转给其他人。

要在不同类型的主机不同类型的操作系统上实现网络通信,是件很麻烦的事情。

不过幸好,所有网络通信的协议都是一样的,都是基于这5层模型:

 

 

 

 大白话说懂,“六字真诀”socket大白话说懂,“六字真诀”socket

 

 

这5层对应的专业人员分别为:物理层、数据链路层、网络层->网络通信人员;传输层->内核程序员;应用层->应用程序员。

对于一个写应用软件的程序员来说,只需要关心“应用层”上的网络通信就可以了。为了实现网络通信,他们需要写一些“网络通信相关的代码”,这些代码就是socket。

一句话就是,socket让程序员实现网络通信变得简单

如果没有socket,这些程序员就不得不去关心“传输层”的实现,也就是说,他们要去研究内核相关的知识(linux内核,window内核,IOS内核)。

而有了socket,就轻松了,程序员只需要记住“六字真诀”--绑监受连发收

绑:服务器创建一个socket,绑定本机的IP地址和端口,代码 bind(address, port);

监:服务器监听有哪些客户端连上,代码 listen();

受:服务器开始等待接受客户端的连接,每接受一个便返回一个客户端的IP和端口,代码accept();

连:客户端通过IP和端口连接服务器,代码connect(address, port);

发:客户端和服务器连通后,可以相互发送信息,代码send(data);

收:客户端和服务器连通后,可以相互接收到对方发送的信息recv()。

有了socket,程序员在写代码时根本不需要关心像TCP三次握手这样的操作,因为它已经悄悄的隐匿在六字真诀中的里!

大白话说懂,“六字真诀”socket

 

 

socket和传输层、应用层的关系:

socket是一套api,并不属于传输层或应用层。简单来说,socket是传输层内核代码根据绑监受连发收“六字真诀”封装的一层接口;而应用层如Http,则是用socket实现的一套特殊通信机制。

 

下面是一个用python实现一个简单的本机服务器和客户端socket通信:

# server.py
import socket
import threading

def handle_client(c, addr):
    print(addr, "connected.")
    n = 0

    while True:
        # 接收
        data = c.recv(1024)
        if not data:
            break
        n = n + 1
        print(addr, n)  
        # 发送  
        c.sendall(data)

# 新建一个socket s,with是语法糖,当代码离开with时自动调用s.close()
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    # 绑定 0.0.0.0代表主机上的任意网卡
    s.bind(("0.0.0.0", 1234))
    # 监听
    s.listen()

# 简单版,单线程+接收一次数据
    # c, addr = s.accept()
    # data = c.recv(1024)
    # if not data:
    #         break
    #     n = n + 1
    #     print(addr, n)    
    #     c.sendall(data)

# 复杂版,多线程+一直接收数据
    while True:
        # 接受连接
        c, addr = s.accept()
        # 创建一个线程处理客户端连接
        t = threading.Thread(target=handle_client, args=(c, addr))
        t.start()
            
# client.py
import socket
import time
# 新建一个socket s,with是语法糖,当代码离开with时自动调用s.close()
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    # 连接
    s.connect(("127.0.0.1", 1234))

    # 简单版,发送一条数据
    s.sendall(b"Hello, Kael2")
    data = s.recv(1024)
    print("Received:", repr(data))

    # 复杂版,每个1秒发送一条数据
    # while True:
    #     s.sendall(b"Hello, Kael")
    #     data = s.recv(1024)
    #     print("Received:", repr(data))
    #     time.sleep(1)

分别运行server.py和client.py,就能实现一个简单的网络通信了。

 

参考资料:

https://www.cnblogs.com/zhang512/p/12096742.html

https://www.cnblogs.com/raoxinyue/p/12103966.html

https://www.bilibili.com/video/BV1eg411G7pW?spm_id_from=333.999.0.0

上一篇:STM32位带操作,实现类似51的GPIO功能---摘选自正点原子


下一篇:连接和协议:简单的web服务器