当前位置:首页 > 默认分类 > 正文内容

【Socket通信】关于Socket通信原理解析及python实现

virtualman6年前 (2018-08-02)默认分类2952

Socket(套接字)通信{网络通信其实就是Socket间的通信},首先了解下概念:【来源于百度百科】

1
"两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。"

可以这么说,Socket就是一个网络编程的接口(API),它定义了一种标准,并对TCP/IP进行封装,实现了网络传输数据的能力。

这篇文章默认您已经了解IP、端口等基本网络概念,如未了解,请移步:https://baike.baidu.com/item/IP/224599


我们想象这么一个场景,如果两个人,想要互相送一份礼物【用某风快递】,那么每个人都需要知道对方的什么信息?

  1. 地址【IP】:不然你让快递公司送到哪里?【不然你让互联网提供商把数据送到哪台电脑?】

  2. 姓名【端口】:一个地点不一定住一个人啊,快递小哥怎么知道要送给谁?【一台电脑不一定只有一个程序使用网络啊,系统怎么知道把数据传给哪个程序?】

再一点,快递公司有很多种,不一定非得选择某风快递,你也可以用某通快递、某达快递、某国邮政之类的,各有各的特点。在socket通信中也是这样,分为TCP、UDP两种。

TCP(Transmission Control Protocol,传输控制协议)是基于连接的协议,也就是说,在正式收发数据前,必须和对方建立可靠的连接

UDP(User Data Protocol,用户数据报协议)是与TCP相对应的协议。它是面向非连接的协议,它不与对方建立连接,而是直接就把数据包发送过去

关键词我已经标记出来了,配合上面的情景引入,可以很容易的理解。既然各有各的特色,那么根据生物学定理:“结构决定功能”,我们也很容易知道这俩东西肯定有不一样的地方。

TCP,由于是基于双方连接的情况下传输的,因此它的连接以及数据传输是非常稳定可靠的,可以使一台计算机发出的字节流完好无损的发生给另一台计算机。对要求可靠性非常高的应用程序会选择此种通信方式。

UDP,肯定是不太稳定的了,它适用于一次只传送少量数据、对可靠性要求不高的应用环境。其实我们常常使用的【ping】命令的工作原理就是向对方主机发送ICMP数据包【自行百度】,然后对方主机确认收到数据包,如果数据包是否到达的消息及时反馈回来,那么网络就是通的。对了,QQ的聊天功能大部分是用UDP来实现的,因为这样可以使得传输速率极快,但同时也会出现发生失败的情况,更极端的就是遇到掉包的情况。

另外,关于Socket通信还需理解的两对概念:长连接与短连接异步与同步【这个概念理解起来较难,但你可以先不理解,不会妨碍你实现小项目,在你实现完几个小项目后,再反过来看这块,你会有恍然大悟的感觉】

1、长连接 
       顾名思义,长连接就是连接时间更长的连接方式:连接——>传输数据——>等待——>传输数据…………——>结束
       Socket无论在是否使用都处于连接状态,虽然占用资源更小,但安全性较差。

2、短连接
        同样也是顾名思义,短连接就是连接时间更短的连接方式,但会多次连接:连接——>传输数据——>结束  连接——>传输数据…………——>结束
       SOCKET连接后发送后接收完数据后马上断开连接。

 

1、异步 
       报文发送和接收是分开的,相互独立的,互不影响。这种方式又分两种情况: 
       (1)异步双工:接收和发送在同一个程序中,由两个不同的子进程分别负责发送和接收 
       (2)异步单工:接收和发送是用两个不同的程序来完成。 

2、同步 
       报文发送和接收是同步进行,既报文发送后等待接收返回报文。 同步方式一般需要考虑超时问题,即报文发出去后不能无限等待,需要设定超时时间,超过该时间发送方不再等待读返回报文,直接通知超时返回。
       在长连接中一般是没有条件能够判断读写什么时候结束,所以必须要加长度报文头。读函数先是读取报文头的长度,再根据这个长度去读相应长度的报文。  

原谅我,同步异步实在没找到合适的图,我也实在想不出怎么来举栗子能让读者更好的理解。我个人经历是:做了个评测机【评测机和网站服务器间用socket传输数据】后才理解的。

下面我们就得了解这些快递公司到底如何实现交互的?

