目录:

    TCP流式协议

      TCP模板

      TCP聊天室

      TCP通信与连接循环

      TCP粘包

      socketserver实现并发

    UDP数据报协议

      UDP模板  

      UDP传输

      socketserver实现并发

TCP  可靠的传输
TCP传输数据前需要三次握手建立连接 UDP 不可靠传输
直接发送数据包,不关心对方是否接收成功

TCP传输:流式协议

TCP服务端:必须先启动服务端

import socket
# 1.创建一个代表服务器的socket对象
s = socket.socket() # 2.绑定端口号和IP地址
# 127.0.0.1 表示当前这个电脑的ip
address = ("127.0.0.1", 8080)
s.bind(address)
print("服务器已启动!") # 3.开始监听这个端口
# 5表示:可以有5个处于半连接状态的连接,即连接请求数,指的不是最大连接数
s.listen(5)
print("test") # 4.接受连接请求
# 该函数是阻塞的 会卡主程序的执行,必须等到有一个客户端进来才会继续执行
# 返回元组 第一个是代表客户端的socket对象 第二客户端的地址信息
conn, c_address = s.accept()
print("有一个连接已建立!")
print(c_address)
# 给客户端发送数据 # 5.读写数据
# 接受数据
res = conn.recv(1024)
print(res) # 6.关闭连接
s.close()

TCP客户端:建立连接之前一定要先启动服务端

import socket

# 1.创建客户端的socket对象
c = socket.socket() # 2.建立连接
c.connect("127.0.0.1",8080)
# 3.读写数据 
# 发送数据到服务器
c.send("hello i,m client!".encode("utf-8")) # 5.关闭连接 c.close()

TCP模板:

服务端:
 import socket

 server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

 server.bind(("127.0.0.1",9999))

 server.listen(5)

 while True:
c,addr = server.accept()
while True:
try:#window系统客户端关闭,会报错
msg = c.recv(1024).decode("utf-8")
if not msg:#规避Linux系统客户端异常关闭,会持续收空
c.close()
break
c.send(msg.upper().encode("utf-8"))
except BaseException:
print("客户端异常断开")
c.close()
break
server.close()
客户端:
 import socket

 client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

 client.connect(("127.0.0.1",9999))

 while True:
data = input(">>>:")
if not data:continue#规避发空
client.send(data.encode("utf-8"))
msg = client.recv(1024).decode("utf-8")
print(msg) client.close() 

UDP传输:数据报协议(数据不管是不是空,都会包含头信息)

UDP服务端:不用先启动

import socket
# 1.创建socket对象
s = socket.socket(type=socket.SOCK_DGRAM) # 2.绑定端口和ip
s.bind(("127.0.0.1",10000)) while True:
# 3.接受数据
res = s.recv(1024)
print(res)
while True:
msg = input(">>>:")
# 需要获取对方的ip和端口
# s.sendto(msg.encode("utf-8"), ("127.0.0.1", 10000)) # 4.关闭资源
s.close()

UDP客户端:不用建立连接,直接发就行,不在乎对方是否收到

import socket
# 1.创建socket对象
c = socket.socket(type=socket.SOCK_DGRAM)
while True:
msg = input(">>>:")#发空并不会卡住,因为数据包含报头,服务端接收到内容了
  #2.发送消息
c.sendto(msg.encode("utf-8"),("127.0.0.1",10000))
c.close()

UDP模板:

服务端:
 1 import socket
2
3 # 创建socket对象 指定type参数为socket.SOCK_DGRAM 表示使用UDP协议
4 server = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) # datagram数据报的意思
5 # 绑定ip和端口
6 server.bind(("127.0.0.1",8888))
7
8 while True:
9 # 接收数据 返回一个元祖 数据和 发送方的地址
10 msg,c_addr = server.recvfrom(1024)
11 print("收到来自%s: 说:%s" % (c_addr[0] ,msg.decode("utf-8")))
12 # 发送数据到指定ip和端口
13 server.sendto(msg.upper(),c_addr)
客户端:
1 import socket
2
3 client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # datagram数据报的意思
4
5 while True:
6 msg = input(">>>:")#UDP协议可以发空
7 client.sendto(msg.encode("utf-8"),("127.0.0.1",8888))
8 data,addr = client.recvfrom(1024)
9 print(data.decode("utf-8")) 

