python成长之路【第九篇】:网络编程

时间:2021-07-25 13:08:33

一、套接字

1.1、套接字
套接字最初是为同一主机上的应用程序所创建,使得主机上运行的一个程序(又名一个进程)与另一个运行的程序进行通信。这就是所谓的进程间通信(Inter Process Communication,IPC)。有两种类型的套接字:基于文件的和面向网络的。

第一种:基于文件的
  因为两个进程运行在同一台计算机上,所以这些套接字都是基于文件的,这意味着文件系统支持他们的底层基础结构。这是能够说的通的,因为文件系统是一个运行在同一个主机上的多个进程之间的共享常量。
第二种:基于网络的
  基于网络的套接字,有自己的家族名字AF_INET,或者地址家族:因特网

地址家族(address family,缩写AF)

1.2、面向连接和无连接的套接字
面向连接的通信提供序列化的、可靠的和不重复的数据交付,而没有记录边界。这基本上意味着每条消息可以拆分成多个片段,并且每一条消息片段都确保能够到达目的地,然后将他们按顺序组合在一起,最后将完整消息传递给正在等待的应用程序。
实现这种连接类型的主要协议是传输控制协议(TCP)。为了创建TCP套接字,必须使用SOCK_STREAM作为套接字类型。

实现无连接的主要协议是用户数据报协议(UDP)。为了创建UDP套接字,必须使用SOCK_DGRAM作为套接字类型。

python成长之路【第九篇】:网络编程

二、Python中的网络编程

2.1、socket()模块函数
要创建一个套接字,必须使用socket.socket()函数,它一般的语法如下。
  socket(socket_family, socket_type, protocol=0)
所以,为了创建TCP/IP套接字,可以用下面的方式调用socket.socket()。
  tcpSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
同样,为了创建UDP/IP套接字,需要执行以下语句。
  udpSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

参数一:地址簇socket_family
  socket.AF_INET #IPv4(默认)
  socket.AF_INET6 #IPv6
  socket.AF_UNIX #只能够用于单一的unix系统进程间通信
参数二:类型socket_type
  socket.SOCK_STREAM #流式socket,for TCP(默认)
  socket.SOCK_DGRAM #数据报式socket,for UDP
  socket.SOCK_RAW #原始套接字,普通的套接字无法处理ICMP、IGMP等网络报文,而SOCK_RAW可以;其次,SOCK_RAW也可以处理特殊的IPv4报文,此外,利用原始套接字,可以通过IP_HDRINCL套接字选项由用户构造IP头。
  socket.SOCK_RDM #是一种可靠的UDP形式,即保证交互数据报但不保证顺序。SOCK_RAM用来提供对原始协议的低级访问,在需要执行某些特殊操作时使用,如发送ICMP报文。SOCK_RAM通常仅限于高级用户或管理员运行的程序使用。
  socket.SOCK_SEQPACKET #可靠的连续数据包服务
参数三:协议
  protocol通常省略,默认为0,则系统就会根据地址格式和套接类别,自动选择一个合适的协议。

因为有很多socket模块属性,如果使用“from socket import *”,那么他们就把socket属性引入到了命名空间中。虽然看起来麻烦,但是通过这种方式将能够大大缩短代码。
  tcpSock = socket(AF_INET, SOCK_STREAM)
一旦有了一个套接字对象,那么使用套接字对象的方法将可以进行进一步的交互。

2.2、套接字对象(内置)方法
常见的套接字对象方法和属性

python成长之路【第九篇】:网络编程

2.3、创建通用TCP服务器的一般伪代码
伪代码:服务端
  ss = socket() #创建服务器套接字
  ss.bind() #套接字与地址绑定
  ss.listen() #监听连接
  inf_loop: #服务器无限循环
    cs = ss.accept() #接收客户端连接,产生阻塞
    comm_loop: #通信循环
      cs.recv()/cs.send() #对话(接收/发送)
    cs.close() #关闭客户端套接字
  ss.close() #关闭服务器套接字 #可选

伪代码:客户端
  cs = socket() #创建客户端套接字
  cs.connect() #尝试连接服务器
  comm_loop: #通信循环
    cs.send()/cs.recv() #对话(发送/接收)
  cs.close()

