客户端/服务器的架构

物理层:网卡,光缆,双绞线

数据链路层:包含源mac地址和目标的mac地址,通过广播通讯

网络层:跑的IP协议,IP地址可以定义到一个子网;通过ARP协议可以解析为mac地址;

传输层:提供端口 0-65535 TCP/UDP基于端口传输的

====》socket抽象层{抽象一堆接口,只要遵循socket标准,就支持TCP/UDP基于端口传输}

应用层:软件

客户端与服务端的连接:

1.服务端连接关键字注释:

import socket

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # 基于网络通信,是TCP协议的通讯
server.bind(("127.0.0.1", 8080)) # 开启 绑定IP以及端口
server.listen(5) # 监听;进程池的大小5 # conn 三次握手建立的连接, addr 客户端地址 端口
conn, addr = server.accept()
print("TCP 的链接", conn)
print("客户端的地址和端口", addr) # conn.recv 接收消息;1024 代表接收到 1024个字节 (二进制格式) secv
data = conn.recv(1024)
print("来自于客户端的消息: %s" % data) # 打印输出内容 # 发消息 给 客户端 send (将接收的消息转换为大写返回给客户端 二进制)
conn.send(data.upper()) conn.close() # 关闭连接
server.close() # 结束套接字

2.客户端连接关键字注释:

import socket

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # 基于网络通信,是TCP协议的通讯
client.connect(("127.0.0.1", 8080)) # 与服务端进行连接;
client.send("Hello".encode("utf-8")) # 客户端发消息给 服务端 send 需要二进制 encode # 客户端收取 服务端发过来的消息
data = client.recv(1024)
print("来自于服务端的数据:%s" % data) client.close() # 关闭客户端

输出内容:

# 服务端内容:
TCP 的链接 <socket.socket fd=284, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 8080), raddr=('127.0.0.1', 61799)>
客户端的地址和端口 ('127.0.0.1', 61799)
来自于客户端的消息: b'Hello' # 客户端内容:
来自于服务端的数据:b'HELLO'

解决粘包问题:

1.服务端解决粘包问题:

#! /usr/bin/env python
# -*- coding: utf-8 -*-
# Date: 2017/3/4 import socket
import subprocess # 远程执行命令模块
import struct server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 基于网络通信,是TCP协议的通讯
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # 重用ip和端口,在绑定IP 端口之前 bind 之前
server.bind(("127.0.0.1", 8080)) # 开启 绑定IP以及端口
server.listen(5) # 监听;进程池的大小5 while True: # 循环连接 循环
# conn 三次握手建立的连接, addr 客户端地址 端口
conn, addr = server.accept()
print("客户端地址:", addr) while True: # 消息传输 循环
# conn.recv 接收消息;1024 代表接收到 1024个字节 (二进制格式) secv try: # 捕捉异常
cmd = conn.recv(1024) # recv 会导致堵塞 if not cmd:
break # 针对Linux 客户端断开后 进入死循环现象; print("来自于客户端的消息: %s" % cmd) # 打印输出内容
# 发消息 给 客户端 send (将接收的消息转换为大写返回给客户端 二进制) res = subprocess.Popen(cmd.decode("utf-8"), # 使用 utf-8 解码
shell=True, # 使用shell 解析
stdout=subprocess.PIPE, # 标准输出定向到 管道
stderr=subprocess.PIPE) # 标准错误输出 定向到 管道 err = res.stderr.read()
if err:
back_msg = err
else:
back_msg = res.stdout.read() #####解决粘包部分#####
conn.send(struct.pack("i", len(back_msg))) # 计算出 返回值的长度
conn.sendall(back_msg) # sendall将数据循环的返回 将得到的数据 输出返回
#####↑↑↑↑↑↑↑↑↑↑↑##### except Exception: # 如果发现 异常,直接break
break conn.close() # 关闭连接
server.close() # 结束套接字

2.客户端解决粘包问题

#! /usr/bin/env python
# -*- coding: utf-8 -*-
# Date: 2017/3/4 import socket
import struct client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 基于网络通信,是TCP协议的通讯 client.connect(("127.0.0.1", 8080)) # 与服务端进行连接; while True:
cmd = input("输入你的命令:").strip()
if not cmd:
continue client.send(cmd.encode("utf-8"))
#####解决粘包部分#####
data = client.recv(4)
data_size = struct.unpack("i", data)[0] recv_size = 0 # 收取数据的尺寸
recv_bytes = b"" # 收到的bytes 用于拼接
while recv_size < data_size:
res = client.recv(1024) recv_bytes += res
recv_size += len(res)
#####↑↑↑↑↑↑↑↑↑↑↑##### print(recv_bytes.decode("gbk"))