先看这个图,其实这个图就可以概括一切了,但是为了让大部分更好的理解,我再解释下的。

首先,客户端和服务端会分别新建一个socket,服务端的socket需要通过bind()来绑定上端口,启动listen()进行实时监听,并等待客户端的接入,即accept()。而客户端则需要通过服务器IP和端口两个参数来建立connect()连接,此时,服务器会得到有新客户端连接的信息,启动read()等待客户端数据的传人,客户端如果成功接收到服务端的连接成功后,继续执行write()来向服务端发生数据,同理,服务端也使用这样的模式回馈客户端的数据,知道客户端关闭,服务端会收到客户端退出连接的消息,服务器重新进入等待状态,等待新客户端的进入。

下面是用python写的示例,其他语言也都遵循上面的标准,C++采用的扩展库来实现的,在<WINSOCKET2>这个库中实现。

 1 import socket 
 2 #服务端 
 3 new_socket = socket.socket()         # 创建 socket 对象 
 4 ip = "127.0.0.1"          # 获取本地主机名 
 5 port = 52052                # 设置端口 
 6 new_socket.bind((ip, port))        # 绑定端口 
 7 new_socket.listen(5)                 # 等待客户端连接并设置最大连接数 
 8 while True: 
 9     new_cil, addr = new_socket.accept()     # 建立客户端连接。
 10     print('新进来的客户端的地址:', addr)
 11     print(new_cil.recv().decode())
 12     new_cil.send('答案为6')
 13     new_cil.close()                # 关闭连接
import socket#客户端
ip = "127.0.0.1"
port = 52052
new_socket = socket.socket()  #创建socket对象
new_socket.connect((ip,port))  #连接
new_socket.send("请求给我计算下1+5=多少?".encode(encoding='utf-8')) #发生数据
print("客户端发给服务端:请求给我计算下1+5=多少?") 
back_str = new_socket.recv().decode() #结束数据print("服务端发给客户端:"+back_str)
new_socket.close() #关闭客户端print("客户端结束运行")

人生苦短,我用python!隔壁C语言实现这个至少200行代码!


相关文章

【动态规划】基础背包问题

  1159. 背包问题一 (Standard IO) 时间限制: 1000 ms  空间限制: 262144 KB  具体限制   题目描述 有个背包可承受重量N,现有T件物品每件物品重量为...

【NOIP初赛 】哈夫曼树

【NOIP初赛 】哈夫曼树

根据我已刷的初赛题中基本每套的倒数第五或第六个不定项选择题就有一个关于哈夫曼树及其各种应用的题,占:0—1.5分;然而我针对这个类型的题也多次不会做,so,今晚好好研究下哈夫曼树;  概念:  给定n个权值作为n个叶子结点,构造一棵二叉树,若带权路径长度达到最小,称这样的二...

Python中的selenium库的基本用法

Selenium是一个用于测试网站的自动化测试工具,支持各种浏览器包括Chrome、Firefox、Safari等主流界面浏览器,同时也支持phantomJS无界面浏览器。通过此行代码可以快速在Python中安装selenium库pip install Selenium另外,我们仍需要安装浏览器驱动...

记录一次如何自己使用国外服务器搭建梯子

记录一次如何自己使用国外服务器搭建梯子

机缘巧合之下,租了一台亚马逊的美国服务器,想着这么大的服务器不能就跑一个业务吧,得利用起来,于是,就开始了搭建梯子之旅。 第一步:使用root账号登上ssh服务器。 第二步:执行一键搭建脚本: bash <(wget -qO- -o- https://git.io/v2ray.sh)...

【已解决】Window命令行报错:无法加载文件,因为在此系统上禁止运行脚本。

错误:无法加载文件 D:\Program Files\nodejs\tsc.ps1,因为在此系统上禁止运行脚本。有关详细信息,请参阅 https:/go.microsoft.com/fwlink/?LinkID=135170 中的 about_Execution_Policies。 解决方法:...

【PHP】大量 HTTP 请求调第三方接口,接口堵塞引起的 FD 耗尽(too many file open)问题

“FD耗尽”中的“FD”指的是“文件描述符”(File Descriptor)。在Unix和类Unix系统(如Linux)中,文件描述符是一个非负整数,用于标识一个进程打开的文件或其他输入/输出资源,比如网络套接字(socket...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。