TCP简易聊天室:

服务器端:

import socket
server = socket.socket()
server.bind(("127.0.0.1",65535))
server.listen(5)
# 得到客户端的socket对象和客户端的地址
conn, c_address = server.accept() while True:
data = conn.recv(1024).decode("utf-8")
print("收到来自客户端的数据:",data)
# 如果对方发来一个over 我就关闭连接
if data == "over":
conn.close()
break
# 把对方传过来的数据转换为大写 在发回去!
conn.send(data.upper().encode("utf-8")) # 关闭服务器端
server.close()

客户端:

import socket
client = socket.socket() client.connect(("127.0.0.1",65535)) while True:
# 发送
client.send(input(">>>:").encode("utf-8")) # 接收
data = client.recv(1024).decode("utf-8")
print(data)
if len(data) == 0:
client.close()
break

TCP连接与通信循环:

服务端:

import socket
#1、买手机
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #tcp称为流式协议,udp称为数据报协议SOCK_DGRAM
# print(phone) #2、插入/绑定手机卡
# phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
phone.bind(('127.0.0.1',8080)) #3、开机
phone.listen(5) # 半连接池,限制的是请求数 #4、等待电话连接
print('start....')
while True: # 连接循环
conn,client_addr=phone.accept() #(三次握手建立的双向连接,(客户端的ip,端口))
# print(conn)
print('已经有一个连接建立成功',client_addr) #5、通信:收\发消息
while True: # 通信循环
try:
print('服务端正在等待收数据...')
data=conn.recv(1024) #最大接收的字节数,没有数据会在原地一直等待收,即发送者发送的数据量必须>0bytes
if len(data) == 0:break #在客户端单方面断开连接,服务端才会出现收空数据的情况.windows系统报错(所以捕捉异常).Linux进入死循环(Linux会收空)
print('来自客户端的数据',data)
conn.send(data.upper())
except ConnectionResetError:
break
#6、挂掉电话连接
conn.close() #7、关机
phone.close()

客户端:

import socket

#1、买手机
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# print(phone)
#2、拨电话
phone.connect(('127.0.0.1',8080)) # 指定服务端ip和端口 #3、通信:发\收消息
while True: # 通信循环
msg=input('>>: ').strip() #msg=''
if len(msg) == 0:continue #规避了发送数据为空
phone.send(msg.encode('utf-8'))
# print('has send----->')
data=phone.recv(1024)
# print('has recv----->')
print(data) #4、关闭
phone.close()

UDP传输:没有粘包,缓冲区要>数据包,<512

服务端:
 import socket

 server=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) #数据报协议-》udp
server.bind(('127.0.0.1',8080)) data,client_addr=server.recvfrom(1024) #b'hello'==>b'h'
print('第一次:',client_addr,data) data,client_addr=server.recvfrom(1024) #b'world' =>b'world'
print('第二次:',client_addr,data) data,client_addr=server.recvfrom(1024)
print('第三次:',client_addr,data) server.close() # 第一次: ('127.0.0.1', 52259) b'hello'
# 第二次: ('127.0.0.1', 52259) b'world'
# 第三次: ('127.0.0.1', 52259) b''
客户端:
 import socket

 client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) #数据报协议-》udp

 client.sendto('hello'.encode('utf-8'),('127.0.0.1',8080))
client.sendto('world'.encode('utf-8'),('127.0.0.1',8080))
client.sendto(''.encode('utf-8'),('127.0.0.1',8080)) #发空也可以传输,数据报协议,发送报头 client.close()

TCP用socketserver实现并发:

服务端:
 import socketserver
