目录:

    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. ASP.NET -- WebForm -- ScriptManager 类

    ASP.NET -- WebForm -- ScriptManager 类 通过 ScriptManager 可注册随后将作为页面一部分呈现的脚本. 1. 注册并立即执行脚本. --RegisterS ...

  2. topjui中datagrid增删改查

    1.掌握datagrid的创建方式在html中直接定义与在js中定义 可参考easyui的官方文档:http://www.jeasyui.net/plugins/183.html 2.实现代码如下:重 ...

  3. 在Windows下使用Git+TortoiseGit+码云管理项目代码

    1.      安装Git 下载地址:点击打开链接 安装指南:默认选项即可 2.      安装TortoiseGit 下载地址:点击打开链接 安装指南:点击打开链接 3.      在码云创建账号, ...

  4. 【入门】Spring-Boot项目配置Mysql数据库

    前言 前面参照SpringBoot官网,自动生成了简单项目点击打开链接 配置数据库和代码遇到的问题 问题1:cannot load driver class :com.mysql.jdbc.Drive ...

  5. SQL 撤销索引、表以及数据库

    通过使用 DROP 语句,可以轻松地删除索引.表和数据库. SQL DROP INDEX 语句 我们可以使用 DROP INDEX 命令删除表格中的索引. 用于 Microsoft SQLJet (以 ...

  6. [LeetCode] 9. 回文数

    题目链接:https://leetcode-cn.com/problems/palindrome-number/ 题目描述: 判断一个整数是否是回文数.回文数是指正序(从左向右)和倒序(从右向左)读都 ...

  7. Redtiger SQL注入练习(二)

    第六关: 点击 click me,构造url:user=1',返回user not found.user=1'',同样. 猜测是数字型注入,构造order by , user=1 order by  ...

  8. 以springMVC为例获取上传视频文件时长

    毕设项目是一个在线学习系统,教师用户有上传视频的功能,在答辩之前赶了一个demo出来,好多功能都写死了,比如课程学习进度就是被我写死在前端的一个变量,最近导师要我把项目打包发给他,这才心慌慌赶紧把这些 ...

  9. .net core2.1 三层中使用Autofac代替原来Ioc

    首先,现有的三层项目的结构 其中  Repository public interface IPersonRepository { string Eat(); } public class Perso ...

  10. openstack搭建之-cinder配置(12)

    一. base节点配置 mysql -u root -proot CREATE DATABASE cinder; GRANT ALL PRIVILEGES ON cinder.* TO 'cinder ...