目录

  • 目录
  • Socket
    • 套接字
    • 套接字的原理
    • 套接字的数据处理方式
    • 套接字类型
    • Socket 标准函数
      • ServerSocket 标准函数
      • ClientSocket 标准函数
      • 公有标准函数
  • Socket 编程
    • 编程思路
    • Demo
      • TCP 服务端
      • TCP 客户端

Socket

套接字

源 IP 地址和目的 IP 地址以及源端口号和目的端口号的组合称为套接字,是支持 TCP/IP 的网络通信的基本操作单元,可以看做是不同主机之间的进程进行双向通信的端点,解决网络上两台主机之间的进程通信问题。简单的说就是通信双方的一种约定,用套接字中的相关函数来完成通信过程。其用于标识客户端请求的服务器和服务,是网络通信过程中端点的抽象表示,包含进行网络通信必需的五种信息:连接使用的协议、本地主机的IP地址、本地进程的协议端口、远地主机的 IP 地址、远地进程的协议端口(Socket = IP address + TCP/UDP + port)。应用层(HTTP)和传输层(TCP/UDP)就可以通过套接字接口,区分来自不同应用程序进程或网络连接的通信,实现数据传输的并发服务。

套接字的原理

Socket 可以看成在两个程序进行通讯连接中的一个端点,是连接应用程序和网络驱动程序的桥梁,Socket 在应用程序中创建,通过绑定与网络驱动建立关系。此后,应用程序送给 Socket 的数据,由 Socket 交给网络驱动程序向网络上发送出去。计算机从网络上收到与该 Socket 绑定 IP 地址和端口号相关的数据后,由网络驱动程序交给 Socket,应用程序便可从该 Socket 中提取接收到的数据,网络应用程序就是这样通过 Socket 进行数据的发送与接收的。要通过 Internet 进行通信,至少需要一对套接字,其中一个运行在客户端,称之为 ClientSocket,另一个运行于服务器端面,称为 ServerSocket。根据连接启动的方式以及本地要连接的目标,套接字之间的连接过程可以分为三个步骤:

  • 服务器监听:是指服务端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态。

  • 客户端请求:是由客户端的套接字提出连接请求,要连接的目标是服务器端套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器套接字的地址和端口号,然后再向服务器端套接字提出连接请求。

  • 连接确认:连接确认是当服务器端套接字监听到或者说接收到客户端套接字的连接请求时,它就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的信息发送给客户端,一旦客户端确认了此连接,连接即可建立。而服务器端继续处于监听状态,继续接收其他客户端的连接请求。

套接字的数据处理方式

  • 同步模式:同步模式的特点是在通过 Socket 进行连接、接收、发送数据时,客户机和服务器在接收到对方响应前会处于阻塞状态,即一直等到收到对方请求才继续执行下面的语句。可见,同步模式只适用于数据处理不太多的场合。当程序执行的任务很多时,长时间的等待可能会让用户无法忍受,但同步模式的好处在于应用接口的访问有着更好的稳定性。

  • 异步模式:异步模式的特点是在通过 Socket 进行连接、接收、发送操作时,客户机或服务器不会处于阻塞方式,而是利用 callback 机制进行连接、接收、发送处理,这样就可以在调用发送或接收的方法后直接返回,并继续执行下面的程序。可见,异步套接字特别适用于进行大量数据处理的场合,使用 s.setblocking(0) 启用异步模式。

套接字类型

套接字类型 描述
socket.AF_UNIX 只能够用于单一的 Unix 系统进程间通信,同一台机器进程间通信
socket.AF_INET 服务器之间网络通信,Internet 进程间通信
socket.AF_INET6 IPv6
socket.SOCK_STREAM 流式 socket, for TCP,流套接字用于提供面向连接、可靠的数据传输服务。该服务将保证数据能够实现无差错、无重复发送,并按顺序接收。流套接字之所以能够实现可靠的数据服务,原因在于其使用了传输控制协议,即 TCP(The Transmission Control Protocol) 协议。
socket.SOCK_DGRAM 数据报式 socket, for UDP,数据报套接字提供了一种无连接的服务。该服务并不能保证数据传输的可靠性,数据有可能在传输过程中丢失或出现数据重复,且无法保证顺序地接收到数据。数据报套接字使用 UDP(User Datagram Protocol) 协议进行数据的传输。由于数据报套接字不能保证数据传输的可靠性,对于有可能出现的数据丢失情况,需要在程序中做相应的处理。
socket.SOCK_RAW 原始套接字,普通的套接字无法处理 ICMP、IGMP 等网络报文,而 SOCK_RAW 可以。其次,SOCK_RAW 也可以处理特殊的 IPv4 报文。此外,利用原始套接字,可以通过 IP_HDRINCL 套接字选项由用户构造 IP 头。原始套接字(SOCKET_RAW)允许对较低层次的协议直接访问,比如 IP、 ICMP 协议,它常用于检验新的协议实现,或者访问现有服务中配置的新设备,因为 RAW SOCKET 可以自如地控制 Windows 下的多种协议,能够对网络底层的传输机制进行控制,所以可以应用原始套接字来操纵网络层和传输层应用。比如,我们可以通过 RAW SOCKET 来接收发向本机的 ICMP、IGMP 协议包,或者接收 TCP/IP 栈不能够处理的IP包,也可以用来发送一些自定包头或自定协议的 IP 包。网络监听技术很大程度上依赖于 SOCKET_RAW
socket.SOCK_SEQPACKET 可靠的连续数据包服务
创建TCP Socket: s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
创建UDP Socket: s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

