一、TCP协议

1. TCP协议的特点

    1.TCP是面向连接的运输层协议。这就意味着,在使用该协议之前,必须建立TCP连接。在传输数据完毕后,必须释放已经建立的TCP连接。

    2.每一条TCP连接只能有两个端点,每一条TCP连接只能是点对点的(一对一)。

    3.TCP提供可靠交付的服务。通过TCP连接传送的数据,无差错、不丢失、不重复、并且按序到达。

    4.TCP提供全双工通信。TCP允许通信双方的应用进程在任何时候都能发送数据。
TCP连接的两端都设有发送缓存和接收缓存,用来临时存放双向通信的数据。
在发送时,应用程序在把数据传送给TCP的缓存后,就可以做自己的事,而TCP在合适的时候把数据发出去。
在接收时,TCP把收到的数据放入缓存,上层的应用进程在合适的时候读取缓存中的数据。 5.面向字节流。虽然应用程序和TCP的交互试一次一个数据块(注意:大小是不等的),
但TCP把应用程序交下来的数据仅仅看成是一连串的无结构的字节流。TCP并不知道所传送的字节流的含义。

2.三次握手、四次挥手

3.代码实现

3.1 使用TCP协议实现简单通信
# 客户端:
import socket client = socket.socket()
client.connect(('127.0.0.1', 8080))
client.send(b"this is client!")
data = client.recv(1024)
print(data)
client.close() # 服务端:
import socket server = socket.socket() # 实例化sever对象-->买手机
server.bind(('127.0.0.1', 8080)) # 绑定ip和端口-->手机卡
server.listen(5) # 监听 -->打开手机
conn, addr = server.accept() # 等待建立连接
data = conn.recv(1024) # 接收数据 --> 打电话
print(data)
conn.send(b"received data!!")
conn.close() # 关闭连接-->挂电话
server.close() # 关闭服务器 -->关机
3.2 使用TCP协议实现通信循环
# 客户端:
import socket client = socket.socket()
client.connect(('127.0.0.1', 8080))
while True:
msg = input(">>>")
if msg == 'q':
break
client.send(msg.encode('utf-8'))
data = client.recv(1024)
print(data)
client.close() # 服务端
import socket server = socket.socket() # 实例化sever对象-->买手机
server.bind(('127.0.0.1', 8080)) # 绑定ip和端口-->手机卡
server.listen(5) # 监听 -->打开手机
conn, addr = server.accept() # 等待建立连接
while True:
try:
data = conn.recv(1024) # 接收数据 --> 打电话
print(data)
conn.send(b"received data!!")
except ConnectionResetError:
break
conn.close() # 关闭连接-->挂电话
server.close() # 关闭服务器 -->关机
3.3 使用TCP协议实现链接循环
# 客户端
import socket client = socket.socket()
client.connect(('127.0.0.1', 8080))
while True:
msg = input(">>>")
if msg == 'q':
break
client.send(msg.encode('utf-8'))
data = client.recv(1024)
print(data)
client.close() # 服务端
import socket server = socket.socket() # 实例化sever对象-->买手机
server.bind(('127.0.0.1', 8080)) # 绑定ip和端口-->手机卡
server.listen(5) # 监听 -->打开手机 (半连接池)
while True:
conn, addr = server.accept() # 等待建立连接
while True:
try:
data = conn.recv(1024) # 接收数据 --> 打电话
print(data.decode('utf-8'))
conn.send(b"received data!!")
except ConnectionResetError:
break
conn.close() # 关闭连接-->挂电话
server.close() # 关闭服务器 -->关机
3.4 使用TCP协议实现粘包问题
# 客户端
import socket
import struct
import json client = socket.socket()
client.connect(('127.0.0.1', 8090))
while True:
msg = input(">>>").encode('utf-8')
if len(msg) == 0:
continue
client.send(msg)
header = client.recv(4)
# 对头进行解包,获取真实数据的长度
head_len = struct.unpack('i', header)[0]
head_dic = json.loads(client.recv(head_len).decode('utf-8'))
print(head_dic)
# 对需要接收的数据进行循环接收
total_size = head_dic['len']
recv_size = 0
res = b''
while recv_size < total_size:
data = client.recv(1024)
res += data
recv_size += len(data)
print(res.decode("gbk")) # 服务端
import socket
import subprocess
import struct
import json server = socket.socket() # 实例化sever对象-->买手机
server.bind(('127.0.0.1', 8090)) # 绑定ip和端口-->手机卡
server.listen(5) # 监听 -->打开手机 (半连接池)
while True:
conn, addr = server.accept() # 等待建立连接
while True:
try:
data = conn.recv(1024).decode('utf-8') # 接收数据 --> 打电话
if len(data) == 0: break # 针对mac和Linux,客户端异常断开反复收空的情况 # 生成一个能够读取输出、错误流的对象
obj = subprocess.Popen(data, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout = obj.stdout.read() # 获得输出流
stderr = obj.stderr.read() # 获取错误流 # 打印输出流+输入流的长度
print(len(stdout+stderr))
# 制作一个文件头
header_dic = {
'filename': 'cls.avi',
'len': len(stderr+stdout) # 错误流 或者 输出流 的长度
} # 序列化文件头字典,得到文件头的二进制文件
header_bytes = json.dumps(header_dic).encode('utf-8') # 制作报头
header = struct.pack('i', len(header_bytes)) # 将要发送给客户端的数据打包成固定4个字节
conn.send(header)
conn.send(header_bytes)
conn.send(stdout+stderr) except ConnectionResetError:
break
conn.close() # 关闭连接-->挂电话 server.close() # 关闭服务器 -->关机
3.5 解决粘包问题用到的 struct
1.说明
struct模块中最重要的三个函数是pack(), unpack(), calcsize()
pack(fmt, v1, v2, ...) 按照给定的格式(fmt),把数据封装成字符串(实际上是类似于c结构体的字节流)
unpack(fmt, string) 按照给定的格式(fmt)解析字节流string,返回解析出来的tuple
calcsize(fmt) 计算给定的格式(fmt)占用多少字节的内存 struct中支持的格式如下表:
网址 : https://www.cnblogs.com/gala/archive/2011/09/22/2184801.html 2.代码实现(例子)
import struct
data = 'datafa'
# 服务端
res = struct.pack('i', len(data))
print(res) # b'\x06\x00\x00\x00'
print(len(res)) # 4
3.6 解决粘包问题用到的 subprocess
1.说明
subprocess 模块允许你生成新的进程,连接它们的输入、输出、错误管道,并且获取它们的返回码。 class subprocess.Popen(
args, bufsize=-1, executable=None,
stdin=None, stdout=None, stderr=None, preexec_fn=None,
close_fds=True, shell=False, cwd=None, env=None,
universal_newlines=None, startupinfo=None, creationflags=0,
restore_signals=True, start_new_session=False,
pass_fds=(), *, encoding=None, errors=None, text=None) 2.代码实现(例子):
cmd = r'dir file_list'
obj = subprocess.Popen(
cmd,
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
) stdout = obj.stdout.read() # 来接住stdout流
print('stdout', stdout.decode('gbk')) # 打印进程列表 stderr = obj.stderr.read()
print('stderr', stderr.decode('gbk')) # 当上面的命令出错时,接收错误流
# stderr 'tasklist1' 不是内部或外部命令,也不是可运行的程序或批处理文件。
# stdout 和 stderr同时存在的时候,有一个接收到了数据另一个就不会停止等待

二、UDP协议

1. UDP协议的特点

1.UDP是无连接的,即发送数据之前不需要建立连接(发送数据结束时也没有连接可释放),因此减少了开销和发送数据之前的时延。

2.UDP使用尽最大努力交付,即不保证可靠交付,因此主机不需要维持复杂的连接状态表。

3.UDP是面向报文的。发送方的UDP对应用程序交下来的报文,在添加首部后就向下交付IP层。UDP对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的边界。

4.UDP没有拥塞控制,因此网络出现的拥塞不会使源主机的发送速率降低。

5.UDP支持一对一,一对多,多对一和多对多的交互通信。

6.UDP的首部开销小,只有8个字节,比TCP的20个字节的首部要短。

2. 代码实现

2.1 使用UDP协议实现简单通信
# 客户端
import socket client = socket.socket(type=socket.SOCK_DGRAM)
data = b'this is client'
server_addr = ('127.0.0.1', 8080) client.sendto(data, server_addr)
data1, addr1 = client.recvfrom(1024) print(addr1)
print(data1)
# ('127.0.0.1', 8080)
# b'THIS IS CLIENT' # 服务端
import socket server = socket.socket(type=socket.SOCK_DGRAM) # udp协议
server.bind(('127.0.0.1', 8080)) while True:
data, addr = server.recvfrom(1024)
print(data)
data = data.decode('utf-8')
data = data.upper() server.sendto(data.encode('utf-8'), addr) # b'this is client'
2.2 使用UDP协议实现极简版QQ
# 客户端
import socket client = socket.socket(type=socket.SOCK_DGRAM)
server_addr = ('127.0.0.1', 8080) while True:
data = input(">>>:").strip()
client.sendto(data.encode('utf-8'), server_addr) msg, addr = client.recvfrom(1024)
print(msg.decode('utf-8')) # 服务端
import socket server = socket.socket(type=socket.SOCK_DGRAM)
server.bind(('127.0.0.1', 8080)) while True:
data, addr = server.recvfrom(1024)
print(addr)
print(data.decode('utf-8')) re_msg = input(">>>:")
server.sendto(re_msg.encode('utf-8'), addr)
2.3 socketServer模块可以使TCP通信达到并发效果
# 客户端
import socket client = socket.socket()
client.connect(('127.0.0.1', 8080)) while True:
msg = input(">>>:")
client.send(msg.encode('utf-8')) data = client.recv(1024)
print(data.decode('utf-8')) # 服务端
import socketserver server_addr = ('127.0.0.1', 8080) class MySock(socketserver.BaseRequestHandler):
def handle(self):
# 通信循环
while True:
data = self.request.recv(1024) # 接收数据
print(data.decode('utf-8'))
re_msg = input(">>>:")
self.request.send(re_msg.encode('utf-8')) if __name__ == '__main__':
server = socketserver.ThreadingTCPServer(server_addr, MySock)
server.serve_forever()

网络编程之 TCP-UDP的详细介绍的更多相关文章

  1. 4.Java网络编程之TCP/UDP

    常见传输协议: UDP , TCP UDP协议:    特点:         1.将数据及源和目的封装成数据包中,不需要建立连接         2.每个数据包的大小限制在64K内         ...

  2. 网络编程之TCP/UDP及其流程比较(转)

    TCP与UDP的区别 基于连接与无连接 对系统资源的要求(TCP较多,UDP少) UDP程序结构较简单 流模式与数据报模式TCP保证数据正确性,UDP可能丢包TCP保证数据顺序,UDP不保证 具体编程 ...

  3. java网络编程之TCP通讯

    java中的网络编程之TCP协议的详细介绍,以及如何使用,同时我在下面举2例说明如何搭配IO流进行操作, /* *TCP *建立连接,形成传输数据的通道: *在连接中进行大数据量传输: *通过三次握手 ...

  4. 网络编程之TCP编程

    网络编程之TCP编程 前面已经介绍过关于TCP协议的东西,这里不做赘述.Java对于基于TCP协议的网络通信提供了良好的封装,Java使用socket对象来代表两端的通信窗口,并通过Socket产生I ...

  5. Java网络编程之TCP、UDP

    Java网络编程之TCP.UDP 2014-11-25 15:23 513人阅读 评论(0) 收藏 举报 分类: java基础及多线程(28) 版权声明:本文为博主原创文章,未经博主允许不得转载.   ...

  6. [网络编程之Socket套接字介绍,套接字工作流程,基于TCP协议的套接字程序]

    [网络编程之Socket套接字介绍,套接字工作流程,基于TCP协议的套接字程序] 为何学习socket套接字一定要先学习互联网协议: 1.首先:要想开发一款自己的C/S架构软件,就必须掌握socket ...

  7. 网络编程之TCP/IP各层详解

    网络编程之TCP/IP各层详解 我们将应用层,表示层,会话层并作应用层,从TCP/IP五层协议的角度来阐述每层的由来与功能,搞清楚了每层的主要协议,就理解了整个物联网通信的原理. 首先,用户感知到的只 ...

  8. Python网络编程之TCP套接字简单用法示例

    Python网络编程之TCP套接字简单用法示例 本文实例讲述了Python网络编程之TCP套接字简单用法.分享给大家供大家参考,具体如下: 上学期学的计算机网络,因为之前还未学习python,而jav ...

  9. Java网络编程之TCP

    Java网络编程之TCP ​ TCP主要需要两个类:Socket和ServerSocket,Socket是客户端连接服务器时创建,参数需要指定服务器的ip和端口,ServerSocket是服务器端创建 ...

  10. 应聘复习基础笔记1:网络编程之TCP与UDP的优缺点,TCP三次握手、四次挥手、传输窗口控制、存在问题

    重要性:必考 一.TCP与UDP的优缺点 ①TCP---传输控制协议,提供的是面向连接.可靠的字节流服务.当客户和服务器彼此交换数据前,必须先在双方之间建立一个TCP连接,之后才能传输数据.TCP提供 ...

随机推荐

  1. python获取每日涨跌停股票统计,封闭时间和打开次数

    接口:limit_list 描述:获取每日涨跌停股票统计,包括封闭时间和打开次数等数据,帮助用户快速定位近期强(弱)势股,以及研究超短线策略. 限量:单次最大1000,总量不限制 积分:用户积2000 ...

  2. 好947 Mybatis 配置resultMap 带參数查询Map 注意selectOne数据库返回结果一条数据库 否则会报错

    //TMD 写几个demo 还有大站採集 <a target=_blank href="http://hao947.com/" target="_blank&quo ...

  3. 两分钟学会Unity3D布娃娃的使用

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/wangbin_jxust/article/details/28587233 在RPG游戏中,为了让人 ...

  4. 嵌套循环结合修改IFS环境变量遍历文件数据中IFS的修改一致性

    以下这个脚本使用了两个不同的IFS值来解析数据.第一个IFS值解析出/etc/passwd文件中的单独的行.内部for循环接着将IFS值改为冒号,云溪你从/etc/passwd的行中解析出单独的值. ...

  5. 浅析php-fpm和fastcgi的关系

    先讲讲CGI吧 浏览器向web server发起请求的时候,要有url,header,params等等吧,为什么有这些数据呢,这就是CGI的事了,CGI就规定了,传哪些数据,用什么样的格式传输 web ...

  6. 嵌入式平台 RAM与ROM区分

    ROM(Read Only Memory)和RAM(Random Access Memory)指的都是半导体存储器,ROM在系统停止供电的时候仍然可以保持数据,而RAM通常是在掉电之后就丢失数据,典型 ...

  7. Navicat定时 同步数据库

    转载:https://www.cnblogs.com/DFX339/p/11646812.html 我是用在了 mysql 和 sql server 数据同步(操作一模一样) 好文章,简单粗暴.适合我 ...

  8. 【精通css读书笔记】 第八章 布局

    学习了css布局的基础后又来翻阅<精通css>这本经典书籍,对布局有了进一步的认识. 基于浮动的布局 两列的布局仍然是使用一个元素向左浮动,一个元素向右浮动,值得注意的是要加入displa ...

  9. chroot 试用alpinelinux安装软件包的问题

    前边有说明使用chroot 体验alpinelinux,但是因为默认没有dns server,造成软件包无法下载 现象 问题原因 解决方法 copy host resolv.conf 到alpine ...

  10. Image另存为其他格式

    string imgPath = @"C:\ZHM01000001400001-01 青龙 白虎.tif"; Image img = Image.FromFile(imgPath) ...