python-网络编程socket模块详解
# ### tcp 循环发消息 import socket
# 1.创建一个对象
sk = socket.socket()
sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
# 2.绑定ip,端口号,在网络上注册该主机
sk.bind( ("127.0.0.1",9004) )
# 3.监听端口
sk.listen() while True: # 4.建立三次握手
conn,addr = sk.accept()
# 5.收发数据的逻辑
# 该循环的作用:是循环发消息
while True:
# 接受消息
res = conn.recv(1024)
print(res.decode()) # 发送数据
strvar = input("请输入你要给对方的消息:")
conn.send(strvar.encode()) # 退出
if strvar == "q":
break # 6.四次挥手
conn.close()
# 7.退还端口
sk.close()
# ### tcp 客户端
import socket # 1.创建一个socket对象
sk = socket.socket() # 2.与服务器建立连接
sk.connect( ("127.0.0.1",9004) ) # 3.收发数据的逻辑 while True:
# 发送消息
strvar = input("请输入您要发送的消息:")
sk.send(strvar.encode())
# 接受消息
res = sk.recv(1024) if res == b"q":
break print(res.decode()) # 4.关闭连接
sk.close()
从上面的服务端与客户端我们可以知道,客户端无法单独存在,必须等待对应的服务端开启后才能与服务端开启通讯,而在TCP下的c/s模式下只能支持一客户端一服务器通话,而其他客户端连接进来无法做到实时通讯,必须等待前面的客户端断开连接后我才能与服务端交流,但同时也因为这个特性也早就了TCP下的传输数据稳定,不丢包等优点,缺点:速度慢连接拖拉
下面我们看看UDP下的socket是怎么样子的吧
服务端
# ### udp 服务端
import socket
# 1.创建一个socket对象
sk = socket.socket(type=socket.SOCK_DGRAM) # 2.绑定ip,端口号
sk.bind( ("127.0.0.1",9000) ) # 3.收发数据
# udp协议,如果作为服务器,第一次需要先接受消息,才能得到对方的ip和端口号
msg,cli_addr = sk.recvfrom(1024)
print(msg,cli_addr)
"""
b's9\xe6\x80\xbb\xe5\x86\xb3\xe8\xb5\x9b,lpl\xe5\x86\x8d\xe9\x80\xa0\xe8\xbe\x89\xe7\x85\x8c,\xe5\x87\xa4\xe5\x87\xb0\xe6\xb6\x85\xe6\xa7\x83' ('127.0.0.1', 53492)
"""
print(msg.decode()) # 发送数据给客户端
msg = "iG牛逼"
sk.sendto(msg.encode("utf-8"),cli_addr) # 4.关闭连接
sk.close()
客户端
# ### 客户端
import socket
# 1.创建socket对象
sk = socket.socket(type=socket.SOCK_DGRAM) # 2.收发数据
msg = "s9总决赛,lpl再造辉煌,凤凰涅槃"
# sendto(发送的二进制字节流消息,对方的ip和端口[元组])
sk.sendto(msg.encode("utf-8"),("127.0.0.1",9000)) # 接受数据
msg,addr = sk.recvfrom(1024)
print(msg.decode("utf-8"))
print(addr) # 3.关闭udp连接
sk.close
从上面我们可以看出,UDP协议下连接服务器时不会因为TCP的三次握手跟四次挥手而造成的连接拖沓,因为这个特点理论上可以同时又多个客户端同时连接服务器,而服务器可以同时给这些客户端提供服务,且不会理客户端的当前的连接状态,我只管发,但你收不收我不管,udp协议是基于这样的情况下运作的,那么UDP跟TCP的对比有啥优点呢?
快,不仅连接快,传输速度也快,但同时也造就了容易丢包,解决方法 创建缓存区,把数据一股气全部丢到缓存区里让客户端子去取,这样避免造成大面积丢包
这两种协议在传输数据时都存在黏包现象,为什么呢?
因为数据传输过程中服务端发送的太快,而客户端接收的太慢了,也就造成了数据黏包,从而造成数据紊乱,
解决这个问题有两个方案
(1)在服务端与客户端加延时可以避免黏包的现象发生
(2)把要传送的数据大小先发送给客户端,然后约定好每次发送多少,通过这样准确的发送与接收也可以避免黏包现象的发生
下面我通过代码来解释这个现象
# ### 黏包 服务端 import socket
import time
sk = socket.socket()
sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
# 在网络上注册该主机
sk.bind( ("127.0.0.1",9001) )
# 监听端口
sk.listen()
# 三次握手
conn,addr = sk.accept()
# 处理收发数据的逻辑 # 在真正第一次发送数据之前,把真实的数据长度先发过去
conn.send("".encode()) # 第一次发送
msg = "hello," * 20
conn.send(msg.encode())
# time.sleep(0.1)
# 第二次发送
conn.send("world".encode()) # 四次挥手
conn.close()
# 退还端口
sk.close()
# ### 客户端 import socket
import time
# 创建一个tcp对象
sk = socket.socket()
# 连接服务器
sk.connect( ("127.0.0.1",9001) ) time.sleep(0.2) # 接受发送过来的真实的数据长度
res = sk.recv(8)
num = int(res.decode("utf-8"))
# 处理收发数据逻辑
res1 = sk.recv(num) # hello,
res2 = sk.recv(1024) # world
print(res1)
print(res2)
# 关闭链接
sk.close()
这是通过延时接收隔离了黏包现象,简单点就是接收速度变慢了
不推荐这种用法,影响效率
下面第二种
# ### 客户端 import socket
import time
# 创建一个tcp对象
sk = socket.socket()
# 连接服务器
sk.connect( ("127.0.0.1",9001) ) time.sleep(0.2) # 接受发送过来的真实的数据长度
res = sk.recv(8)
num = int(res.decode("utf-8"))
# 处理收发数据逻辑
res1 = sk.recv(num) # hello,
res2 = sk.recv(1024) # world
print(res1)
print(res2)
# 关闭链接
sk.close()
# ### 客户端
import socket
import struct sk = socket.socket()
sk.connect( ("127.0.0.1",9000) ) # 处理收发数据的逻辑
# 接受第一次发送过来的长度
n = sk.recv(4)
tup = struct.unpack("i",n)
n = tup[0]
print(n,type(n)) # 接受第二次发送过来的真实数据
res1 = sk.recv(n)
print(res1.decode("utf-8")) res2 = sk.recv(1024)
print(res2.decode("utf-8"))
# 关闭链接
sk.close()
这种就是我上面说的那样,通过先计算文件大小然后在跟客户端商量好每次发多少给你客户端接收多少,即避免了黏包,又提升力了效率
python-网络编程socket模块详解的更多相关文章
- java网络编程Socket通信详解
Java最初是作为网络编程语言出现的,其对网络提供了高度的支持,使得客户端和服务器的沟通变成了现实,而在网络编程中,使用最多的就是Socket.像大家熟悉的QQ.MSN都使用了Socket相关的技术. ...
- python 网络编程--socket模块/struct模块
socket模块: 客户端:CS架构, client -> server 浏览器:BS架构, browser -> server 网络通信本质:传输字节 doc命令查看ip地址:ipc ...
- (转)python标准库中socket模块详解
python标准库中socket模块详解 socket模块简介 原文:http://www.lybbn.cn/data/datas.php?yw=71 网络上的两个程序通过一个双向的通信连接实现数据的 ...
- Java网络编程和NIO详解1:JAVA 中原生的 socket 通信机制
Java网络编程和NIO详解1:JAVA 中原生的 socket 通信机制 JAVA 中原生的 socket 通信机制 摘要:本文属于原创,欢迎转载,转载请保留出处:https://github.co ...
- Java网络编程和NIO详解开篇:Java网络编程基础
Java网络编程和NIO详解开篇:Java网络编程基础 计算机网络编程基础 转自:https://mp.weixin.qq.com/s/XXMz5uAFSsPdg38bth2jAA 我们是幸运的,因为 ...
- Java网络编程和NIO详解8:浅析mmap和Direct Buffer
Java网络编程与NIO详解8:浅析mmap和Direct Buffer 本系列文章首发于我的个人博客:https://h2pl.github.io/ 欢迎阅览我的CSDN专栏:Java网络编程和NI ...
- Java网络编程和NIO详解9:基于NIO的网络编程框架Netty
Java网络编程和NIO详解9:基于NIO的网络编程框架Netty 转自https://sylvanassun.github.io/2017/11/30/2017-11-30-netty_introd ...
- 铁乐学Python_Day33_网络编程Socket模块1
铁乐学Python_Day33_网络编程Socket模块1 部份内容摘自授课老师的博客http://www.cnblogs.com/Eva-J/ 理解socket Socket是应用层与TCP/IP协 ...
- Java网络编程和NIO详解7:浅谈 Linux 中NIO Selector 的实现原理
Java网络编程和NIO详解7:浅谈 Linux 中NIO Selector 的实现原理 转自:https://www.jianshu.com/p/2b71ea919d49 本系列文章首发于我的个人博 ...
随机推荐
- Redis学习二(数据操作).
key 操作 删除 key:del key 批量删除key:redis-cli -a(密码)keys "QXJ_*"| xargs redis-cli -a(密码)del 查看所有 ...
- Mysql - 高可用方案之MMM(二)
一.概述 上一篇博客中(https://www.cnblogs.com/ddzj01/p/11535796.html)介绍了如何搭建MMM架构,本文将通过实验介绍MMM架构的优缺点. 二.优点 1. ...
- Prometheus学习系列(一)之Prometheus简介
前言 本文来自Prometheus官网手册 和 Prometheus简介 什么是prometheus? Prometheus是一个最初在SoundCloud上构建的开源系统监视和警报工具包.自2012 ...
- python网络编程:UDP方式传输数据
UDP --- 用户数据报协议(User Datagram Protocol),是一个无连接的简单的面向数据报的运输层协议. UDP不提供可靠性,它只是把应用程序传给IP层的数据报发送出去,但是并不能 ...
- 新建GitHub仓库与删除
一.登录GitHub创建仓库 ,步骤如下: 1.点击新建 2.填写仓库名称等 3.创建完成 二.关联已有的本地项目(没有需要关联的本地项目,可以直接从刚刚创建的GitHub仓库clone) 1.到本地 ...
- JS基础语法---String对象下的方法(字符串的方法)
实例方法---->必须要通过new的方式创建的对象(实例对象)来调用的方法 静态方法---->直接通过大写的构造函数的名字调用的方法(直接通过大写的对象名字调用的) 字符串的常用属性: . ...
- Android utils 之 日志工具类
工具类 在开发的过程中,我们时常会对代码执行特定的处理,而这部分处理在代码中可能多次用到,为了代码的统一性.规范性等,通过建工具类的方式统一处理.接下来我会罗列各种工具类. 日志工具类 在utils文 ...
- C#后台架构师成长之路-基础体系篇章大纲
如下基础知识点,如果不熟透,以后容易弄笑话..... 1. 常用数据类型:整型:int .浮点型:double.布尔型:bool.... 2. 变量命名规范.赋值基础语法.数据类型的转换.运算符和选择 ...
- 11.2 Data Guard Physical Standby Switchover Best Practices using SQL*Plus (Doc ID 1304939.1)
11.2 Data Guard Physical Standby Switchover Best Practices using SQL*Plus (Doc ID 1304939.1) APPLIES ...
- js对象数组中的某属性值 拼接成字符串
js对象数组中的某属性值 拼接成字符串 var objs=[ {id:1,name:'张三'}, {id:2,name:'李四'}, {id:3,name:'王五'}, {id:4,name:'赵六' ...