from threading import current_thread
# fork linux下一个多进程接口 windows没有这接口 # 用于处理请求的类
class MyHandler(socketserver.BaseRequestHandler):
def handle(self):
print(self)
print(self.server) # 获取封装的服务器对象
print(self.client_address)# 客户端地址
print(self.request)# 获取客户端的socket对象
print(current_thread())
#通讯循环
       while True:
data = self.request.recv(1024)
print(data.decode("utf-8"))
self.request.send(data.upper()) server = socketserver.ThreadingTCPServer(("127.0.0.1",9999),MyHandler)
server.serve_forever()# 代表连接循环
   # 循环建立连接,每建立一个连接就会启动一个线程(服务员)+调用Myhanlder类产生一个对象,调用该对象下的handle方法,专门与刚刚建立好的连接做通信循环
客户端1:
 import socket

 c = socket.socket()
c.connect(("127.0.0.1",9999)) while True:
msg = input(">>>:")
c.send(msg.encode("utf-8"))
print(c.recv(1024).decode("utf-8")) 
客户端2:
相同代码

图解:实现连接循环和通信循环

UDP用socketserver实现并发:

UDP本身可以实现并发,但是并发量大的情况下会变很慢

服务端:
ThreadingTCPServer
handler 在连接成功时执行
self.request 是客户端的socket对象 ThreadingUDPServer
handler 接收到数据时执行
self.request 数据和服务器端的socket对象  
 import socketserver
from threading import current_thread # fork linux下一个多进程接口 windows没有这接口
# 用于处理请求的类
class MyHandler(socketserver.BaseRequestHandler):
def handle(self):
       #通信循环,只有在客户端发来消息时才会得到client_address和request
print(self)
print(self.server) # 获取封装的服务器对象
print(self.client_address) # 客户端地址
print(self.request) # 是一个元祖 包含收到的数据 和服务器端的socket
# data,client = self.request data = self.request[0]
print(data.decode("utf-8"))
self.request[1].sendto(b"i am server", self.client_address) #self.request[1],拿到的是服务端的socket对象 server = socketserver.ThreadingUDPServer(("127.0.0.1", 9999), MyHandler)
server.serve_forever()
客户端1:产生一个线程
 import socket

 c = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
addr = ("127.0.0.1",9999) while True:
msg = input(">>>:")
c.sendto(msg.encode("utf-8"),addr) print(c.recvfrom(1024)[0].decode("utf-8")) 
客户端2:再产生一个线程
同上代码 

图解:实现通信循环