当返回值过大时,通过自定义报头方式解决粘包

1.自定义报头,发送方服务端配置

#! /usr/bin/env python
# -*- coding: utf-8 -*-
# Date: 2017/3/4 import socket
import subprocess # 远程执行命令模块
import struct
import json server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 基于网络通信,是TCP协议的通讯
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # 重用ip和端口,在绑定IP 端口之前 bind 之前
server.bind(("127.0.0.1", 8080)) # 开启 绑定IP以及端口
server.listen(5) # 监听;进程池的大小5 while True: # 循环连接 循环
# conn 三次握手建立的连接, addr 客户端地址 端口
conn, addr = server.accept()
print("客户端地址:", addr) while True: # 消息传输 循环
# conn.recv 接收消息;1024 代表接收到 1024个字节 (二进制格式) secv try: # 捕捉异常
cmd = conn.recv(1024) # recv 会导致堵塞 if not cmd:
break # 针对Linux 客户端断开后 进入死循环现象; print("来自于客户端的消息: %s" % cmd) # 打印输出内容
# 发消息 给 客户端 send (将接收的消息转换为大写返回给客户端 二进制) res = subprocess.Popen(cmd.decode("utf-8"), # 使用 utf-8 解码
shell=True, # 使用shell 解析
stdout=subprocess.PIPE, # 标准输出定向到 管道
stderr=subprocess.PIPE) # 标准错误输出 定向到 管道 err = res.stderr.read()
if err:
back_msg = err
else:
back_msg = res.stdout.read()
# ########将返回长度记录到字典当中,分三次将所有数据发出
# 制作字典
head_dic = {
"data_size": len(back_msg)
} head_json = json.dumps(head_dic) # 将字典依照 json 格式存储
head_bytes = head_json.encode("utf-8") # 将json 格式 解码为 二进制bytes格式 conn.send(struct.pack("i", len(head_bytes))) # 第一次发:将计算的报头head_bytes长度发送给客户端
conn.send(head_bytes) # 第二次发:发送报头的数据 conn.sendall(back_msg) # 第三次发:sendall将数据循环的返回 将得到的数据 输出返回 except Exception: # 如果发现 异常,直接break
break
# ######↑↑↑↑↑↑↑↑↑↑↑↑↑ conn.close() # 关闭连接
server.close() # 结束套接字

2.自定义报头,接收客户端配置

#! /usr/bin/env python
# -*- coding: utf-8 -*-
# Date: 2017/3/4 import socket
import struct
import json client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 基于网络通信,是TCP协议的通讯
client.connect(("127.0.0.1", 8080)) # 与服务端进行连接; while True:
cmd = input("输入你的命令:").strip()
if not cmd:
continue client.send(cmd.encode("utf-8")) # 收取 服务端返回的数据:分三次收取
# 1.收报头的长度
head = client.recv(4) # 收取报头 二进制格式"b'\x11\x00\x00\x00'"
head_size = struct.unpack("i", head)[0] # 取出报头长度 int "17" # 2.收报头:根据报头的长度
head_bytes = client.recv(head_size) # 根据报头长度head_size 收取报头 二进制格式"b'{"data_size": 61}'"
head_json = head_bytes.decode("utf-8") # 将bytes的格式解码为 json的字符串 "'str'{"data_size": 61}" head_dic = json.loads(head_json) # 将json字符串转换为 字典 "'dict'{'data_size': 61}"
data_size = head_dic["data_size"] # 取出真实数据的长度 "61" # 3.根据长度-收取真实数据
recv_size = 0 # 收取数据的尺寸
recv_bytes = b"" # 收到的bytes 用于拼接
while recv_size < data_size:
res = client.recv(1024) recv_bytes += res
recv_size += len(res)
print(recv_bytes.decode("gbk"))

