前言
今天“出差在外”,晚上又琐事缠身,实在也没办法特别沉下心去学什么内容,但还是不希望一天一篇的flag就此倒下,只能多多参考别人的博客浅浅学习一下python的socket应用,后续课内做实验了,学习更深入的知识后,我会再补上自己的理解。
(11.4)已更新
Socket?
任何应用,比如浏览网页、刷抖音、微信聊天等等都是通过TCP/IP进行通讯的。
Socket是TCP/IP协议的一组封装,可以理解为是双方通信的接口。
Socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯。
就好似收发快递,收件人和寄件人并不需要知道中间快递是怎么传输的,只需要在意快递有没有发出去,有没有收到。中间具体的快递运输流程则是快递公司进行管理的。
对应到信息传输,Socket就相当于快递公司,起到一个中间承接的作用。
?目前的socket编程,使用的最多的是通过tcp协议进行网络通讯的。
常见的套接字对象方法和属性
名 称 | 描 述 |
---|
服务端 | 服务器套接字方法 | s.bind(ADDR) | 将地址(主机名、端口号对)绑定到套接字上 | s.listen([backlog]) | 设置并启动 TCP 监听器,如果指定backlog,则必须至少为0(如果低于0,则设置为0); | s.accept() | 被动接受 TCP 客户端连接,一直等待直到连接到达(阻塞) | 客户端 | 客户端套接字方法 | s.connect() | 主动发起 TCP 服务器连接 | s.connect_ex() | connect()的扩展版本,此时会以错误码的形式返回问题,而不是抛出一个异常 | 普通通用 | 普通的套接字方法 | s.recv() | 接收 TCP 消息 | s.recv_into() | 接收 TCP 消息到指定的缓冲区 | s.send() | 发送 TCP 消息 | s.sendall() | 完整地发送 TCP 消息 | s.recvfrom() | 接收 UDP 消息 | s.recvfrom_into() | 接收 UDP 消息到指定的缓冲区 | s.sendto() | 发送 UDP 消息 | s.getpeername() | 连接到套接字(TCP)的远程地址 | s.getsockname() | 当前套接字的地址 | s.getsockopt() | 返回给定套接字选项的值 | s.setsockopt() | 设置给定套接字选项的值 | s.shutdown() | 关闭连接 | s.close() | 关闭套接字 | s.detach() | 在未关闭文件描述符的情况下关闭套接字,返回文件描述符 | s.ioctl() | 控制套接字的模式(仅支持 Windows) | 阻塞 | 面向阻塞的套接字方法 | s.setblocking() | 设置套接字的阻塞或非阻塞模式 | s.settimeout() | 设置阻塞套接字操作的超时时间 | s.gettimeout() | 获取阻塞套接字操作的超时时间 | 文件方法 | 面向文件的套接字方法 | s.fileno() | 套接字的文件描述符 | s.makefile() | 创建与套接字关联的文件对象 | 属性 | 数据属性 | s.family | 套接字家族 | s.type | 套接字类型 | s.proto | 套接字协议 |
?C/S 双方通信流程
服务器端的基本流程:
1.初始化socket()
2.使用bind()绑定ip和端口号
3使用listen()监听消息
4.获取客户端的套接字地址accept()
5.使用recv()接收数据,send()发送数据与客户端进行交互
客户端的基本流程:
1.初始化socket()
2.使用ip和端口号connect()连接服务器
3.使用recv()接收数据,send()发送数据与服务器进行交互 ?
tcp三次握手为例:
服务端S进行socket.listen()时向服务端发起连接请求,第一次握手
客户端C进行socket.connect()时是客户端向服务端发送第一个报文的时候,第二次握手
服务端S进行socket.accpet()服务端响应,第三次握手
连接成功
代码演示
ps:UDP的端口好像只能使用一次
server.py
import socket #导入socket库
from time import ctime
import json
import time
HOST = ''
PORT = 9001
ADDR = (HOST, PORT)
BUFFSIZE = 1024 #定义一次从socket缓冲区最多读入1024个字节
MAX_LISTEN = 5 #表示最多能接受的等待连接的客户端的个数
def tcpServer():# TCP服务
# with socket.socket() as s:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:#AF_INET表示socket网络层使用IP协议,SOCK_STREAM表示socket传输层使用tcp协议
# 绑定服务器地址和端口
s.bind(ADDR)
# 启动服务监听
s.listen(MAX_LISTEN)
print('等待用户接入……')
while True:
# 等待客户端连接请求,获取connSock
conn, addr = s.accept()
print('警告,远端客户:{} 接入系统!!!'.format(addr))
# with conn:
while True:
print('接收请求信息……')
# 接收请求信息
data = conn.recv(BUFFSIZE) #读取的数据一定是bytes类型,需要解码成字符串类型
if not data:
break
info = data.decode()
# print('data=%s' % data)
print(f'接收数据:{info}')
# 发送请求数据
conn.send(f'服务端接收到信息{info}'.encode())
print('发送返回完毕!!!')
conn.close()
s.close()
# 创建UDP服务
def udpServer():
# 创建UPD服务端套接字
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
# 绑定地址和端口
s.bind(ADDR)
# 等待接收信息
while True:
print('UDP服务启动,准备接收数据……')
# 接收数据和客户端请求地址
data, address = s.recvfrom(BUFFSIZE)
if not data:
break
info = data.decode()
print(f'接收请求信息:{info}')
s.sendto(b'i am udp,i got it', address)
s.close()
if __name__ == '__main__':
while True:
choice = input('input choice t-tcp or u-udp:')
if choice != 't' and choice != 'u':
print('please input t or u,ok?')
continue
if choice == 't':
print('execute tcpsever')
tcpServer()
else:
print('execute udpsever')
udpServer()
client.py
import socket
from time import ctime
HOST = 'localhost'
PORT = 9001
ADDR = (HOST, PORT)
BUFFSIZE = 1024
def tcpClient():
# 创建客户套接字
with socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM) as s:
# 尝试连接服务器
s.connect(ADDR)
print('连接服务成功!!')
# 通信循环
while True:
inData = input('pleace input something:')
if inData == 'q':
break
# 发送数据到服务器
# inData = '[{}]:{}'.format(ctime(), inData)
s.send(inData.encode())
print('发送成功!')
# 接收返回数据
outData = s.recv(BUFFSIZE)
print(f'返回数据信息:{outData}')
# 关闭客户端套接字
s.close()
def udpClient():
# 创建客户端套接字
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
while True:
# 发送信息到服务器
data = input('please input message to server or input \'quit\':')
if data == 'quit':
break
data = '[{}]:{}'.format(ctime(), data)
s.sendto(data.encode('utf-8'), ADDR)
print('send success')
# 接收服务端返回信息
recvData, addrs = s.recvfrom(BUFFSIZE)
info = recvData.decode()
print(f'recv message : {info}')
# 关闭套接字
s.close()
if __name__ == '__main__':
while True:
choice = input('input choice t-tcp or u-udp or q-quit:')
if choice == 'q':
break
if choice != 't' and choice != 'u':
print('please input t or u,ok?')
continue
if choice == 't':
print('execute tcpsever')
tcpClient()
else:
print('execute udpsever')
udpClient()
可以在windows命令行界面输入命令检测端口是否被占用:netstat -an|find /i "端口号"?
可以看到9001是没有被占用的?
当运行server.py后
参考:
Python socket详解_Python 学习者的博客-CSDN博客_python socketSocket编程1.基本概念1.什么是客户端/服务器架构?服务器就是一系列硬件或软件,为一个或多个客户端(服务的用户)提供所需的“服务”。它存在唯一目的就是等待客户端的请求,并响应它们(提供服务),然后等待更多请求。说白了就是一个提供服务,一个请求服务得到相应的一个过程。2.套接字:通信端点套接字是计算机网络数据结构,它体现了上节中描述的“通信端点”的概念。在任何类型的通信开始之前,...https://blog.csdn.net/sinat_38682860/article/details/100039701
|