传输模型与套接字

传输模型

基本模型

image.png

层次划分

image.png

网络协议

网络协议是不同计算机间为了进行数据交换而建立的规则,是通信计算机双方必须共同遵从的一组约定。如怎么样建立连接、怎么样互相识别等。只有遵守这个约定,计算机之间才能相互通信交流。


image.png

基本模型

image.png
注意点
  • 我们在程序里面能操作最低的层次就是传输层
  • 互联网数据传输主要用两个协议:TCP和UDP
  • HTTP协议不涉及数据包的传输,仅仅规定了客户端和服务器之间的通信格式
  • HTTP协议是应用层的协议,是基于传输层的TCP协议来工作的

TCP连接

建立连接(三次握手)

image.png

传输数据

image.png

断开连接(四次挥手)

image.png

IP地址和端口

IP地址

所谓的IP地址就是给每个连接互联网上的主机分配一串数字当作地址,按照TCP/IP规定,每个IP地址长32bit,分为4段,用十进制数字表示,段与段之间用点号隔开。


image.png

IP地址 = 网络号+主机号, 通过网络号的不同分为了五大类IP地址,
这是一个历史的概念,在实际中已经没有意义了,我们了解一下就好


image.png

私有(内网)IP地址

  • IPv4地址协议中预留了3个IP地址段,作为私有地址,供内部组网使用;
  • 私有地址可以自己组网时用,但不能在外网上用;
  • 这些地址的计算机要上网必须转换成为合法的IP地址,也就是公网地址;


    image.png

端口

  • 端口用来唯一标识应用程序
  • 每个应用程序都占了一个端口,一个端口同时只能被一个程序使用
  • 共有65535个端口


    image.png

套接字socket

socket是计算机网络通信的基本的技术之一。如今大多数基于网络的软件,如浏览器,即时通讯工具甚至是P2P下载都是基于Socket实现的。�
网络上两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket,应用程序通过socket向网络中发出消息,或者接收消息。

socket是应用层与TCP/IP协议族的中间抽象层,它是一组接口,把复杂的TCP/IP协议族封装为几个简单的接口提供给应用层调用,实现程序在网络中的通信

socket仅仅是一个调用接口,为了方便程序员针对TCP或者UDP编程的接口。

socket

image.png

socket七个方法

image.png

image.png

注意:

  • 服务端是通过accept生成的对等连接套接字来和客户端通信的
  • accept和recv是会阻塞的,当没有数据来的时候阻塞等数据过来。
    服务端通过accept接受客户端连接请求,没有请求则处于阻塞状态,知道客户端通过connect来连接。recv也是阻塞直到客户端send数据过来。

代码示例

  1. 写一个不断接受(while True)用户连接的服务端,它的作用是把客户端发来的数据原封不动的返回。写一个客户端来测试上面的服务端。
    服务端:
import socket

server_socket = socket.socket()  # 创建一个套接字,默认使用IPV4和TCP
server_socket.bind(('0.0.0.0', 7001))  # 绑定ip和端口(注意这里是元组)到套接字,4个0表示任何地址可以访问
server_socket.listen(5)  # 服务器监听客户端请求,将服务器套接字变为被动套接字监听模式。不能再发送数据了,由后面产生新的套接字进行数据交互。

print('等待客户端的到来.....')
new_client_socket, address= server.accept()  # 接受客户端连接,程序会默认进入阻塞状态(等待客户端连接),如果客户端连接后,自动解除阻塞,会自动向下继续执行。
# 会返回形如(new_client_socket, address)的元组,new_client_socket新的套接字对象,用于与相应客户端端进行数据交互,只服务当前客户端,address客户端地址((hostname,port)的元组),

print('来自{}的请求'.format(address))

while True:
    data = new_client_socket.recv(1024)  # 接受数据,返回的是字节码,1024个字符,recv会让程序再次阻塞,收到消息后再解除阻塞。

    print('接受的数据:{}'.format(data.decode())) # 进行解码
    if not data:   #如果客户端断开了,则会不断的循环,所以需要判断处理
        print('data is lose')
        new_client_socket.close()  # 关闭和当前客户端的连接
        break

new_client_socket.send(data) # 发送数据,要求以字节码格式,可以用b'string'或者encode()对字符串进行编码

server_socket.close()  #  服务器不再接受新的客户端连接,老客户端可以继续服务。

客户端:

import socket

client = socket.socket()
client.connect(('127.0.0.1', 7001))

while True:
    message = input('请输入内容>>').strip()  # 去掉前后空格
    if len(message) == 0:
        continue
    client.send(message.encode())  # 需要发送字节
    data = client.recv(1024)  # 1024个字符
    print(data.decode())  # 接受的是字节,需要解码成字符串

client.close()
image.png

总结:这是一个能一直保持连接的程序,因为上面的步骤只是最基本的用法,所以想要能一直连接的程序,就需要使用while True保持循环,还有一个问题就是,此程序只能连接一个客户端,并不能支持多并发,所以当出现第二个客户端时,就会出现挂起不动,所以想要完成多个连接,下篇涉及到。

通过TCP实现文件下载

服务器

# 1. 导入模块
import socket
# 2. 创建socket
tcp_server_socket = socket.socket()
# 3. 绑定端口
tcp_server_socket.bind(("0.0.0.0", 8004))
# 4. 设置监听,设置套接字由主动变为被动
tcp_server_socket.listen(128)
print('开始监听....')
# 5. 接受客户端连接
new_client_socket, address = tcp_server_socket.accept()
print('欢迎新客户端:', address)
# 6. 接收客户端发送的文件名
file_name = new_client_socket.recv(1024).decode()
print('文件名:{}'.format(file_name))
# 7. 根据文件名读取文件内容
try:    
    with open(file_name, 'rb') as f:  # 发送也是需要按字节码形式,所以这里用rb
        # 8. 把读取的文件内容发送给客户端(循环)
        while True:
            file_data = f.read(1024)
            # 判断是否读取到文件末尾
            if file_data:
                new_client_socket.send(file_data)
            else:
                break
except Exception as e:
    print('文件%s下载失败'%file_name)
else:
    print('文件%s下载成功' %file_name)

# 9. 关闭和当前客户的连接
new_client_socket.close()
# 10. 关闭服务器
tcp_server_socket.close()

客户端

# 导入模块
import socket

# 2. 创建套接字
tcp_client_socket = socket.socket()
# 3. 建立连接
tcp_client_socket.connect(('127.0.0.1', 8004))
# 4.接受用户输入的文件名
file_name = input('请输入要下载的文件名:\n')
# 5.发送文件名到服务器
tcp_client_socket.send(file_name.encode())
# 6. 创建文件,并且准备保存
with open('download/'+ file_name, 'wb') as f:
    # 7. 接受服务端发送的数据,保存到本地(循环)
    while True:       
        file_data = tcp_client_socket.recv(1024)
        # 判断数据是否传送完毕
        if file_data:
            f.write(file_data)
        else:
            break

# 8. 关闭套接字
tcp_client_socket.close()
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,752评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,100评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,244评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,099评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,210评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,307评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,346评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,133评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,546评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,849评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,019评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,702评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,331评论 3 319
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,030评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,260评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,871评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,898评论 2 351

推荐阅读更多精彩内容