第二十七天- 网络通信协议 TCP UDP 缓冲区

1.网络通信协议

  osi七层模型:按照分工不同把互联网协议从逻辑上划分了层级

  socket层

2.理解socket:

  Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。我们可理解成模块,直接拿来用。

套接字socket历史:

套接字起源于 20 世纪 70 年代加利福尼亚大学伯克利分校版本的 Unix,即人们所说的 BSD Unix。 因此,有时人们也把套接字称为“伯克利套接字”或“BSD 套接字”。一开始,套接字被设计用在同 一台主机上多个应用程序之间的通讯。这也被称进程间通讯,或 IPC。套接字有两种(或者称为有两个种族),分别是基于文件型的和基于网络型的。

  基于文件类型的套接字家族: 

  套接字家族的名字:AF_UNIX

  unix一切皆文件,基于文件的套接字调用的就是底层的文件系统来取数据,两个套接字进程运行在同一机器,可以通过访问同一个文件系统间接完成通信

  基于网络类型的套接字家族:

  套接字家族的名字:AF_INET

  AF_INET6被用于ipv6,还有一些其他的地址家族,不过,基本没用,所有地址家族中,AF_INET是使用最广泛的一 个 ,python支持多种地址家族,不过我们主要用网络编程,所以主要还是AF_INET

3.基于TCP和UDP两个协议下socket的通讯

  TCP(Transmission Control Protocol)可靠的、面向连接的协议(eg:打电话)、传输效率低全双工通信(发送缓存&接收缓存)、面向字节流。使用TCP的应用:Web浏览器;电子邮件、文件传输程序。

  UDP(User Datagram Protocol)不可靠的、无连接的服务,传输效率高(发送前时延小),一对一、一对多、多对一、多对多、面向报文,尽最大努力服务,无拥塞控制。使用UDP的应用:域名系统 (DNS);视频流;IP语音(VoIP)。

tcp协议下的socket:

  服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束

注意:tcp是基于链接的,必须先启动服务端,然后再启动客户端去链接服务端

基本代码:

server端

 1 import socket
 2 sk = socket.socket()
 3 sk.bind((‘127.0.0.1‘,8898))  #把地址绑定到套接字
 4 sk.listen()          #监听链接
 5 conn,addr = sk.accept() #接受客户端链接
 6 ret = conn.recv(1024)  #接收客户端信息
 7 print(ret)       #打印客户端信息
 8 conn.send(b‘hi‘)        #向客户端发送信息
 9 conn.close()       #关闭客户端套接字
10 sk.close()        #关闭服务器套接字(可选)

client端

1 import socket
2 sk = socket.socket()           # 创建客户套接字
3 sk.connect((‘127.0.0.1‘,8898))    # 尝试连接服务器
4 sk.send(b‘hello!‘)
5 ret = sk.recv(1024)         # 对话(发送/接收)
6 print(ret)
7 sk.close()            # 关闭客户套接字

相关bug:

1.socket绑定IP和端口时可能出现下面的问题:不让重复使用端口

 1 #加入一条socket配置,重用ip和端口
 2 import socket
 3 from socket import SOL_SOCKET,SO_REUSEADDR
 4 sk = socket.socket()
 5 sk.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #在bind前加,允许地址重用
 6 sk.bind((‘127.0.0.1‘,8898))  #把地址绑定到套接字
 7 sk.listen()          #监听链接
 8 conn,addr = sk.accept() #接受客户端链接
 9 ret = conn.recv(1024)   #接收客户端信息
10 print(ret)              #打印客户端信息
11 conn.send(b‘hi‘)        #向客户端发送信息
12 conn.close()       #关闭客户端套接字
13 sk.close()        #关闭服务器套接字(可选)

View 解决办法 Code

若任然报错,出现 OSError: [WinError 10013] 以一种访问权限不允许的方式做了一个访问套接字的尝试。那么只能换端口了,因为你的电脑不支持端口重用。

2.远程主机强迫关闭了一个先有连接

这是由于强制断开造成的,解决很简单,谁依赖于谁,先关掉依赖者,再关闭被依赖者就好;还有一种是和多个连接造成,tcp协议下最好一对一,一对多可见下面代码。

 1 import socket
 2
 3 server = socket.socket()
 4 ip_port = (‘127.0.0.1‘,8081)
 5 server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)  # 固定写法,允许地址重用,若还报错OSerror,系统原因,改端口
 6
 7 server.bind(ip_port)
 8 server.listen()  # 监听 可跟参数 n 代表监听n+1次 如,listen(3),意思是我连接着一个,后面还有3排队,共4个.
 9
