前言

  基于网络通信(AF_INET)的socket(套接字)实现了TCP/UDP协议

目录


基于TCP协议的socket

服务端

  1. #服务端
  2. from socket import *
  3.  
  4. #AF_INIT(基于网络通信) SOCK_STREAM(TCP协议)(买手机)
  5. tcp_server= socket(AF_INET,SOCK_STREAM)
  6.  
  7. #防止端口FIN_WAIT状态,重用ip和端口(4次挥手断开连接需要时间)
  8. #tcp_server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
  9.  
  10. #绑定ip和端口(插手机卡)
  11. tcp_server.bind(('127.0.0.1',8080))
  12.  
  13. #可以挂起几个连接(开机)
  14. tcp_server.listen(5)
  15.  
  16. while True:
  17. #服务端等待连接(等电话)
  18. conn, addr = tcp_server.accept()
  19.  
  20. while True: #通话中
  21. try:
  22. # 接收buffer_size个字节的信息 (收消息)
  23. data = conn.recv(1024)
  24. # (发消息)
  25. conn.send(data.upper())
  26. except Exception as e: #客户端错误方式关闭连接,退出
  27. print(e,'客户端断开连接')
  28. break
  29.  
  30. # 关闭连接 (挂电话)
  31. conn.close()
  32.  
  33. # 关闭服务 (关机)
  34. tcp_server.close()

客户端

  1. #客户端
  2. from socket import *
  3.  
  4. #开机
  5. tcp_client= socket(AF_INET,SOCK_STREAM)
  6. #拨通电话
  7. tcp_client.connect(('127.0.0.1',8080))
  8.  
  9. while True:
  10. msg = input('>>:').strip()
  11. #发消息
  12. tcp_client.send(msg.encode('utf-8'))
  13. #收消息
  14. data = tcp_client.recv(1024)
  15. print(data.decode('utf-8'))
  16.  
  17. #关机
  18. tcp_client.close()
  1. #服务端
  2. from socket import *
  3.  
  4. ip_port = ('127.0.0.1',8080)
  5. back_log = 5
  6. buffer_size = 1024
  7.  
  8. tcp_server= socket(AF_INET,SOCK_STREAM) #AF_INIT(基于网络通信) SOCK_STREAM(TCP协议)(买手机)
  9. tcp_server.bind(ip_port) #绑定ip和端口(插手机卡)
  10. tcp_server.listen(back_log) #可以挂起几个连接(开机)
  11. while True:
  12. conn, addr = tcp_server.accept() # 服务端等待连接(等电话)
  13. print('双向链接', conn)
  14. print('客户端地址', addr)
  15.  
  16. while True:
  17. try:
  18. data = conn.recv(buffer_size) # 接收buffer_size个字节的信息 (收消息)
  19. print("客户端发来的消息", data.decode('utf-8'))
  20. conn.send(data.upper()) # (发消息)
  21. except Exception:
  22. break
  23.  
  24. conn.close() #关闭连接 (挂电话)
  25. tcp_server.close() #关闭服务 (关机)
  26.  
  27. '''
  28. 输出:
  29. 双向链接 <socket.socket fd=516, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 8080), raddr=('127.0.0.1', 47586)>
  30. 客户端地址 ('127.0.0.1', 47586)
  31. 客户端发来的消息 chen
  32. '''

服务端

  1. #客户端
  2. from socket import *
  3.  
  4. ip_port = ('127.0.0.1',8080)
  5. back_log = 5
  6. buffer_size = 1024
  7.  
  8. tcp_client= socket(AF_INET,SOCK_STREAM)
  9. tcp_client.connect(ip_port) #拨通电话
  10. while True:
  11. msg = input('>>:').strip()
  12. tcp_client.send(msg.encode('utf-8')) #发消息
  13. print('客户端已经发送消息')
  14. data = tcp_client.recv(buffer_size) #收消息
  15. print('收到服务端发送的消息',data.decode('utf-8'))
  16.  
  17. tcp_client.close() #关机
  18.  
  19. '''
  20. 输出:
  21. >>:chen
  22. 客户端已经发送消息
  23. 收到服务端发送的消息 CHEN
  24. '''

