socket 套接字的使用:

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

server 端

import socket
sk = socket.socket() # 实例化一个socket的sk对象
sk.bind(('127.0.0.1', 10010)) # 设置IP和端口号
sk.listen() # 监听链接
conn, addr = sk.accept() # 接收客户端链接 conn.send('你好'.encode()) # conn.send(b'alex') 向客户端发送信息
# 如果服务器是发送,客户端要对应使用接收
ret = conn.recv(1024).decode() # 接收客户端信息
# 服务器是接收,客户端要对应发送
print(ret) # 打印客户端信息
conn.close() # 关闭客户端套接字
sk.close() # 关闭服务器套接字

client 端

import socket
sk = socket.socket() #实例化一个socket的sk对象
sk.connect(('127.0.0.1', 10010)) # 设置ip和端口号,必须和服务器端相同
ret = sk.recv(1024).decode() #接收时要设置长度
print(ret) # 打印接收的信息
sk.send('我好'.encode()) # 发送信息给服务器端
sk.close()

UDP 链接:

server端

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

client端

import socket
ip_port=('127.0.0.1',9000)
udp_sk=socket.socket(type=socket.SOCK_DGRAM)
udp_sk.sendto(b'hello',ip_port)
back_msg,addr=udp_sk.recvfrom(1024)
print(back_msg.decode('utf-8'),addr)

带退出功能的聊天

# server端:
import socket
sk = socket.socket()
sk.bind(('127.0.0.1', 11111))
sk.listen()
conn, addr = sk.accept()
while True:
msg = input('>>>: ')
conn.send(msg.encode())
if msg == 'q': break
ret = conn.recv(1024).decode()
if ret == 'q':break
print(ret)
conn.close()
sk.close() # client端
import socket
sk = socket.socket()
sk.connect(('127.0.0.1', 11111))
while True:
ret = sk.recv(1024).decode()
print(ret)
if ret == 'q': break
msg1 = input('>>>>: ')
sk.send(msg1.encode())
if msg1 == 'q': break
sk.close()

同步服务器时间:

#  server 端:

import socket
import time
sk = socket.socket()
sk.bind(('127.0.0.1', 10010))
sk.listen()
conn, addr = sk.accept()
ret = conn.recv(1204).decode()
str_time = time.strftime(ret)
conn.send(str_time.encode())
conn.close()
sk.close() # client端
import socket
sk = socket.socket()
sk.connect(('192.168.13.50', 10010))
time_type = '%Y-%m-%d'
sk.send(time_type.encode('utf-8'))
msg = sk.recv(1024)
print(msg)
sk.close()

黏包:

只有TCP有粘包现象,UDP永远不会粘包

# 发送一个 ‘hello’, 然后在发送一个‘world’
# 接收方接收到的是‘helloworld’
# 这就叫黏包

发送到的黏包

接收端的黏包

1.发送端的粘包  合包机制 + 缓存区
2.接收端的粘包 延迟接受 + 缓存区

总结

黏包现象只发生在tcp协议中:

1.从表面上看,黏包问题主要是因为发送方和接收方的缓存机制、tcp协议面向流通信的特点。

2.实际上,主要还是因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的

黏包的解决方法:

# 告诉客户端,你发送的数据长度
# server端

import struct
import socket sk = socket.socket()
sk.bind(('127.0.0.1',9000))
sk.listen() conn,addr = sk.accept()
send_msg = input('>>>').encode()
bytes_len = struct.pack('i', len(send_msg))
conn.send(bytes_len)
conn.send(send_msg) # 粘包现象
conn.send(b'world')
conn.close()
sk.close()
# client 端

import struct
import socket sk = socket.socket()
sk.connect(('127.0.0.1',9000))
bytes_len = sk.recv(4)
msg_len = struct.unpack('i',bytes_len)[0]
msg = sk.recv(msg_len)
print(msg.decode())
msg2 = sk.recv(5)
print(msg2)
sk.close()

补充:

1.两个连续的send就会发生粘包
2.用struct自定义协议可以解决粘包问题
3.什么情况下我们不需要解决粘包 : 文件的传输
4.自定义协议的进阶版本
先发送字符串的长度,再发送字符串
先发送json的长度,再发送json,json的字典中包含着下一条信息的长度,然后按照长度接收