from socket import *
from time import ctime HOST = ''
PORT = 9999
BUFSIZ = 1024
ADDR = (HOST, PORT) tcpSerSock = socket(AF_INET, SOCK_STREAM)
tcpSerSock.bind(ADDR)
tcpSerSock.listen(5) while True:
print('waiting for connection...')
tcpCliSock, addr = tcpSerSock.accept()
print('...connected from:', addr) while True:
data = tcpCliSock.recv(BUFSIZ)
if not data:
break
tcpCliSock.send(bytes(ctime(), encoding="utf-8") + data)
tcpCliSock.close()
tcpSerSock.close()
解释:
第1个代码块:
导入了time.ctime()和socket模块的所有属性。 第2个代码块:
HOST变量时空白的,这是对bind()方法的标识,表示它可以使用任何可用的地址。我们也选择了一个随机的端口号。将缓冲区大小设置为1KB。可以根据网络性能和程需要改变这个容量。listen()方法的参数是在连接被转接或拒绝之前,传入连接请求的最大数。 第3个代码块:
分配了TCP服务器套接字(tcpSerSock),紧随其后的是将套接字绑定到服务器地址以及开启TCP监听器的调用。 第4个代码块:
一旦进入服务器的无限循环之后,我们就(被动地)等待客户端的连接。当一个连接请求出现时,我们进入对话循环中,在该循环中我们等待客户端发送的消息。如果消息是空白的,这意味着客户端已经退出,所以此时我们将跳出对话循环,关闭当前客户端连接,然后等待另一个客户端连接。如果确实得到了客户端发送的消息,就将其格式化并返回相同的数据,但是会在这些数据中加上当前时间戳的前缀。最后一行永远不会执行,它只是用来提醒读者,如果写了一个处理程序来考虑一个更加优雅的退出方式,那么应该调用close()方法。
from socket import *

HOST = '127.0.0.1'  #or 'localhost'
PORT = 9999
BUFSIZ = 1024
ADDR = (HOST, PORT) tcpCliSock = socket(AF_INET, SOCK_STREAM)
tcpCliSock.connect(ADDR) while True:
data = input('>>:')
if not data:
break
tcpCliSock.send(bytes(data, 'utf-8'))
data = tcpCliSock.recv(BUFSIZ)
if not data:
break
print(str(data, encoding="utf-8")) #和下面语句相同
# print(data.decode('utf-8'))
tcpCliSock.close()
解释:
第1个代码块:
从socket模块导入所有属性
第2个代码块:
HOST和PORT变量指服务器的主机名与端口名。因为在同一台计算机上运行测试,所以HOST包含本地主机名。端口号PORT应该与你为服务器设置的完全相同。此外,也将缓冲区大小设置为1KB。
第3个代码块:
分配了TCP客户端套接字,接着主动调用并连接到服务器。
第4个代码块:
客户端也有一个无限循环,但这并不意味着它会像服务器的循环一样永远运行下去。客户端循环在以下两种条件下将会跳出:用户没有输入,或者服务器终止且对recv()方法的调用失败。否则,在正常情况下,用户输入一些字符串数据,把这些数据发送到服务器进行处理。然后,客户端接收到加了时间戳的字符串,并显示在屏幕上。
执行上面代码输出结果:
>>:i
Tue Sep 13 19:11:20 2016i