客户端

基于UDP协议的socket

服务端  

  1. #服务端
  2. from socket import *
  3.  
  4. #AF_INIT(基于网络通信) SOCK_DGRAM(数据报式)
  5. udp_server= socket(AF_INET,SOCK_DGRAM)
  6.  
  7. #防止端口FIN_WAIT状态,重用ip和端口(4次挥手断开连接需要时间)
  8. #udp_server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
  9.  
  10. #绑定ip和端口(插手机卡)
  11. udp_server.bind(('127.0.0.1',8080))
  12.  
  13. while True:
  14. #接收消息
  15. data,addr = udp_server.recvfrom(1024)
  16.  
  17. #按客户端ip和端口发送
  18. udp_server.sendto(data.upper(),addr)
  19.  
  20. udp_server.close()  

客户端

  1. #客户端
  2. from socket import *
  3.  
  4. #开机
  5. udp_client= socket(AF_INET,SOCK_DGRAM)
  6.  
  7. while True:
  8. msg = input('>>:').strip()
  9.  
  10. #向指定ip和端口发消息
  11. udp_client.sendto(msg.encode('utf-8'),('127.0.0.1',8080))
  12. #收消息,返回数据和服务器ip
  13. data,addr = udp_client.recvfrom(1024)
  14.  
  15. udp_client.close()

TCP协议下粘包现象及处理  

tcp协议下会产生粘包现象,即当前的命令结果与上一条的命令结果粘在了一起。

产生粘包现象的原因有两个:

  1.  tcp是面向流的协议, tcp_client.recv() 设置的一次接收的size小于服务器传输过来的字节大小,当客户端从缓存的拿去接收的数据时,没有全部取走,而缓存中是以队列的形式存储,当再一次执行命令的时候会收到上一次命令结果的后半部分与当前命令结果连接在一起的结果   

  2.  tcp下使用Nagle算法优化,会将间隔较小且数据较小的数据,合成一个较大的数据块一起发送

解决方法:粘包现象的根本是,不知道发送数据的大小 

  1. from socket import *
  2. import subprocess
  3. import struct
  4. ip_port=('127.0.0.1',8080)
  5. back_log=5
  6. buffer_size=1024
  7.  
  8. tcp_server=socket(AF_INET,SOCK_STREAM)
  9. tcp_server.bind(ip_port)
  10. tcp_server.listen(back_log)
  11.  
  12. while True:
  13. conn,addr=tcp_server.accept()
  14. print('新的客户端链接',addr)
  15. while True:
  16. #收
  17. try:
  18. cmd=conn.recv(buffer_size)
  19. if not cmd:break
  20. print('收到客户端的命令',cmd)
  21.  
  22. #执行命令,得到命令的运行结果cmd_res
  23. res=subprocess.Popen(cmd.decode('utf-8'),shell=True,
  24. stderr=subprocess.PIPE,
  25. stdout=subprocess.PIPE,
  26. stdin=subprocess.PIPE)
  27. err=res.stderr.read()
  28. if err:
  29. cmd_res=err
  30. else:
  31. cmd_res=res.stdout.read()
  32.  
  33. #发
  34. if not cmd_res:
  35. cmd_res='执行成功'.encode('gbk')
  36.  
  37. length=len(cmd_res)
  38.  
  39. #给数据设置消息头表明数据的大小
  40. data_length=struct.pack('i',length)
  41. conn.send(data_length)
  42. conn.send(cmd_res)
  43.  
  44. except Exception as e:
  45. print(e)
  46. break

