Socket简介 与 UDP
1. Socket 简介
2. UDP
1. Socket 简介
网络编程,是指让在不同的电脑上的软件能够进行数据传递,即进程之间的通信。
本地的进程间通信(IPC)
例如有:队列、同步(互斥锁、条件变量等)等,这些通信方式都是一台机器上不同进程之间的通信方式。
网络中的进程间通信
首要解决的问题是如何唯一标识一个进程,否则通信无从谈起!
在本地可以通过进程PID来唯一标识一个进程,但是在网络中这是行不通的。
其实TCP/IP协议族已经帮我们解决了这个问题,网络层的“ip地址”可以唯一标识网络中的主机,而传输层的“协议+端口”可以唯一标识主机中的应用程序(进程)。
这样利用 IP 地址、协议、端口 就可以标识网络的进程了,网络中的进程通信就可以利用这个标志与其它进程进行交互。
Socket
Socket(简称套接字)是一个位于网络中特定节点的服务所具有的标识符,它包含了一个节点地址和一个端口号,用来标识这一服务。
套接字是进程间通信的一种方式,它与其他进程间通信的一个主要不同是:它能实现不同主机间的进程间通信,我们网络上各种各样的服务大多都是基于 Socket 来完成通信的。例如我们每天浏览网页、QQ 聊天、收发 email 等等。
创建 socket
在 python 中使用 socket 模块的函数 socket :
socket.socket(AddressFamily, Type)
函数 socket.socket 创建一个 socket,返回该 socket 的描述符,该函数带有两个参数:
- Address Family:可以选择 AF_INET(用于 Internet 进程间通信) 或者 AF_UNIX(用于同一台机器进程间通信),实际工作中常用 AF_INET。
- Type:套接字类型,可以是 SOCK_STREAM(流式套接字,主要用于 TCP 协议)或者 SOCK_DGRAM(数据报套接字,主要用于 UDP 协议)。
示例:
1 >>> import socket
2 >>> # 创建一个 TCP Socket
3 >>> tcp_s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
4 >>> tcp_s
5 <socket.socket fd=548, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0>
6 >>> # 创建一个 UDP Socket
7 >>> udp_s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
8 >>> udp_s
9 <socket.socket fd=620, family=AddressFamily.AF_INET, type=SocketKind.SOCK_DGRAM, proto=0>
2. UDP
2.1 UDP 介绍
UDP(User Data Protocol)——用户数据报协议,是一个无连接的、简单的、面向数据报的运输层协议。
特点
- 不具有可靠性的数据报协议。它只是把应用程序传给 IP 层的数据报发送出去,但是并不能保证它们能到达目的地,因此能否到达目的地,到达目的地的时间以及内容的正确性都是不能被保证的。
- 由于 UDP 在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,包数据顺序乱掉时也没有纠正的功能,再加上 UDP 本身的处理既简单又高效,故而传输速度很快。
- 将数据封装为数据包,每个数据报都是一个独立的信息,包括完整的源地址或目的地址,每个数据包的大小限制在 64K 中。
应用场景:注重速度流畅
UDP 是面向消息的协议,通信时不需要建立连接,数据的传输自然是不可靠的,UDP 一般用于多点通信和实时的数据业务,比如:
- 音视频等多媒体通信(即时通信,因为它们即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响)
- 广播通信(广播、多播)
- TFTP(简单文件传送)
- SNMP(简单网络管理协议)
- RIP(路由信息协议,如报告股票市场、航空信息)
- DNS(域名解释)
UDP 操作简单,而且仅需要较少的监护,因此通常用于局域网高可靠性的分散系统中 client/server 应用程序。例如视频会议系统,并不要求音频视频数据绝对的正确,只要保证连贯性就可以了,这种情况下显然使用 UDP 会更合理一些。
UDP 网络通信过程
2.2 UDP基础示例
发送、接收数据
创建一个 UDP 客户端程序的流程较为简单,具体步骤如下:
- 创建客户端套接字
- 发送/接收数据
- 关闭套接字
示例:UDP 发送方
1 import socket
2
3 # 1. 创建套接字
4 udpSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
5
6 # 2. 准备接收方的地址
7 sendAddr = ("192.168.3.4", 8080)
8
9 # 3. 从键盘获取要发送的数据
10 sendData = input("请输入要发送的数据:")
11
12 # 4. 发送数据到指定的电脑上
13 udpSocket.send(sendData.encode(), sendAddr)
14 # encode():将 str 转为 bytes。
15 # decode():将 bytes 转为 str。如我们从网络或磁盘上读取了字节流,那么读到的数据就是 bytes。
16
17 # 5. 等待接收方发送过来的数据
18 recvData = udpSocket.recv(1024) # 1024表示本次接收数据的最大字节数
19
20 # 6. 显示对方发送的数据
21 print(recvData)
22
23 # 7. 关闭套接字
24 udpSocket.close()
执行效果:
会变的端口号:
重新运行多次脚本,然后在“网络调试助手”中,看到的现象如下:
- 每重新运行一次网络程序,发送方的端口号会变化,不一样的原因在于,这个数字标识这个网络程序,当重新运行时,如果没有确定到底用哪个,系统默认会随机分配。
- 这个网络程序在运行的过程中,这个IP+端口号就唯一标识了这个程序,所以如果其他电脑上的网络程序如果想要向此程序发送数据,那么就需要向这个数字(即端口)标识的程序发送即可。
2.3 UDP 绑定信息
一般情况下,在一台电脑上运行的网络程序会有很多,而各自用的端口号很多情况下也不知道。为了不与其他的网络程序占用同一个端口号,往往在编程中,UDP 的端口号一般不绑定。
但是如果需要做成一个接收方的程序的话,是需要绑定的。正如如果报警电话每天都在变,想必世界就会乱了。所以一般服务性的程序,往往需要一个固定的端口号,这就是所谓的端口绑定。
示例:
1 import socket
2
3 # 创建套接字
4 udpSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
5
6 # 绑定本地的相关信息,如果一个网络程序不绑定,系统就会随机分配
7 binAddr = ("", 7788) # IP地址和端口号,IP一般不用写,表示本机的任何一个IP
8 udpSocket.bind(binAddr)
9
10 # 接收方的地址信息
11 sendAddr = ("192.168.234.1", 8080)
12
13 # 发送数据
14 sendData = udpSocket.sendto("haha".encode(), sendAddr)
15
16 # 等待接收方发送过来的数据
17 recvData = udpSocket.recvfrom(1024) # 1024表示本次接收数据的最大字节数
18
19 # 显示对方发送的数据
20 print(recvData)
21
22 # 关闭套接字
23 udpSocket.close()
执行效果:
2.4 UDP 小应用
应用 1:echo 服务器,即把接收的数据再发送回去
1 import socket
2 import time
3
4
5 # 创建套接字
6 udpSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
7
8 # 绑定本地的相关信息,如果一个网络程序不绑定,系统就会随机分配
9 binAddr = ("", 7788) # IP地址和端口号,IP一般不用写,表示本机的任何一个IP
10 udpSocket.bind(binAddr)
11
12 # 接收方的地址信息
13 sendAddr = ("192.168.234.1", 8080)
14
15 num = 1
16
17 def repeat():
18 # 等待对方发送来的数据
19 recvData = udpSocket.recvfrom(1024) # 1024即本次接收数据的最大字节数
20 # 将接收的数据再次发送回去
21 udpSocket.sendto(recvData[0], sendAddr)
22 # 统计信息
23 print("已经将接收到的第%d个信息返回给对方,数据内容为:%s" % (num, recvData[0].decode()))
24
25 # 若不使用 try..except... 重试机制,而会出现“远程主机强制关闭连接”的报错
26 while True:
27 try:
28 repeat()
29 except:
30 repeat()
31
32 # 关闭套接字
33 udpSocket.close()
注意,若出现“ConnectionResetError: [WinError 10054] 远程主机强迫关闭了一个现有的连接”:出现这种原因代表远程过于频繁,所以远程怀疑是恶意攻击。
可以使用 try...except...重试,在报错时重新调用该方法使其重新抓取,直至抓取成功。
执行效果:
应用 2:聊天室
模拟一个聊天室,显示所有接收到的数据。
1 import socket
2 import time
3
4
5 # 创建套接字
6 udpSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
7
8 # 绑定本地的相关信息,如果一个网络程序不绑定,系统就会随机分配
9 binAddr = ("", 7788) # IP地址和端口号,IP一般不用写,表示本机的任何一个IP
10 udpSocket.bind(binAddr)
11
12 # 接收方的地址信息
13 sendAddr = ("192.168.234.1", 8080)
14
15
16 def repeat():
17 # 等待对方发送来的数据
18 recvData = udpSocket.recvfrom(1024) # 1024即本次接收数据的最大字节数
19 # 打印消息记录
20 print("【%s】%s:%s"%(time.ctime(), recvData[1][0], recvData[0].decode()))
21
22
23 while True:
24 try:
25 repeat()
26 except:
27 repeat()
28
29
30 # 关闭套接字
31 udpSocket.close()
执行效果:
Socket简介 与 UDP的更多相关文章
- TCP Socket Establish;UDP Send Package Process In Kernel Sourcecode Learning
目录 . 引言 . TCP握手流程 . TCP connect() API原理 . TCP listen() API原理 . UDP交互过程 . UDP send() API原理 . UDP bind ...
- Android查缺补漏(IPC篇)-- 进程间通讯之Socket简介及示例
本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8425736.html 进程间通讯篇系列文章目录: Android查缺补漏(IP ...
- python的socket编程之udp编程
在上篇文章中,仅仅讲述了如何进行了TCP编程,在本章中,将讲述使用udp进行编码,先看如下的代码,服务器端: root@python 513]# cat serverudp.py #!/usr/bin ...
- (unix domain socket)使用udp发送>=128K的消息会报ENOBUFS的错误
一个困扰我两天的问题, Google和Baidu没有找到解决方法! 此文为记录这个问题,并给出原因和解决方法. 1.Unix domain socket简介 unix域协议并不是一个实际的协议族,而是 ...
- 网络编程(socket简介)
socket简介 Python 提供了两个基本的 socket 模块. 第一个是 Socket,它提供了标准的 BSD Sockets API. 第二个是 SocketServer, 它提供了服务器中 ...
- [深入浅出WP8.1(Runtime)]Socket编程之UDP协议
13.3 Socket编程之UDP协议 UDP协议和TCP协议都是Socket编程的协议,但是与TCP协议不同,UDP协议并不提供超时重传,出错重传等功能,也就是说其是不可靠的协议.UDP适用于一次只 ...
- socket 简介
对TCP/IP.UDP.Socket编程这些词你不会很陌生吧?随着网络技术的发展,这些词充斥着我们的耳朵.那么我想问: 1. 什么是TCP/IP.UDP?2. Sock ...
- 老李分享:使用 Python 的 Socket 模块开发 UDP 扫描工具
老李分享:使用 Python 的 Socket 模块开发 UDP 扫描工具 poptest是业内唯一的测试开发工程师培训机构,测试开发工程师主要是为测试服务开发测试工具,在工作中要求你做网络级别的安全 ...
- 网络编程—网络基础概览、socket,TCP/UDP协议
网络基础概览 socket概览 socket模块—TCP/UDP的实现 TCP/UDP总结 网络基础概览 osi七层协议各层主要的协议 # 物理层传输电信号1010101010 # 数据链路层,以太网 ...
随机推荐
- JVM相关 - 深入理解 System.gc()
本文基于 Java 17-ea,但是相关设计在 Java 11 之后是大致一样的 我们经常在面试中询问 System.gc() 究竟会不会立刻触发 Full GC,网上也有很多人给出了答案,但是这些答 ...
- 基于μcOS-II实时操作系统源码实现RMS和EDF调度(共享资源)
μcOS-II多任务实验报告(RMS.EDF调度) 目录 μcOS-II多任务实验报告(RMS.EDF调度) 一.实验概述 二.环境搭建 三.代码分析 四.实验步骤 1 给TCB块添加扩展 2 创建并 ...
- [数据结构与算法-13]ST表
ST表 主要用来快速查询静态数据区间最大值 思路 数组\(A[i][j]\)存储数列\(\{a_i\}\)中区间\(i \in [i, i+2^j)\)的最大值 查询时只需要查询\(max\{A[i] ...
- 《Asp.Net Core3 + Vue3入坑教程》 - Vue 1.使用vue-cli创建vue项目
简介 <Asp.Net Core3 + Vue3入坑教程> 此教程适合新手入门或者前后端分离尝试者.可以根据图文一步一步进操作编码也可以选择直接查看源码.每一篇文章都有对应的源码 目录 & ...
- css整理之-----------基本知识
盒子模型 所有HTML元素可以看作盒子,它包括:边距,边框,填充,和实际内容. CSS中组成一个块级盒子需要: Content box: 这个区域是用来显示内容,大小可以通过设置 width 和 he ...
- CMU15-455 Lab2 - task4 Concurrency Index -并发B+树索引算法的实现
最近在做 CMU-15-445 Database System,lab2 是需要完成一个支持并发操作的B+树,最后一部分的 Task4 是完成并发的索引这里对这部分加锁的思路和完成做一个总结,关于 B ...
- 一款检测代码中TODO的eslint插件
一款检测代码中TODO的eslint插件 前言 看了我标题进来的同学应该也知道我做的是个啥东西 没错是一个eslint插件,前端魔法师们日常所使用的工具之一 什么?你不知道eslint是干嘛的--吃鲸 ...
- 5行代码!完成bat病毒制作!!!
这个病毒的功能是删除当前目录下.cpp类型的代码. copy %0 "%userprofile%\AppData\Roaming\Microsoft\Windows\Start Menu\P ...
- P1014_Cantor表 (JAVA语言)
题目描述 现代数学的著名证明之一是Georg Cantor证明了有理数是可枚举的.他是用下面这一张表来证明这一命题的: 1/11/1 , 1/21/2 , 1/31/3 , 1/41/4, 1/51/ ...
- 面向对象进阶时,if语句写错位置
这周blog我也不知道要写什么,因为这章我其实学得有点懵,前面那几天我纠结了好久代码,一直不知道原因错在哪里.后来经过询问老师才知道自己调用错了构造方法,相信也有跟我一样的新手会犯这个错误.我在创建关 ...