010-Python-socket编程的更多相关文章

  1. Python Socket 编程——聊天室示例程序

    上一篇 我们学习了简单的 Python TCP Socket 编程,通过分别写服务端和客户端的代码了解基本的 Python Socket 编程模型.本文再通过一个例子来加强一下对 Socket 编程的 ...

  2. python/socket编程之粘包

    python/socket编程之粘包 粘包 只有TCP有粘包现象,UDP永远不会粘包. 首先需要掌握一个socket收发消息的原理 发送端可以是1k,1k的发送数据而接受端的应用程序可以2k,2k的提 ...

  3. PYTHON SOCKET编程简介

    原文地址: PYTHON SOCKET编程详细介绍   Python 提供了两个基本的 socket 模块. 第一个是 Socket,它提供了标准的 BSD Sockets API. 第二个是 Soc ...

  4. python socket编程笔记

    用python实现一个简单的socket网络聊天通讯 (Linux --py2.7平台与windows--py3.6平台) 人生苦短之我用Python篇(socket编程) python之路 sock ...

  5. [Python_7] Python Socket 编程

    0. 说明 Python Socket 编程 1. TCP 协议 [TCP Server] 通过 netstat -ano 查看端口是否开启 # -*-coding:utf-8-*- "&q ...

  6. Python Socket 编程示例 Echo Server

    简评:我们已经从「Python Socket 编程概览」了解了 socket API 的概述以及客户端和服务器的通信方式,接下来让我们创建第一个客户端和服务器,我们将从一个简单的实现开始,服务器将简单 ...

  7. Python Socket 编程——聊天室演示样例程序

    上一篇 我们学习了简单的 Python TCP Socket 编程,通过分别写服务端和client的代码了解主要的 Python Socket 编程模型.本文再通过一个样例来加强一下对 Socket ...

  8. python socket编程入门(编写server实例)+send 与sendall的区别与使用方法

    python 编写server的步骤: 1. 第一步是创建socket对象.调用socket构造函数.如: socket = socket.socket( family, type ) family参 ...

  9. 第九章:Python高级编程-Python socket编程

    第九章:Python高级编程-Python socket编程 Python3高级核心技术97讲 笔记 9.1 弄懂HTTP.Socket.TCP这几个概念 Socket为我们封装好了协议 9.2 cl ...

  10. python socket编程详细介绍

    Python 提供了两个基本的 socket 模块. 第一个是 Socket,它提供了标准的 BSD Sockets API. 第二个是 SocketServer, 它提供了服务器中心类,可以简化网络 ...

随机推荐

  1. 【多线程补充】SimpleDateFormat非线程安全与线程中、线程组中异常的处理

    1.SimpleDateFormat非线程安全的问题 类SimpleDateFormat主要负责日期的转换与格式化,但在多线程环境中,使用此类容易造成数据转换及处理的不正确,因为SimpleDateF ...

  2. 什么是联机分析处理(OLAP)

    OLAP的提出引起了很大的反响,OLAP作为一类产品同联机事务处理 (OLTP) 明显区分开来. 当今的数据处理大致可以分成两大类:联机事务处理OLTP(on-line transaction pro ...

  3. linux 工具学习网站

    推荐一个很不错的linux工具学习网站; 对于一个开发人员来说,我觉得掌握这些工具对于基于linux的应用开发来说事半功倍. http://linuxtools-rst.readthedocs.io/ ...

  4. 拦截RESTful API并做相应处理的方式

    ⒈使用Filter(过滤器) package cn.coreqi.security.filter; import org.springframework.stereotype.Component; i ...

  5. [Kubernetes]如何使用yaml文件使得可以向外暴露服务

    最近因为项目需要上线,所以这段时间都扑到了Kubernetes上面. 昨天老大交代了一个任务,大概就是这样的: 看起来挺简单的,因为相关文件都给我了,我以为直接把文件拖上去,然后在访问ip:port方 ...

  6. golang printf中的%c,%d,%u.都分别代表输出的是什么类型的?

    %表示格式化字符串输出 目前printf支持以下格式的输出,例如: printf("%c",a):输出单个字符. printf("%d",a):输出十进制整数. ...

  7. HDOJ 1754 I Hate It (线段树)

    题目: Problem Description 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少.这让很多学生很反感.不管你喜不喜欢,现在需要你做的是,就是按照老师的要 ...

  8. python学习第16天。

    内置函数是在原本已经有的序列的基础上,再生成新的. List的方是修改原列表. 内置函数中大部分函数的返回值大部分都是迭代器.生成器. Sorted需要遍历操作,不是单纯的迭代,所以不生成迭代器. 一 ...

  9. 前端----css 选择器

      css 为了修饰页面作用, 让页面好看 ⑴ css的引入方式1,行内样式body里面2,内接样式在html里面的 style 里面3,外接样式两种:①链接式: <link rel=" ...

  10. PHP--php时间差8个小时的问题

    自PHP5.0开始,用PHP获取系统时间时,时间比当前时间少8个小时.原因是PHP.ini中没有设置timezone时,PHP是使用的UTC时间,所以在中国时间要少8小时. 解决办法: 1.在PHP. ...