python成长之路【第九篇】:网络编程的更多相关文章

  1. Python成长之路第二篇(1)_数据类型内置函数用法

    数据类型内置函数用法int 关于内置方法是非常的多这里呢做了一下总结 (1)__abs__(...)返回x的绝对值 #返回x的绝对值!!!都是双下划线 x.__abs__() <==> a ...

  2. python成长之路第一篇(5)文件的基本操作

    一.三元运算 我们在上章学习的if,,else,,有一种简便的方法 他的表达式是这样的:变量 = 值1 if 条件 else 值2 解释过来就是如果aaa等于sss则输出值1否则输出值2 二.类的概念 ...

  3. python 自动化之路 day 08&lowbar;2 网络编程

    本节内容 Socket介绍 Socket参数介绍 基本Socket实例 Socket实现多连接处理 通过Socket实现简单SSH 通过Socket实现文件传送 作业:开发一个支持多用户在线的FTP程 ...

  4. python学习之路-9 socket网络编程

    socket基础 socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. so ...

  5. Python成长之路第一篇(3)&lowbar;初识字典

    经过上章的学习我们已经了解到了列表可以通过索引来获取对应的值,在本章我们将学到通过名字来索引数据,这种结构的类型称之为映射(maooing),在Python中字典是唯一内建的映射类型,其中的值我们称之 ...

  6. Python成长之路第一篇(4)&lowbar;if&comma;for&comma;while条件语句

    有了以上的基本基础,已经上面写的几个小练习,大家肯定有很多的不满,比如查询为什么查询一次就退出了呢?下面我们来学习条件语句 一.万恶的加号 以前我们在print的时候如果要加上变量都有是使用+来作为连 ...

  7. Python成长之路第一篇(2)-初识列表和元组

    可以将列表和元组当成普通的“数组”,他能保存任意数量任意类型的Python对象,和数组一样都是通过数字0索引访问元素,列表和元组可以存储不同类型的对象,列表和元组有几处重要区别.列表元素用([])包括 ...

  8. PYthon成长之路第一篇&lpar;1&rpar;&lowbar;&lowbar;字符串初识

    今天一起走进python的代码世界,一起领悟python的魅力 在很多学习python的书中都会以 print  “Hello,world!” 这样的而一个程序为开始,那么其中的 hello,worl ...

  9. python学习之路---day25( 网络编程基础和初识socket)

    基本网络知识和初识socket一:基本知识 网线:传输电信号 集线器:将所有连接到集线器的网络设备连通起来 交换机: 升级版的集线器 网卡:接受电信号 MAC地址:物理地址: 8C-88-4B-88- ...

  10. Python成长之路第一篇(2)&lowbar;&lowbar;初识列表和元组

    可以将列表和元组当成普通的“数组”,他能保存任意数量任意类型的Python对象,和数组一样都是通过数字0索引访问元素,列表和元组可以存储不同类型的对象,列表和元组有几处重要区别.列表元素用([])包括 ...

随机推荐

  1. &lbrack;LeetCode&rsqb; Encode and Decode Strings 加码解码字符串

    Design an algorithm to encode a list of strings to a string. The encoded string is then sent over th ...

  2. &lpar;转载&rpar;Autodesk面试技术题解答

    Autodesk面试技术题解答 By SmartPtr(http://www.cppblog.com/SmartPtr/)          近一年以来,AUTODESK的面试题在网上是闹的沸沸扬扬, ...

  3. 线程池 队列 synchronized

    线程池 BlockingQueue synchronized volatile 本章从线程池到阻塞队列BlockingQueue.从BlockingQueue到synchronized 和 volat ...

  4. 为Android添加JNI支持

    起因 今天在进行Android原生开发时,需要通过JNI调用C++代码实现一些处理.以前没有做过类似的东西,在网上找了很久才解决问题,特记录下来以便以后翻阅. Eclipse无cygwin编译so的方 ...

  5. opencv 3&period;3&period;0 如何旋转图像?

    函数介绍 1. void cv::flip(InputArray src,OutputArray dst,int flipCode) 2. void cv::transpose(InputArray ...

  6. Oracle12c&colon;自动分区表

    为什么要创建oracle分区表? 一般情况下,如果不分区,则每次查询的对象都是一整张表,如果采用了表分区,那么可以根据具体的分区字段当作条件来避免扫描整张表,减少IO的扫描以提高表的查询速度. 新建( ...

  7. vue&period;js之组件篇

    Vue.js 组件 模块化:是从代码逻辑的角度进行划分的: 组件化:是从UI界面的角度进行划分的. 组件(Component)是 Vue.js 最强大的功能之一,组件可以扩展 HTML 元素,封装可重 ...

  8. ExcelTools使用

    using NPOI.SS.Formula.Functions; using NPOI.SS.UserModel; using System; using System.Collections.Gen ...

  9. docker-compose介绍

    docker-compose 常用命令 Commands: build Build or rebuild services bundle Generate a Docker bundle from t ...

  10. spring BeanFactory及ApplicationContext中Bean的生命周期

    spring bean 的生命周期 spring BeanFactory及ApplicationContext在读取配置文件后.实例化bean前后.设置bean的属性前后这些点都可以通过实现接口添加我 ...