10 while 1:
11     conn,addr = server.accept()  # 阻塞等待连接
12     while 1:
13         server_msg = input(‘>>>>> ‘)
14         server_msg = server_msg.encode(‘utf-8‘)
15         conn.send(server_msg)  # 发消息
16         if server_msg == ‘byebye‘:  # 多个客户端连接时,结束前一个后,跳出当前循环到上一个while,重新获得连接
17             break
18
19         from_client_msg = conn.recv(1024)  # 接消息
20         from_client_msg = from_client_msg.decode(‘utf-8‘)
21         if from_client_msg == ‘byebye‘:
22             break
23         print(‘来自客户端的消息:‘,from_client_msg)
24     conn.close()

View 一对多_服务端 Code

 1 import socket
 2
 3 client = socket.socket()
 4 server_ip = (‘127.0.0.1‘,8081)
 5 client.connect(server_ip)
 6
 7 while 1:
 8     from_server_msg = client.recv(1024)
 9     from_server_msg = from_server_msg.decode(‘utf-8‘)
10     print(‘来自服务器>>>‘,from_server_msg)
11     if from_server_msg == ‘byebye‘:
12         break
13
14     client_msg = input(‘>>>>> ‘)
15     client_msg = client_msg.encode(‘utf-8‘)
16     client.send(client_msg)
17     if client_msg == ‘byebye‘:
18         break
19
20 client.close()

View 一对多_客户端 Code

 1 # 再来一份即可
 2 import socket
 3
 4 client = socket.socket()
 5 server_ip = (‘127.0.0.1‘,8081)
 6 client.connect(server_ip)
 7
 8 while 1:
 9     from_server_msg = client.recv(1024)
10     from_server_msg = from_server_msg.decode(‘utf-8‘)
11     print(‘来自服务器>>>‘,from_server_msg)
12     if from_server_msg == ‘byebye‘:
13         break
14
15     client_msg = input(‘>>>>> ‘)
16     client_msg = client_msg.encode(‘utf-8‘)
17     client.send(client_msg)
18     if client_msg == ‘byebye‘:
19         break
20
21 client.close()

View 一对多_客户端01 Code

总结:用socket进行通信,必须是一收一发对应好。

udp协议下的socket

  服务器端先初始化Socket,然后与端口绑定(bind),recvform接收消息,这个消息有两项,消息内容和对方客户端的地址,然后回复消息时也要带着你收到的这个客户端的地址,发送回去,最后关闭连接,一次交互结束。

注意:udp是无链接的,启动服务之后可以直接接受消息,不需要提前建立链接,但在发消息时要跟上地址。

基本 代码:

server端

1 import socket
2 udp_sk = socket.socket(type=socket.SOCK_DGRAM)   #创建一个服务器的套接字
3 udp_sk.bind((‘127.0.0.1‘,9000))        #绑定服务器套接字
4 msg,addr = udp_sk.recvfrom(1024)
5 print(msg)
6 udp_sk.sendto(b‘hi‘,addr)                 # 对话(接收与发送)
7 udp_sk.close()                         # 关闭服务器套接字

client端:

1 import socket
2 ip_port=(‘127.0.0.1‘,9000)
3 udp_sk=socket.socket(type=socket.SOCK_DGRAM)
4 udp_sk.sendto(b‘hello‘,ip_port)
5 back_msg,addr=udp_sk.recvfrom(1024)
6 print(back_msg.decode(‘utf-8‘),addr)

4.练习代码:

#  用户登录作业用tcp协议下的socket写:#  1. 服务端#     - 等待客户端来发送数据:用户名、密码#     - 本地文件中查看用户名密码是否合法。#     - 合法:登录成功#     - 否则:用户名或密码错误

#  2. 客户端#     - 用户输入:用户名、密码#     - 发送到服务端进行校验。

 1 import socket
 2 import time
 3
 4 server = socket.socket()
 5 ip_port = (‘127.0.0.1‘,8083)
 6 server.bind(ip_port)
 7 server.listen()
 8 conn,addr = server.accept()  # 等待conn
 9