day 24 socket 黏包的更多相关文章

  1. python学习之socket&黏包

    7.4 socket ​ [重要] 避免学习各层的接口,以及协议的使用, socket已经封装好了所有的接口,直接使用这些接口或者方法即可,方便快捷,提升开发效率. socket在python中就是一 ...

  2. struct解决socket黏包问题 (指令传输)

    服务端代码如下 import struct import subprocess import socket server = socket.socket() server.bind(()) serve ...

  3. socket之黏包

    一.黏包成因 1.tcp协议的拆包机制 当发送端缓冲区的长度大于网卡的MTU时,tcp会将这次发送的数据拆成几个数据包发送出去. MTU是Maximum Transmission Unit的缩写.意思 ...

  4. Python Socket通信黏包问题分析及解决方法

    参考:http://www.cnblogs.com/Eva-J/articles/8244551.html#_label5 1.黏包的表现(以客户端远程操作服务端命令为例) 注:只有在TCP协议通信的 ...

  5. python socket编程和黏包问题

    一.基于TCP的socket tcp是基于链接的,必须先启动服务端,然后再启动客户端去链接服务端,有顺序,不重复,可靠.不会被加上数据边界. server端 import socket sk = so ...

  6. python基础(30):黏包、socket的其他方法

    1. 黏包 1.1 黏包现象 让我们基于tcp先制作一个远程执行命令的程序(命令ls -l ; lllllll ; pwd) 同时执行多条命令之后,得到的结果很可能只有一部分,在执行其他命令的时候又接 ...

  7. Python网络编程基础 ❷ 基于upd的socket服务 TCP黏包现象

    TCP的长连接 基于upd的socket服务 TCP黏包现象

  8. socket编程之黏包

    原理概述 上图是我在学习python的socket编程中遇到的黏包问题所画,以实例来说明这个高大上的黏包问题. 我们知道socket()实例中sendall()方法是无论数据有多大,一次性提交写入缓冲 ...

  9. 网路编程之socket与 socketserver、黏包

    socket与socketerver才是我们学习python中网络编程的重中之重在介绍他们两个之前我先介绍一些相关知识 一.socket 概念 咱们现在ois模型中找到socket所承担的角色 soc ...

随机推荐

  1. World Cup 996B(排队模拟)

    题意:有n个通道,按顺序每一次站一个通道,直到所站的通道没有人 分析:模拟这个过程 #include<cstdio> int main() { ]; while(~scanf(" ...

  2. JSP基本_JavaBeans

    1.JavaBeansとはJavaBeansとは.ある機能を一つにまとめたクラスです.Webアプリケーションでは.JavaBeansは主にデータ操作に使用します.データ管理のプログラムをJavaBea ...

  3. 跨域(二)——WebSocket

    严格地说,WebSocket技术不属于HTML5,这个技术是对HTTP无状态连接的一种革新,本质就是一种持久性socket连接,在浏览器客户端通过javascript进行初始化连接后,就可以监听相关的 ...

  4. 一个seq_file的小问题

    在修改一个内核模块的时候,我们使用seq_file来打印我们的数据,结果非常出人意料. static void flowinfo_seq_printf_stats(struct seq_file *s ...

  5. MongoDB的常规备份策略

    MongoDB的备份其实算是一个基本操作,最近总是有人问起,看来很多人对这里还不太熟悉.为了避免一次又一次地重复解释,特总结成一篇博客供后来者查阅.如有不尽正确之处请指正. 1. 内建方法 1.1 复 ...

  6. django 运行脚本

    转自:https://segmentfault.com/a/1190000006752130 runscript 命令会首先检查每个 app 下的 scripts 目录,如果找到对应名字的脚本就会执行 ...

  7. C#导出Excel,某单元格内容长度超过255 的解决方法

    public static void ToExcel(DataTable dtSource, string strPath, string strSheetName) { System.Data.Ol ...

  8. android资讯类软件框架《IT蓝豹》

    android资讯类软件框架 android资讯类软件框架,支持侧滑,并且首页viewpager切换tab,tab滑动到最右侧的时候提示滑动结束, 滑动到最左侧的时候切换滑动侧滑menu.左滑和侧滑处 ...

  9. Maven项目之间的关系

    1. 依赖关系 1.1 标签<dependency>把另一个项目的jar引入到当前项目 1.2 自动下载另一个项目所依赖的其他项目 2. 继承关系. 2.1 父项目是pom类型 2.2 子 ...

  10. 模块移除 命令rmmod 的实现

    // rmmod.c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include < ...