UDP 和 TCP 的区别:
tcp是可靠的、面向连接的、尽力传输的协议,而udp是不可靠 的、面向非连接的、不尽力传输的协议。但是不可靠不代表它没有用,udp有自己的应用场景,语音和视频几乎都在使用udp协议,它的不可靠只是相对于 tcp来说的,但是它的好处就是效率,高效在某些场景要比可靠性重要。这就涉及trade-off了,也就是权衡,需要根据你的应用权衡利弊,然后进行选择。

NOTE:
1)TCP发送数据时,已建立好TCP连接,所以不需要指定地址。UDP是面向无连接的,每次发送要指定是发给谁。
2)服务端与客户端不能直接发送列表,元组,字典。需要字符串化 repr(data)。

Socket 标准函数

ServerSocket 标准函数

Socket 函数 描述
s.bind(address) 将套接字绑定到地址, 在AF_INET下,以元组(host,port)的形式表示地址.
s.listen(backlog) 开始监听TCP传入连接。backlog指定在拒绝连接之前,操作系统可以挂起的最大连接数量。该值至少为1,大部分应用程序设为5就可以了。backlog指定最多允许多少个客户连接到服务器。它的值至少为1。收到连接请求后,这些请求需要排队,如果队列满,就拒绝请求。
s.accept() 接受TCP连接并返回(conn,address),其中conn是新的套接字对象,可以用来接收和发送数据。address是连接客户端的地址。socket 进入“waiting”状态。客户请求连接时,方法建立连接并返回服务器。accept方法返回一个含有两个元素的元组(connection,address)。第一个元素connection是新的socket对象,服务器必须通过它与客户通信;第二个元素 address是客户的Internet地址。

ClientSocket 标准函数

Socket 函数 描述
s.connect(address) 连接到address处的套接字。一般address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。
s.connect_ex(adddress) 功能与connect(address)相同,但是成功返回0,失败返回errno的值。

公有标准函数

Socket 函数 描述
s.recv(bufsize[,flag]) 接受 TCP 套接字的数据。数据以字符串形式返回,bufsize 指定要接收的最大数据量。flag 提供有关消息的其他信息,通常可以忽略。recv 方法在接收数据时会进入「blocked」状态,如果发送的数据量超过了 recv 所允许的,数据会被截短。多余的数据将缓冲于接收端。以后调用 recv 时,多余的数据会从缓冲区删除(以及自上次调用 recv 以来,客户可能发送的其它任何数据)。
s.send(string[,flag]) 发送 TCP 数据。将 String 中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能小于 String 的字节大小。
s.sendall(string[,flag]) 完整发送 TCP 数据。将 String 中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回 None,失败则抛出异常。
s.recvfrom(bufsize[,flag]) 接受 UDP 套接字的数据。与 recv() 类似,但返回值是(data, address)。其中 data 是包含接收数据的字符串,address 是发送数据的套接字地址。
s.sendto(string[,flag],address) 发送 UDP 数据。将数据发送到套接字,address 是形式为 (ipaddr, port) 的元组,指定远程地址。返回值是发送的字节数。
s.close() 关闭套接字。
s.getpeername() 返回连接套接字的远程地址。返回值通常是元组(ipaddr, port)。
s.getsockname() 返回套接字自己的地址。通常是一个元组 (ipaddr, port)
s.setsockopt(level,optname,value) 设置给定套接字选项的值。
s.getsockopt(level,optname[,buflen]) 返回套接字选项的值。
s.settimeout(timeout) 设置套接字操作的超时期,timeout 是一个浮点数,单位是秒。值为 None 表示没有超时期。一般,超时期应该在刚创建套接字时设置,因为它们可能用于连接的操作(如: connect())
s.gettimeout() 返回当前超时期的值,单位是秒,如果没有设置超时期,则返回None。
s.fileno() 返回套接字的文件描述符。
s.setblocking(flag) 如果 flag 为 0,则将套接字设为非阻塞模式,否则将套接字设为阻塞模式(默认值)。非阻塞模式下,如果调用 recv() 没有发现任何数据,或 send() 调用无法立即发送数据,那么将引起 socket.error 异常。
s.makefile() 创建一个与该套接字相关连的文件