远程登录服务端

  1. from socket import *
  2. import struct
  3. from functools import partial
  4. ip_port=('127.0.0.1',8080)
  5. back_log=5
  6. buffer_size=1024
  7.  
  8. tcp_client=socket(AF_INET,SOCK_STREAM)
  9. tcp_client.connect(ip_port)
  10.  
  11. while True:
  12. cmd=input('>>: ').strip()
  13. if not cmd:continue
  14. if cmd == 'quit':break
  15.  
  16. tcp_client.send(cmd.encode('utf-8'))
  17.  
  18. #解决粘包:根据服务端传输的消息头表明数据大小,反复读取缓存缓存数据
  19. length_data=tcp_client.recv(4)
  20. length=struct.unpack('i',length_data)[0]
  21.  
  22. recv_size = 0
  23. recv_msg = b''
  24. while recv_size < length:
  25. recv_msg += tcp_client.recv(buffer_size)
  26. recv_size = len(recv_msg)
  27.  
  28. print('命令的执行结果是 ',recv_msg.decode('gbk'))
  29.  
  30. tcp_client.close()

远程登录客户端

使用socketserver模块实现高并发

tcp服务端  

  1. class MyServer(socketserver.BaseRequestHandler):
  2.  
  3. #通信循环在在内部会调用handlle方法
  4. def handle(self): #在打电话中
  5. print('conn is: ',self.request) #conn
  6. print('addr is: ',self.client_address) #addr
  7.  
  8. while True:
  9. try:
  10.   #收消息
  11. data=self.request.recv(1024)
  12. if not data:break
  13. print('收到客户端的消息是',data,self.client_address)
  14.  
  15. #发消息
  16. self.request.sendall(data.upper())
  17.  
  18. except Exception as e:
  19. print(e)
  20. break
  21.  
  22. if __name__ == '__main__':
  23. s=socketserver.ThreadingTCPServer(('127.0.0.1',8080),MyServer) #多线程
  24. s.serve_forever()

udp服务端

  1. import socketserver
  2.  
  3. class MyServer(socketserver.BaseRequestHandler):
  4. def handle(self):
  5. print(self.request)
  6. print('收到客户端的消息是',self.request[0])
  7. self.request[1].sendto(self.request[0].upper(),self.client_address)
  8.  
  9. if __name__ == '__main__':
  10. s=socketserver.ThreadingUDPServer(('127.0.0.1',8080),MyServer)
  11. s.serve_forever()

  

python之路(12)网络编程的更多相关文章

  1. Python之路,Day8 - Socket编程进阶

    Python之路,Day8 - Socket编程进阶   本节内容: Socket语法及相关 SocketServer实现多并发 Socket语法及相关 socket概念 socket本质上就是在2台 ...

  2. python下的复杂网络编程包networkx的安装及使用

    由于py3.x与工具包的兼容问题,这里采用py2.7 1.python下的复杂网络编程包networkx的使用: http://blog.sina.com.cn/s/blog_720448d30101 ...

  3. python六十七课——网络编程(基础知识了解)

    网络编程: 什么是网络编程? 网络:它是一种隐形的媒介:可以将多台计算机使用(将它们连接到一起) 网络编程:将多台计算机之间可以相互通信了(做数据交互) 一旦涉及到网络编程,划分为两个方向存在,一方我 ...

  4. Python之路【第七篇】python基础 之socket网络编程

    本篇文章大部分借鉴 http://www.cnblogs.com/nulige/p/6235531.html python socket  网络编程 一.服务端和客户端 BS架构 (腾讯通软件:ser ...

  5. python的学习之路day7-socket网络编程

    python基础部分学习完了,时间也已经过了两个月左右,感觉没学到什么,可能是我学习之后忘记的太多了. 由于没钱买书,要是去培训就更没钱了,所以在网上找了一本书,感觉还不错,讲的比较好,比较详细. P ...

  6. Python进阶开发之网络编程,socket实现在线聊天机器人

    系列文章 √第一章 元类编程,已完成 ; √第二章 网络编程,已完成 ; 本文目录 什么是socket?创建socket客户端创建socket服务端socket工作流程图解socket公共函数汇总实战 ...

  7. python之旅:网络编程

    一 客户端/服务器架构 1.硬件C/S架构(打印机) 2.软件C/S架构 互联网中处处是C/S架构 如黄色网站是服务端,你的浏览器是客户端(B/S架构也是C/S架构的一种) 腾讯作为服务端为你提供视频 ...

  8. Python基础-week07 Socket网络编程

    一 客户端/服务器架构 1.定义 又称为C/S架构,S 指的是Server(服务端软件),C指的是Client(客户端软件) 本章的中点就是教大写写一个c/s架构的软件,实现服务端软件和客户端软件基于 ...

  9. python(38)- 网络编程socket

    一 客户端/服务器架构 即C/S架构,包括 1.硬件C/S架构(打印机) 2.软件C/S架构(web服务) 美好的愿望: 最常用的软件服务器是 Web 服务器.一台机器里放一些网页或 Web 应用程序 ...

  10. python学习笔记11 ----网络编程

    网络编程 网络编程需要知道的概念 网络体系结构就是使用这些用不同媒介连接起来的不同设备和网络系统在不同的应用环境下实现互操作性,并满足各种业务需求的一种粘合剂.网络体系结构解决互质性问题彩是分层方法. ...

