我们看到的所有的通信软件和网络游戏,都必须要实现两个终端之间的网络通信,比如:
1.网页冲浪,是操作网页的人与网页部署的服务器通信;
2.王者荣耀,是10个玩家分别与游戏服务器两两通信,若当玩家1用技能,则玩家1的电脑先通过网络告诉服务器,服务器再告诉2345678910;
3.微信,是所有用户分别与微信服务器两两通信,服务器收到你发的消息,再转给其他人。
要在不同类型的主机不同类型的操作系统上实现网络通信,是件很麻烦的事情。
不过幸好,所有网络通信的协议都是一样的,都是基于这5层模型:
这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是一套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