Socket 编程

编程思路

TCP 服务端:

  • 创建套接字,绑定套接字到本地 IP 与端口
  • 开始监听连接
  • 进入循环,不断接受客户端的连接请求
  • 然后接收传来的数据,并发送给对方数据
  • 传输完毕后,关闭套接字

TCP 客户端:

  • 创建套接字,连接远端地址
  • 连接后发送数据和接收数据
  • 传输完毕后,关闭套接字

Demo

TCP 服务端

Step 1:创建套接字,如果创建 socket 函数失败,会抛出一个 socket.error 的异常,需要捕获。

try:# create an AF_INET, STREAM socket (TCP)s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error, msg:print 'Failed to create socket. Error code: ' + str(msg[0]) + ' , Error message : ' + msg[1]sys.exit()

Step 2:绑定 socket

HOST = ''   # Symbolic name meaning all available interfaces
PORT = 8888 # Arbitrary non-privileged port
ADDR = (HOST, RORT)
try:s.bind(ADDR)
except socket.error , msg:print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]sys.exit()

Step 3: 监听连接

s.listen(5)

Step 4:接收请求

# wait to accept a connection - blocking call
conn, addr = s.accept()

Step 5:发送响应

# now keep talking with the client
data = conn.recv(1024)
conn.sendall(data)

Step 6:关闭 socket

s.close()

NOTE1:将上面的服务器程序改造成一直运行,最简单的办法是将 accept 放到一个循环中,那么就可以一直接收连接了。

# now keep talking with the client
while True:#wait to accept a connection - blocking callconn, addr = s.accept()print 'Connected with ' + addr[0] + ':' + str(addr[1])data = conn.recv(1024)reply = 'OK...' + dataif not data: breakconn.sendall(reply)conn.close()

NOTE2:多个 Client 可以随时建立连接,而且每个客户端可以跟服务器进行多次通信,将处理的程序与主程序的接收连接分开。一种方法可以使用线程来实现,主服务程序接收连接,创建一个线程来处理该连接的通信,然后服务器回到接收其他连接的逻辑上来。

  • 定义线程体函数
# Function for handling connections. This will be used to create threads
def client_thread(conn):# Sending message to connected clientconn.send('Welcome to the server. Type something and hit enter\n') # send only takes string# infinite loop so that function do not terminate and thread do not end.while True:# Receiving from clientdata = conn.recv(1024)reply = 'OK...' + dataif not data: breakconn.sendall(reply)# came out of loopconn.close()
  • 创建多线程
# now keep talking with the client
while True:# wait to accept a connection - blocking callconn, addr = s.accept()print 'Connected with ' + addr[0] + ':' + str(addr[1])# start new thread takes 1st argument as a function name to be run, second is the tuple of arguments to the function.start_new_thread(client_thread ,(conn,))s.close()

TCP 客户端

Step 1:创建套接字,如果创建 socket 函数失败,会抛出一个 socket.error 的异常,需要捕获。

try:# create an AF_INET, STREAM socket (TCP)s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error, msg:print 'Failed to create socket. Error code: ' + str(msg[0]) + ' , Error message : ' + msg[1]sys.exit()

Step 2: 连接

remote_hostname = 'www.google.com'
try:# 获得远程主机的 IP 地址remote_ip = socket.gethostbyname(remote_hostname)
except socket.gaierror:#could not resolveprint 'Hostname could not be resolved. Exiting'sys.exit()s.connect((remote_ip , port))

Step 3:发送请求

try :#Set the whole strings.sendall(message)
except socket.error:#Send failedprint 'Send failed'sys.exit()

Step 4:接收响应

reply = s.recv(4096)

Step 5:关闭 socket

s.close()