随机推荐

  1. liteos简介(一)

    LiteOS是在2015华为网络大会上华为发布的敏捷网络3.0中的一个轻量级的物联网操作系统,LiteOS体积只有10KB级. 在Hi3559A中,liteos是用于Cortex-A53,用于处理MP ...

  2. SpringCloud微服务Zuul跨域问题

    目前项目结构是VUE做前端,后端采用微服务架构,在开发时前端需要跨域请求数据,通过ZuulFilter配置解决了简单跨域请求需要.但当需要在请求的header中增加token信息时,出现了请求失败的情 ...

  3. JavaScript 最终将在编程语言中占统治地位?

    JavaScript 最终将在编程语言中占统治地位? JavaScript 现在是大多数开发者都会使用的编程语言.网络效应会推动它成为有史以来第一个真正占统治地位的编程语言吗? 大约十年前,编程的方式 ...

  4. 如何注册一个google账号

    注册过google账号的人都知道,在注册的过程中会需要短信验证. 可我大天朝偏偏连这个都锁了,导致根本验证不了. 所以,经过网上方法的不断尝试,排除了很多的方法:例如使用qq邮箱注册等,现在已经不能用 ...

  5. Elastic Stack-Elasticsearch使用介绍(五)

    一.前言     前4篇将Elasticsearch用法的API和原理方面东西介绍了一下,相信大家对Elasticsearch有了一定的认知,接下我们主要从索引的建立到后期的一些优化做一些介绍: 二. ...

  6. 使用 canvas 画图时图像文字模糊的解决办法

    最近在使用 canvas 画图的时候,遇到了图像文字模糊的问题,解决思路就是根据分辨率创建不同尺寸的画布.以下是创建高分辨率画布的代码: /** * 创建高分辨率画布 * @param w 画布宽 * ...

  7. ubuntu下安装Visual Studio Code

    环境准备 先安装一般umake没有问题 sudo add-apt-repository ppa:ubuntu-desktop/ubuntu-make sudo apt-get update sudo ...

  8. 利用node.js来实现长连接/聊天(通讯实例)

    首先: 需要在服务器端安装node.js,然后安装express,socket.io这两个模块,并配置好相关的环境变量等. 其次: 服务端代码如下: var app = require('expres ...

  9. Spring Boot与消息

    一.概述 1. 大多应用中,可通过消息服务中间件来提升系统异步通信.扩展解耦能力 2. 消息服务中两个重要概念: 消息代理(message broker)和目的地(destination) 当消息发送 ...

  10. php框架之phalcon

    1.开发助手 1) 下载 git clone https://github.com/phalcon/cphalcon.git git clone https://github.com/phalcon/ ...