TCP和UDP的更多相关文章

  1. C++网络套接字编程TCP和UDP实例

    原文地址:C++网络套接字编程TCP和UDP实例作者:xiaojiangjiang 1.       创建一个简单的SOCKET编程流程如下 面向有连接的套接字编程 服务器: 1)  创建套接字(so ...

  2. 【校验】TCP和UDP的校验和

    一开始,私以为校验和只是简单的求和得到的结果,后来在TCP和UDP里面看到使用的校验和方式有点奇怪--二进制反码(循环进位)求和. 人类的认知过程必将从简单到复杂,看下这个二进制反码循环求和是啥子意思 ...

  3. 初入网络系列笔记(2)TCP和UDP

    一.借鉴说明,本博文借鉴以下博文 1.BlueTzar,TCP/IP四层模型, http://www.cnblogs.com/BlueTzar/articles/811160.html 2.叶剑峰,漫 ...

  4. 传输层协议TCP和UDP

    本文力图简洁,让读者对TCP和UDP有个初步的认知.闲话少说,现在开始吧.TCP和UDP都是传输层的协议.TCP通过三次握手建立可靠连接,对未送达的消息重新进行发送.UDP不建立连接而直接发送,对未送 ...

  5. 【Python网络编程】利用Python进行TCP、UDP套接字编程

    之前实现了Java版本的TCP和UDP套接字编程的例子,于是决定结合Python的学习做一个Python版本的套接字编程实验. 流程如下: 1.一台客户机从其标准输入(键盘)读入一行字符,并通过其套接 ...

  6. http、tcp、udp、OAUTH2.0网络协议区别

                    一.先来一个讲TCP.UDP和HTTP关系的 1.TCP/IP是个协议组,可分为三个层次:网络层.传输层和应用层. 在网络层有IP协议.ICMP协议.ARP协议.RAR ...

  7. TCP 三次握手四次挥手, ack 报文的大小.tcp和udp的不同之处、tcp如何保证可靠的、tcp滑动窗口解释

    一.TCP三次握手和四次挥手,ACK报文的大小 首先连接需要三次握手,释放连接需要四次挥手 然后看一下连接的具体请求: [注意]中断连接端可以是Client端,也可以是Server端. [注意] 在T ...

  8. OSI参考模型及各层功能,TCP与UDP的区别

    OSI参考模型:ISO/IEC 7498标准定义了网络互联的7层结构模型,即开放系统互连参考模型. OSI参考模型定义了开放系统的层次结构.层次之间的相互关系,以及各层所包括的可能的服务.OSI的服务 ...

  9. TCP与UDP的区别

    TCP与UDP的区别 TCP面向连接:UDP是无连接,即发送数据之前不需要建立连接 TCP提供可靠的服务,TCP连接传送的数据,无差错.不丢失.不重复,且按顺序到达:UDP尽最大努力交付,即不保证可靠 ...

  10. 基于socket的TCP和UDP编程

    一.概述 TCP(传输控制协议)和UDP(用户数据报协议是网络体系结构TCP/IP模型中传输层一层中的两个不同的通信协议. TCP:传输控制协议,一种面向连接的协议,给用户进程提供可靠的全双工的字节流 ...

随机推荐

  1. LeetCode算法题-Relative Ranks(Java实现)

    这是悦乐书的第248次更新,第261篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第115题(顺位题号是506).根据N名运动员的得分,找到他们的相对等级和得分最高的三个 ...

  2. 【Linux基础】查看硬件信息-CPU

    1.物理CPU数:计算机上实际配置的CPU个数. //查看计算机物理CPU个数(必须先sort后uniq) cat /proc/cpuinfo | grep "physical id&quo ...

  3. Offset Management For Apache Kafka With Apache Spark Streaming

    An ingest pattern that we commonly see being adopted at Cloudera customers is Apache Spark Streaming ...

  4. zabbix问题-非常少的网络故障失败或罕见:Proxy超时的问题

    解决方案 在zabbix_agentd.conf中添加这些. BufferSend = 10 BufferSize = 150 MaxLinesPerSecond = 100 Timeout = 29 ...

  5. 压力测试Apache

    在做类似商城秒杀系统的同事都知道要在支持高并发,高可用的环境下进行多次的压力测试来防止自己的项目结构被高额的点击量击穿,导致商品超卖等损失 介绍一款简单的软件 xampp xam里带了Apache服务 ...

  6. 在Bootstrap开发框架的工作流模块中实现流程完成后更新资料状态处理

    在开发查看流程表单明细的时候,在Web界面中,我们往往通过使用@RenderPage实现页面内容模块化的隔离,减少复杂度,因此把一些常用的如审批.撤销.会签.阅办等等的流程步骤都放到了通用处理的页面V ...

  7. HashMap 与 HashSet 联系

    HashMap实现 Map接口 HashSet实现Collection接口 HashSet底层是HashMap  好的 记住这个就可以了 HashSet只存放key, value:   private ...

  8. axios拦截器

    import axios from "axios"; axios.interceptors.response.use(response => { //=>设置响应拦截器 ...

  9. 给hMailServer添加DKIM图文教程

    https://www.hmailserver.org/viewtopic.php?f=4&t=12

  10. [转帖]内置系统账户:Local system/Network service/Local Service 区别

    内置系统账户:Local system/Network service/Local Service 区别 学习使用 xp_cmdshell 的时候 发现必须 sqlserver 的服务运行在local ...