Python Module_Socket_网络编程相关推荐

  1. Python高级网络编程系列之第一篇

    在上一篇中我们简单的说了一下Python中网络编程的基础知识(相关API就不解释了),其中还有什么细节的知识点没有进行说明,如什么是TCP/IP协议有几种状态,什么是TCP三次握手,什么是TCP四次握 ...

  2. Python之网络编程(TCP套接字与UDP套接字)

    文章目录 基于tcp的套接字 实现目标 tcp服务端源码 tcp客户端源码 tcp效果实现 基于udp的套接字 udp作用介绍 udp服务端源码 udp客户端源码 udp效果实现 用udp实现一个时间 ...

  3. Python Socket网络编程(二)局域网内和局域网与广域网的持续通信

    目录 前言 IP地址 简介 公有IP 私有IP 局域网之间网络通信 前提 功能描述 源码 运行结果 局域网与广域网网络通信 前提 源码 结语 前言 本系列博客是笔者学习Python Socket的过程 ...

  4. Python Socket网络编程(一)初识Socket和Socket初步使用

    目录 前言 网络编程 实质 IP地址和端口 数据传输协议 协议 Socket 概念 套接字 socket对象方法 初步使用 功能 源码 运行结果 结语 前言 本系列博客是笔者学习Python Sock ...

  5. python recv_python网络编程调用recv函数完整接收数据的三种方法

    最近在使用python进行网络编程开发一个通用的tcpclient测试小工具.在使用socket进行网络编程中,如何判定对端发送一条报文是否接收完成,是进行socket网络开发必须要考虑的一个问题.这 ...

  6. 0x011.Python学习-网络编程、PortScan

    Python3 网络编程 Python 提供了两个级别访问的网络服务.: 低级别的网络服务支持基本的 Socket,它提供了标准的 BSD Sockets API,可以访问底层操作系统Socket接口 ...

  7. 用 Python 写网络编程(四)

    本文首发于TesterHome社区,作者是资深游戏测试开发工程师陈子昂.用 Python 写网络编程共四篇,今天分享的是第四篇.原文链接:https://testerhome.com/topics/2 ...

  8. Python 异步网络编程实战

    Python 异步网络编程实战 - songcser - 掘金小册 小册介绍 第一部分是对 Python 协程的讲解,从字节码开始简单讲解了 Python 虚拟机的执行过程,可以大体了解到 Pytho ...

  9. Python之网络编程(socket基础)

    文章目录 客户端/服务器架构 1.即C/S架构 2.C/S架构与socket的关系 3.两机交互的原理 Socket编程 1.socket编程的概念 2.socket的两种类型 3.socket的运行 ...

最新文章

  1. 软件工程概论 课后作业1
  2. OSPF-stub/totaly stub
  3. hdu1542 线段树扫描线求矩形面积的并
  4. 电商双11已臻巅峰,众筹的双11才刚刚开始
  5. mysql change命令_Mysql 操作基本命令大全
  6. 【性能测试】性能测试的基础理论
  7. 字节跳动AI Lab 算法岗专属内推码!
  8. 基于Teigha.Net实现CAD到SHP的转换方案
  9. MySQL的自定义函数
  10. stm32与计算机串口通信,STM32串口通信协议
  11. 5试点城市BIM/CIM平台情况盘点
  12. Chrome 各版本下载地址大全
  13. 好看的个人网站源码_新手想建个人网站,都要注意哪些关于自助建站源码的坑?...
  14. win10系统查看组件服务器,如何查看win10电脑DNS服务器地址 win10查看DNS服务器地址的方法...
  15. 09-搜索前端开发-搜索页面
  16. 走向Web渗透工程师
  17. nas 软件 性能测试,酷狼NAS 10T性能测试
  18. DevComponents.DotNetBar之SuperTabControl动态调整TABS页的位置,以动态调整按钮ButtonItem
  19. 使用Python发送和读取Lotus Notes邮件
  20. 学习笔记:《数字媒体技术概论》-3/10 计算机视觉技术及应用-中国大学慕课公开课

热门文章

  1. 基于Android设备的Kali Linux渗透测试教程第1章渗透测试
  2. mysql删除没有索引页_InnoDB中没有主键是如何运转的
  3. 清华计算机与科学系考研,清华计算机科学与技术系考研怎么复习
  4. python 优先队列_Python中heapq与优先队列【详细】
  5. 领英1000多个假账户被曝光,用AI生成假脸冒充真人发推销信息,已形成相关产业链...
  6. 英伟达新核弹GPU:4nm制程800亿晶体管,20张即可承载全球互联网流量,全新Hopper架构太炸了...
  7. 小鹏发布会上硬刚特斯拉AutoPilot:有视频有真相,特斯拉不懂中国路况
  8. 对话图灵奖得主John Hennessy,他说对美国留学签证变化很忧心
  9. Windows上也能用Swift编程了,官方编译工具安装包现已上线
  10. 2D变3D,视角随意换,神还原高清立体感,还是不用3D建模的那种 | 代码数据开源...