10 dic = {‘张三‘:‘123‘,‘赵四‘:‘345‘,‘王八‘:‘567‘}
11
12 client_msg = conn.recv(1024)
13 client_msg = client_msg.decode(‘utf-8‘)  # 还原成字典
14 client_msg = eval(client_msg)
15 print(client_msg)
16 time.sleep(5)
17
18 for k in dic:
19     if {k:dic[k]} == client_msg:
20         conn.send(‘登录成功!‘.encode(‘utf-8‘))
21     else:
22         conn.send(‘用户名或密码错误!‘.encode(‘utf-8‘))

View 服务端 Code

 1 import socket
 2
 3 client = socket.socket()
 4 server_ip = (‘127.0.0.1‘,8083)
 5 client.connect(server_ip)
 6
 7 k = input(‘请输入账户:‘)
 8 v = input(‘请输入密码:‘)
 9 # 存入字典,发送给服务端
10 msg = {k:v}
11 client.send(str(msg).encode(‘utf-8‘))
12
13 from_server_msg = client.recv(1024)
14 print(from_server_msg.decode(‘utf-8‘))

View 客户端 Code

# udp协议下的socket聊天工具(类10086)#  1. 服务端#     - 接收客户端发送的信息并作出回复。#     - 检查是否有某些指定关键字并回复消息,如果发送过来的消息中还有sb字符串,那么将sb替换成alexsb,然后和你要输入的内容组合起来发送给客户端。#  2. 多个客户端#     - 客户端向服务端发送信息

 1 import socket
 2
 3 talk_server = socket.socket(type=socket.SOCK_DGRAM)
 4 ip_port = (‘127.0.0.1‘,8086)
 5 talk_server.bind(ip_port)
 6
 7 while 1:
 8     from_client_msg,addr = talk_server.recvfrom(1024)
 9     from_client_msg = from_client_msg.decode(‘utf-8‘)
10     print(‘来自客户端>>>‘,from_client_msg)
11     if from_client_msg == ‘byebye‘:
12         break
13
14     msg = input(‘>>> ‘)
15     if ‘sb‘in from_client_msg:
16         msg2 = from_client_msg.replace(‘sb‘, ‘alexsb‘)
17         talk_server.sendto((msg+msg2).encode(‘utf-8‘),addr)
18     else:
19         talk_server.sendto(msg.encode(‘utf-8‘), addr)
20
21 talk_server.close()

View 服务端 Code

 1 # udp下复制多个以下代码即可实现多客户端
 2
 3 import socket
 4
 5 talk_client = socket.socket(type=socket.SOCK_DGRAM)
 6 server_ip_port = (‘127.0.0.1‘,8086)
 7
 8 while 1:
 9     msg = input(‘>>>‘)
10     if msg == ‘byebye‘:
11         break
12     msg = msg.encode(‘utf-8‘)
13     talk_client.sendto(msg,server_ip_port)
14
15     from_server_msg,addr = talk_client.recvfrom(1024)
16     print(‘来自服务端>>>‘,from_server_msg.decode(‘utf-8‘))
17
18 talk_client.close()

View 客户端 Code

continue...

  

原文地址:https://www.cnblogs.com/xi1419/p/10005240.html

时间: 2024-07-29 05:01:26

第二十七天- 网络通信协议 TCP UDP 缓冲区的相关文章

python 网络通信协议/TCP,UDP区别

一.osi七层协议 互联网协议按照功能不同分为osi七层或tcp/ip五层或tcp/ip四层 协议具体内容 各层的功能简述: [1]物理层:主要定义物理设备标准,如网线的接口类型.光纤的接口类型.各种传输介质的传输速率等.它的主要作用是传输比特流(就是由1.0转化为电流强弱来进行传输,到达目的地后在转化为1.0,也就是我们常说的数模转换与模数转换),这一层的数据叫做比特. [2]数据链路层:定义了如何让格式化数据以进行传输,以及如何让控制对物理介质的访问,这一层通常还提供错误检测和纠正,以确保数

菜鸟学python第二十七天(网络协议)

网络协议 网络通信的基本要素 物理介质 网络协议 OSI七层模型 OSI五层 应用层 传输层 : TCP/UDP协议,传输层为每个需要联网的应用程序绑定了一个私人端口号(一个整数,最大65585) 注意:0-1024是系统保留的端口,不要使用已经占用的端口(apache:8080,MySQL:3306,FTP:21) 网络层 : IP协议,子网掩码,IP与子网掩码进行AND运算,产生网络地址, 如果网络地址一致,则表明在同一个子网络(局域网). IP协议包含路由协议,帮助找到局域网的网关. 数据

