(1)TCP和UDP协议说明
1.TCP协议和UDP协议区别
- 按对应的协议类型,端口有两种:TCP协议端口和UDP协议端口。由于TCP和UDP 两个协议是独立的,因此各自的端口号也相互独立,比如TCP有235端口,UDP也可以有235端口,两者并不冲突。
- 其实其他协议也有“端口”,但它们不称之为端口,而是称之为“协议号”,如IP协议号。
- TCP协议,是一种“连接方式”,是一种直接与接收方进行的连接,发送信息以后,需要确认信息是否到达,比如“三次握手”。
- UDP协议,“无连接方式”,不是直接与接收方进行连接,只管把信息放在网上发出去,而不管信息是否到达。
- 各自的特点:TCP更可靠,传输速度慢;UDP不可靠,速度快。
2.TCP协议常见端口
- FTP:文件传输协议,使用21号端口。常说某某计算机开了FTP服务便是启动了文件传输服务。下载文件,上传主页,都要用到FTP服务。
- Telnet:它是一种用于远程登录的端口,使用23号端口,用户可以以自己的身份远程连接到计算机上。
- SMTP:简单邮件传送协议,用于发送邮件,使用25号端口。
- POP3:与SMTP对应,用于接收邮件,通常情况使用110号端口。也是说,只要有相应的使用POP3协议的程序(例如Foxmail或Outlook),就可以不以Web方式登录进邮箱界面(如是163邮箱就没有必要先进入网易网站,再进入自己的邮箱来收信),直接用邮件程序就可以收到邮件。
3.UDP协议常见端口
- HTTP:这是大家用得最多的协议,就是常说的“超文本传输协议”。80号端口。常说的WWW服务、Web服务器用的是这个端口。
- DNS:用于域名解析服务,使用53号端口。互联网上的每一台计算机都有一个网络地址与之对应,这个地址是常说的IP地址,它以纯数字的形式表示。然而这却不便记忆,于是出现了域名,访问计算机的时候只需要知道域名。域名和IP地址之间的变换由DNS服务器来完成。
- SNMP:简单网络管理协议,使用161号端口,是用来管理网络设备的。由于网络设备很多,无连接的服务就体现出其优势。
4.udp可以不主动绑定地址和端口
udp客户端可以不主动绑定地址和端口:
①当UDP客户端调用sendto时,内核会根据外出接口给它绑定一个IP地址和一个临时端口号。
②当UDP客户调用connect,连接要发送消息的目的地址时,也会为UDP客户绑定了一个临时端口号和IP地址。
③UDP客户可以接收到达它绑定的临时端口的任何UDP数据报。
(2)python网络编程之socket编程
1.socket用法介绍
什么是 Socket?
Socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯。
socket()函数
Python 中,我们用 socket()函数来创建套接字,语法格式如下:
socket.socket([family[, type[, proto]]])
参数
• family: 套接字家族可以使AF_UNIX或者AF_INET
• type: 套接字类型可以根据是面向连接的还是非连接分为SOCK_STREAM或SOCK_DGRAM
• protocol: 一般不填默认为0.
Socket 对象(内建)方法
函数 |
描述 |
服务器端套接字 |
|
s.bind() |
绑定地址(host,port)到套接字, 在AF_INET下,以元组(host,port)的形式表示地址。 |
s.listen() |
开始TCP监听。backlog指定在拒绝连接之前,操作系统可以挂起的最大连接数量。该值至少为1,大部分应用程序设为5就可以了。 |
s.accept() |
被动接受TCP客户端连接,(阻塞式)等待连接的到来 |
客户端套接字 |
|
s.connect() |
主动初始化TCP服务器连接,。一般address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。 |
s.connect_ex() |
connect()函数的扩展版本,出错时返回出错码,而不是抛出异常 |
公共用途的套接字函数 |
|
s.recv() |
接收TCP数据,数据以字符串形式返回,bufsize指定要接收的最大数据量。flag提供有关消息的其他信息,通常可以忽略。 |
s.send() |
发送TCP数据,将string中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能小于string的字节大小。 |
s.sendall() |
完整发送TCP数据,完整发送TCP数据。将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常。 |
s.recvform() |
接收UDP数据,与recv()类似,但返回值是(data,address)。其中data是包含接收数据的字符串,address是发送数据的套接字地址。 |
s.sendto() |
发送UDP数据,将数据发送到套接字,address是形式为(ipaddr,port)的元组,指定远程地址。返回值是发送的字节数。 |
s.close() |
关闭套接字 |
s.getpeername() |
返回连接套接字的远程地址。返回值通常是元组(ipaddr,port)。 |
s.getsockname() |
返回套接字自己的地址。通常是一个元组(ipaddr,port) |
s.setsockopt(level,optname,value) |
设置给定套接字选项的值。 |
s.getsockopt(level,optname[.buflen]) |
返回套接字选项的值。 |
s.settimeout(timeout) |
设置套接字操作的超时期,timeout是一个浮点数,单位是秒。值为None表示没有超时期。一般,超时期应该在刚创建套接字时设置,因为它们可能用于连接的操作(如connect()) |
s.gettimeout() |
返回当前超时期的值,单位是秒,如果没有设置超时期,则返回None。 |
s.fileno() |
返回套接字的文件描述符。 |
s.setblocking(flag) |
如果flag为0,则将套接字设为非阻塞模式,否则将套接字设为阻塞模式(默认值)。非阻塞模式下,如果调用recv()没有发现任何数据,或send()调用无法立即发送数据,那么将引起socket.error异常。 |
s.makefile() |
创建一个与该套接字相关连的文件 |
2.UDP通信示例
# 发送消息:从一个ip地址的一个端口 → 另一个ip地址的一个端口
# 以虚拟的一个客户端到服务器端为例
# 这里是客户端先给服务器端发消息,所以要先打开服务器端
# 这样客户端发送消息和服务器端接受消息才能顺序,才不会报错
木马原理就是由于电脑被植入了一段程序,该程序打开了某个端口,接收到了另外一个端口发送来的消息,然后通过os.system(指令消息文本)等方式破坏电脑
UDP服务端
# UDP服务端
import socket # 网络通信 TCP UDP
import time
# 创建端口:创建一个服务器端
udpsever = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# socket.AF_INET表示网络通信,windows用AF_INET
# SOCK_DGRAM表示报文,采用udp协议
# 绑定指定的ip地址和端口
udpsever.bind(("127.0.0.1", 8848))
print("服务端启动成功,等待客户端连接")
while True:
try:
# 获取收到的消息,和地址(由ip和端口组成的元组)
data, addr = udpsever.recvfrom(1024)
# 1024表示缓冲区的大小,字节
# 缓冲区(Buffer)就是在内存中预留指定大小的存储空间用来对I/O的数据做临时存储,这部分预留的内存空间叫缓冲区。
# 可以减少实际物理读写次数,减少动态分配和回收内存的次数。
# 打印消息
print("来自", addr, "消息:", data.decode("utf-8"))
# os.system(data.decode("utf-8")) # 木马原理
# 回复消息
senddata = ("服务端于时间:" + str(time.time()) + " 已收到你的消息:" + data.decode("utf-8")).encode("utf-8")
udpsever.sendto(senddata, addr) # 发送数据倒指定的地址,这里是收到的消息的来源地址
except:
break
udpsever.close()
UDP客户端
# UDP客户端
import socket
# 创建客户端
udpclient = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 当客户端不绑定一个ip地址和端口时,系统会自动绑定当前ip地址和随机一个临时端口
print("客户端创建成功,准备向服务端发送消息")
while True:
try:
# 发送消息(方式一)
data = input("请输入消息:")
udpclient.sendto(data.encode("utf-8"), ("127.0.0.1", 8848)) # 发送消息到目的地址
# 发送消息(方式二)
#udpclient.connect(("127.0.0.1", 8848)) # 连接要发送的目的地址 # 元组,元素分别为要发送到的ip地址和端口
#udpclient.send(data.encode("utf-8")) # 发送消息
# 打印收到的消息
print(udpclient.recv(1024).decode("utf-8")) # 收到消息并打印
except:
break
udpclient.close()
3.TCP通信示例
先启动服务端,再启动客户端
TCP服务端
# TCP服务端
import socket
import time
import os
# 创建服务器端
SeverTCP = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 绑定ip和端口
SeverTCP.bind(("127.0.0.1", 9988))
# host = socket.gethostname() # 获取本地主机名
# print(host) # hhttt
# ip = socket.gethostbyname(host)
# print(type(ip), ip) # <class 'str'> 192.168.1.50
# port = 9999
# serversocket.bind((host, port)) # 绑定端口
# 设定最大连接数,即最多接收5个客户端,超过后排队
SeverTCP.listen(5)
# 返回接收到的客户端的链接和地址
clientsock, clientaddr = SeverTCP.accept()
while True:
try:
# 打印收到的消息
data = clientsock.recv(2014) # 缓冲区接收
print("收到来自", clientaddr, "消息:", data.decode("utf-8"))
# 根据该消息执行系统命令
os.system(data.decode("utf-8"))
# 回复消息
senddata = ("服务端于时间 " + str(time.time()) + " 收到你的消息:" + data.decode("utf-8") ).encode("utf-8")
clientsock.send(senddata)
except:
break
clientsock.close()
SeverTCP.close()#关闭
TCP 客户端
# TCP 客户端
import socket
# 创建客户端
clientTCP = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # SOCK_STREAM表示TCP,SOCK_DGRAAM表示UDP
# 绑定ip和端口
# 当客户端不绑定一个ip地址和端口时,系统会自动绑定当前ip地址和随机一个临时端口
# 连接别人的ip和端口
clientTCP.connect(("127.0.0.1", 9988)) # 连接目的地址的ip和端口 # 端口只要没有正在使用,就可以随便用
while True:
try:
# 发送消息
data = input("请输入消息:")
clientTCP.send(data.encode("utf-8"))
# 打印收到的消息
data, addr = clientTCP.recvfrom(1024) # 接收小于 1024 字节的数据
print("收到消息:", data.decode("utf-8"))
except:
break
clientTCP.close()
(3)常见问题解决办法
①客户端连接时出现【127.0.0.1由于目标积极拒绝,无法连接】
解决办法:一般是由于连接的服务器端口未正常启动导致的,通常若服务器端在该端口正常启动,是不会出现这个问题的,可以在命令提示符中用"netstat -an"查看对应端口是否启动和对应的进程,如果未找到该端口,说明未启动,需要先启动服务器。
参考:血与泪的教训:127.0.0.1由于目标积极拒绝,无法连接_由于目标计算机积极拒绝,无法连接127.0.0.1:5426-CSDN博客
②TCP连接出现“通常每个套接字地址(协议/网络地址/端口)只允许使用一次”错误
对于同一个端口,只能同时被一个服务端占用,如果该端口已经被占用,说明你的服务端已经启动起来,再次在这个端口启动,就会显示这个错误。
解决办法,关闭该端口对应进程后再启动服务端:
- 找到该端口的PID:cmd → netstat -aon → 查看PID;
- 在任务列表里面根据PID找到:cmd → tasklist → 根据PID找应用;
- 打开任务管理器,在详细信息那一栏,PID排序一下,根据PID找到对应的进程进行关闭。
③客户端和服务端在不同主机时端口不通解决办法
解决办法:开放自己电脑的对应端口供局域网内其他主机访问
参考:如何开放自己电脑的端口供局域网内其他主机访问_mac开放端口供局域网访问-CSDN博客
end