python 学习5 网络编程-TCP/UDP

摘抄自:廖雪峰的官方网站:http://www.liaoxuefeng.com/ TCP客户端和服务器端代码: #coding=utf-8 #客户端程序TCP 连接 import socket s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) s.connect(('127.0.0.1',9999)) print(s.recv(1024)) for data in ['Michael','Tracy','Sarah']: s.send(data

linux网络编程--tcp/udp编程模型

tcp 模型如下: 上面的模型已经很清楚了 具体函数用法就不细说了 请看tcp简单的例子: 其中server.c #include <stdio.h>#include <string.h>#include <stdlib.h>#include <sys/socket.h>#include <sys/types.h>#include <netinet/in.h>#include <arpa/inet.h> #define e

网络通信协议 udp tcp

四 网络通信协议(互联网协议) 第二天再讲这里,大家第二天再看这里把~~~ 网络通信协议是网络传输的灵魂,非常重要,协议即准则,准则是传输消息的格式要求,那么我们从电脑上发出一个消息,到底是以什么样的消息格式发到了对方的手上呢,来看一看这里>>>,网络通信协议 五 osi七层模型 互联网的核心就是由一堆协议组成,协议就是标准,标准就是大家都认可的,所有人都按照这个来,这样大家都能够互相了解,互相深入了~~~比如全世界人通信的标准是英语 五层通信流程: 六 socket 结合上图来看,so

网络通信协议下的 TCP(三次握手,四次挥手) 和 UDP socket 套接字

osi七层模型 互联网的核心就是由一堆协议组成,协议就是标准,标准就是大家都认可的,所有人都按照这个来,这样大家都能够互相了解,互相深入了~~~比如全世界人通信的标准是英语 五层通信流程: tcp协议:(TCP把连接作为最基本的对象,每一条TCP连接都有两个端点,这种端点我们叫作套接字(socket),它的定义为端口号拼接到IP地址即构成了套接字,例如,若IP地址为192.3.4.16 而端口号为80,那么得到的套接字为192.3.4.16:80.) 当应用程序希望通过 TCP 与另一个应用程序

TCP与UDP收发的时候TCP有缓冲区还是UDP有缓冲区,使用它们时该注意什么?

问题:TCP与UDP收发的时候TCP有缓冲区还是UDP有缓冲区,使用它们时该注意什么? (一)基础 1.TCP为可靠链接,分三次握手四次释放. 2.UDP为不可靠链接 (二)TCP与UDP的输出每 个TCP套接口有一个发送缓冲区,可以用SO_SNDBUF套接口选项来改变这一缓冲区的大小.当应用进程调用write往套接口写数据时,内核从应用进 程缓冲区中拷贝所有数据到套接口的发送缓冲区,如果套接口发送缓冲区容不下应用程序的所有数据,或者是应用进程的缓冲区大于套接口的发送缓冲区,或者是套 接口的发送

网络编程—网络基础概览、socket,TCP/UDP协议

网络基础概览 socket概览 socket模块-TCP/UDP的实现 TCP/UDP总结 网络基础概览 osi七层协议各层主要的协议 # 物理层传输电信号1010101010 # 数据链路层,以太网协议,arp协议.对这些信号进行分组,同时规范了分组形式--以太网协议,头部是mac地址中间是信息, # 网络层:ip协议,arp协议帮忙找到mac地址,ip,子网掩码,网关(下面有一些简单概括) # 传输层:tcp协议,udp协议 # (socket)就是一组接口,将复杂的tcp协议和udp协议隐

[网络] SOCKET, TCP/UDP, HTTP, FTP

(一)TCP/UDP,SOCKET,HTTP,FTP简析 TCP/IP是个协议组,可分为三个层次:网络层.传输层和应用层: 网络层:IP协议.ICMP协议.ARP协议.RARP协议和BOOTP协议 传输层:TCP协议与UDP协议 应用层:FTP.HTTP.TELNET.SMTP.DNS等协议 HTTP是应用层协议,其传输都是被包装成TCP协议传输.能够用SOCKET实现HTTP. SOCKET是实现传输层协议的一种编程API,能够是TCP.也能够是UDP. (二)Socket连接与HTTP连接差