Python网络编程之socket应用

1 引言

2 网络基础

3 socket介绍

4 socket基本使用

5 总结

1 引言

本篇主要对Python下网络编程中用到的socket模块进行初步总结。首先从网络基础理论出发,介绍了TCP协议和UDP协议;然后总结了socket中的常用函数;最后通过实际代码展示基本函数的应用。

2 网络基础

  要想理解socket,首先得熟悉一下TCP/IP协议族。TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协议,定义了主机如何连入因特网及数据如何在它们之间传输的标准,从字面意思来看TCP/IP是TCP和IP协议的合称,但实际上TCP/IP协议是指因特网整个TCP/IP协议族。下面对TCP/IP协议族中与socket紧密相关的的TCP协议和UDP协议进行介绍。

  TCP是流协议,而UDP是数据报协议。换句话说,TCP在客户机和服务器之间建立持续的开放连接,在该连接的生命期内,字节可以通过该连接写出(并且保证顺序正确)。然而,通过 TCP 写出的字节没有内置的结构,所以需要高层协议在被传输的字节流内部分隔数据记录和字段。

  UDP是数据报协议,不需要在客户机和服务器之间建立连接,它只是在地址之间传输报文。UDP的一个很好特性在于它的包是自分隔的(self-delimiting),也就是一个数据报都准确地指出它的开始和结束位置。然而,UDP的一个可能的缺点在于,它不保证包将会按顺序到达,甚至根本就不保证。不过,UDP有一个很大的有点就是效率高。

  TCP与UDP直接的对比就好似手机通信和邮寄信件通信。TCP犹如手机通信机制,当呼叫者通过手机拨打接受者手机,只有接受者按下接听键,两方才算建立起了连接,且只要没人挂断,连接就一直是存活的,也只有在连接存活情况下两者才能通话。UDP就如有邮局系统,只有有人来寄信,邮局就回帮他寄,但是不会去管收件人是否存在、也不管收件人什么时候能收到信,如果寄件人陆续寄出多封信,收件人收的的信先后顺序是混乱的,如果有的信没有送达,那这封信就此消失在历史的尘埃中。

  通常,人们用socket来建立计算机网络中多个主机(或进程)TCP/IP间的连接。

3 socket介绍

Socket(中文译为套接字)是操作系统内核中的一个数据结构,它几乎是所有网络通信的基础。网络通信,归根到底还是进程间的通信(不同计算机上的进程间通信, 又称为网络通信, IP协议进行的主要是端到端通信)。在网络中,每一个节点(计算机或路由)都有一个网络地址,也就是IP地址。两个进程通信时,首先要确定各自所在的网络节点的网络地址。但是,网络地址只能确定进程所在的计算机,而一台计算机上很可能同时运行着多个进程,所以仅凭网络地址还不能确定到底是和网络中的哪一个进程进行通信,因此套接字中还需要包括其他的信息,也就是端口号(PORT)。在一台计算机中,一个端口号一次只能分配给一个进程,也就是说,在一台计算机中,端口号和进程之间是一 一对应的关系。

socket使用(IP地址,协议,端口号)来标识一个进程。所以,使用端口号和网络地址的组合可以唯一的确定整个网络中的一个网络进程。端口号的范围从0~65535,一类是由互联网指派名字和号码公司ICANN负责分配给一些常用的应用程序固定使用的“周知的端口”,其值一般为0~1023, 用户自定义端口号一般大于等于1024。

网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。每一个socket都用一个半相关描述{协议、本地地址、本地端口}来表示;一个完整的套接字则用一个相关描述{协议、本地地址、本地端口、远程地址、远程端口}来表示。socket也有一个类似于打开文件的函数调用,该函数返回一个整型的socket描述符,随后的连接建立、数据传输等操作都是通过socket描述符来实现的。以TCP协议中socket建立连接的“三次握手”为例,其过程如下:

  如图所示,当客户端通过socket调用connect时,触发了连接请求,向服务器发送了SYN J包,这时connect进入阻塞状态;服务器监听到连接请求,即收到SYN J包,调用socket的accept函数接收请求向客户端发送SYN K ,ACK J+1,这时accept进入阻塞状态;客户端收到服务器的SYN K ,ACK J+1之后,这时connect返回,并对SYN K进行确认;服务器收到ACK K+1时,accept返回,至此三次握手完毕,连接建立。

两个socket通过“网络”交互数据进行数据交互时只负责两件事:建立连接,传递数据;同时socket在收发数据时遵循的原则:有发就有收,收发必相等!

4 socket基本使用

1)socket函数

  功能:使用给定的地址族、套接字类型、协议编号(默认为0)来创建套接字。

  格式:socket.socket([family[, type[, proto]]])

  参数:

    family : AF_INET (默认ipv4),AF_INET6(ipv6) , AF_UNIX(Unix系统进程间通信).

    type : SOCK_STREAM (TCP), SOCK_DGRAM(UDP) .

    protocol : 一般为0或者默认

  备注:如果socket创建失败会抛出一个socket.error异常

2)服务器端函数

 a)bind函数

  格式:s.bind(address)

  功能:将地址address绑定到套接字, 地址以元组(host,port)的形式表示。

  参数:

    address为元组(host,port)

    host: ip地址, 为一个字符串

    post: 自定义主机号, 为整型

b)listen函数

  格式:s.listen(backlog)

  功能:使服务器的这个端口和IP处于监听状态,等待网络中某一客户机的连接请求。如果客户端有连接请求,端口就会接受这个连接。

  参数:backlog : 操作系统可以挂起的最大连接数量。该值至少为1,大部分应用程序设为5就可以了

c)accept函数

  格式:s.accept()

  功能:接受远程计算机的连接请求,建立起与客户机之间的通信连接。服务器处于监听状态时,如果某时刻获得客户机的连接请求,此时并不是立即处理这个请求,而是将这个请求放在等待队列中,当系统空闲时再处理客户机的连接请求。

  返回值:返回一个数组(conn,address),其中conn是新的套接字对象,可以用来接收和发送数据。address是连接客户端的地址

3)客户端函数

  a)connect函数

  格式:s.connect(address)

  功能:用来请求连接远程服务器

  参数:address为远程服务器地址, 格式为元组(hostname,port),如果连接出错,返回socket.error错误

  b)connect_ex函数

  格式:s.connect_ex(address)

  备注:connect()函数的扩展版本,出错时返回出错码,而不是抛出异常

4)通用函数

  a)recv函数

  格式:s.recv(bufsize[,flag])

  功能:接收远端主机传来的数据

  参数:

    bufsize : 指定要接收的数据大小

    flag : 提供有关消息的其他信息,通常可以忽略

  返回值:返回值为数据以字符串形式</code>

  b)send函数

  格式:s.send(string[,flag])

  功能:发送数据给指定的远端主机

  参数:

    string : 要发送的字符串数据

    flag : 提供有关消息的其他信息,通常可以忽略

  返回值:返回值是要发送的字节数量,该数量可能小于string的字节大小。

c)sendall函数

  格式:s.sendall(string[,flag])

  功能:内部调用了send函数,完整发送TCP数据。将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。

  参数:同send函数

  返回值 : 成功返回None,失败则抛出异常。

d)close函数

  格式:s.close()

  功能:关闭套接字

e)recvfrom函数

  格式:s.recvfrom(bufsize[.flag])

  功能:与recv()类似,区别是返回值不同

  返回值:返回一个数组(data,address),其中data是包含接收数据的字符串,address是发送数据的套接字地址。

f)sendto函数

  格式:s.sendto(string[,flag],address)

  功能:将数据发送到套接字

  参数:

    string : 要发送的字符串数据

    flag : 提供有关消息的其他信息,通常可以忽略

    address是形式为(ipaddr,port)的元组,指定远程地址

  返回值:返回值是要发送的字节数量

  备注:该函数主要用于UDP协议。

g)settimeout函数

  格式:s.settimeout(timeout)

  功能:设置套接字操作的超时期

  参数:timeout是一个浮点数,单位是秒。值为None表示没有超时期。一般,超时期应该在刚创建套接字时设置,因为它们可能用于连接的操作(如 client 连接最多等待5s )

h)getpeername函数

  格式:s.getpeername()

  功能:获取连接套接字的远程地址

  返回值:返回值通常是元组(ipaddr,port)。

i)getsockname函数

  格式:s.getsockname()

  功能:获取套接字自己的地址

  返回值:通常是一个元组(ipaddr,port)

  socket中常用的函数就上面这些了。先用上面这些函数尝试TCP协议下的socket通信。

  服务器端代码如下:

import socket

sk = socket.socket()

sk.bind((‘127.0.0.1‘ ,8088))

sk.listen(5)

print(‘正在等待客户端连接……‘)

conn , addr = sk.accept()

print(‘客户端已连接到服务器……‘)

mes_from_client = conn.recv(1024).decode(‘utf-8‘)

print(mes_from_client)

mes_to_server = ‘你好,客户端,已收到你的信息!‘.encode(‘utf-8‘)#发送的数据必须是byte类型

conn.send(mes_to_server)

conn.close()

sk.close()

  客户端代码:

import socket

sk = socket.socket()

sk.connect((‘127.0.0.1‘,8088))

mes_to_server = ‘你好,服务器!‘.encode(‘utf-8‘)#发送的数据必须是byte类型

sk.send(mes_to_server)

mes_from_server = sk.recv(1024).decode(‘utf-8‘)

print(mes_from_server)

sk.close()

  注意:上述两代码块必须放在两不同的py文件中,且必须先运行服务器代码,然后在开启客户端。开启服务器后,首先输出“正在等待客户端连接……”,然后进程会阻塞在accept函数中,下面的代码不会被执行,知道有客户端连接过来。开启客户端后,服务器端会先收到客户端发来的信息,然后客户端也会受到服务器发来的信息。

  上面的例子中,服务器和客户端都是收发了一条信息后socket关闭,如果要保持连接进行长时间通信呢?那么,我们可以把收发函数放入一个“while True”循环中:

  服务器端代码:

import socket

BUF_SIZE = 1024  #设置缓冲区大小

server_addr = (‘127.0.0.1‘, 8089)  #IP和端口构成表示地址

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  #生成一个新的socket对象

server.bind(server_addr)  #绑定地址

print("socket与地址绑定完成……")

server.listen(5)  #监听, 最大监听数为5

print("socket监听开始……")

client, client_addr = server.accept()  #接收TCP连接, 并返回新的套接字和地址, 阻塞函数

print("报告:有客户端请求连接,正在连接……")

print(‘客户端地址为:{}‘.format( client_addr))

while True :

    mes_from_client = client.recv(BUF_SIZE)  #从客户端接收数据

    mes = mes_from_client.decode(‘utf-8‘)

    print(‘客户端说:{}‘.format(mes))

    mes = input(‘回复客户端的信息>‘)

    mes_to_client = mes.encode(‘utf-8‘)

    client.sendall(mes_to_client)  #发送数据到客户端

server.close()

  客户端代码:

import socket

BUF_SIZE = 1024  #设置缓冲区的大小

server_addr = (‘127.0.0.1‘, 8089)  #IP和端口构成的服务器地址

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  #返回新的socket对象

client.connect(server_addr)  #连接服务器

while True:

    mes = input("发送给服务器的信息> ")

    mes_to_server = mes.encode(‘utf-8‘)

    client.sendall(mes_to_server)  #发送数据到服务器

    mes_from_server = client.recv(BUF_SIZE)  #从服务器端接收数据

    mes = mes_from_server.decode(‘utf-8‘)

    print(mes)

client.close()

  运行上述代码后,客户端和服务器可以长时间维持通信。不过,使用socket时一定要注意,有发才有收,收发必相等,否则,就回出现异常。如果需要求换其他客户端与当前服务器进行通信,必须先断开当前客户端的连接。

  再来尝试UDP协议下socket通信:

  服务器端代码:

import socket

sk = socket.socket(type=socket.SOCK_DGRAM)

sk.bind((‘127.0.0.1‘ , 8090))

print(‘等待客户端发来消息……‘)

msg , addr = sk.recvfrom(1024) # 此处会阻塞

print(msg.decode(‘utf-8‘))

mes_to_server = ‘你好,客户端,已收到你的信息!‘.encode(‘utf-8‘)#发送的数据必须是byte类型

sk.sendto(mes_to_server,addr)

sk.close()

  客户端代码:

import socket

sk = socket.socket(type=socket.SOCK_DGRAM)

ip_port = (‘127.0.0.1‘ , 8090)

mes_to_server = ‘你好,服务器!‘.encode(‘utf-8‘)#发送的数据必须是byte类型

sk.sendto(mes_to_server , ip_port)

ret , addr = sk.recvfrom(1024)

print(ret.decode(‘utf-8‘))

sk.close()

  如果需要不停收发消息,代码更改如下:

  服务器端代码:

import socket

sk = socket.socket(type=socket.SOCK_DGRAM)

sk.bind((‘127.0.0.1‘ , 8090))

print(‘等待客户端发来消息……‘)

while True:

    msg , addr = sk.recvfrom(1024) # 此处会阻塞

    print(‘收到{}发来的信息,内容是:{}‘.format(addr , msg.decode(‘utf-8‘)))

    mes_to_server = input(‘>>>‘).encode(‘utf-8‘)#发送的数据必须是byte类型

    sk.sendto(mes_to_server,addr)

sk.close()

  客户端代码:

import socket

sk = socket.socket(type=socket.SOCK_DGRAM)

ip_port = (‘127.0.0.1‘ , 8090)

while True:

    mes_to_server = input(‘>>>‘).encode(‘utf-8‘)#发送的数据必须是byte类型

    sk.sendto(mes_to_server , ip_port)

    ret , addr = sk.recvfrom(1024)

    print(ret.decode(‘utf-8‘))

sk.close()

  使用socket进行UDP协议下通信时,可以多个客户端与服务器通信,也就是说,上面客户端代码你可以另开一个进程与服务器通信,且不需要关闭当前客户端,这是TCP协议与UDP协议下socket通信的一个不同之处。

5 总结

  本篇初步总结了Python网络编程中socket模块的使用,事实上只是大致总结了基本函数的用法。其中诸多内容借鉴了一下两篇博客,感谢两位博主。

  参考资料:

  https://www.cnblogs.com/maociping/p/5112019.html

  https://www.cnblogs.com/zhangyux/p/6109284.html

原文地址:https://www.cnblogs.com/chenhuabin/p/10090793.html

时间: 2024-07-31 07:07:11

Python网络编程之socket应用的相关文章

Python网络编程之socket

socket是网络连接端点.例如当你的Web浏览器请求ansheng.me的网站时,你的Web浏览器创建一个socket并命令它去连接ansheng.me的Web服务器主机,Web服务器也对过来的请求在一个socket上进行监听.两端使用各自的socket来发送和接收信息. 在使用的时候,每个socket都被绑定到一个特定的IP地址和端口.IP地址是一个由4个数组成的序列,这4个数均是范围0~255中的值:端口数值的取值范围是0~65535.端口数小于1024的都是为众所周知的网络服务所保留的:

python网络编程之socket编程

一 客户端/服务器架构 即C/S架构,包括 1.硬件C/S架构(打印机) 2.软件C/S架构(web服务) 美好的愿望: 最常用的软件服务器是 Web 服务器.一台机器里放一些网页或 Web 应用程序,然后启动 服务.这样的服务器的任务就是接受客户的请求,把网页发给客户(如用户计算机上的浏览器),然 后等待下一个客户请求.这些服务启动后的目标就是"永远运行下去".虽然它们不可能实现这样的 目标,但只要没有关机或硬件出错等外力干扰,它们就能运行非常长的一段时间. 生活中的C/S架构: 商

网络编程之socket

网络编程之socket socket:在网络编程中的一个基本组件,也称套接字. 一个套接字就是socket模块中的socket类的一个实例. 套接字包括两个: 服务器套接字和客户机套接字 套接字的实例化需要3个参数: 1.地址簇:socket.AF_INET 2. 流:socket.SOCK_STREAM 3.使用的协议: 默认为0 服务器套接字:以下简称socket_server 客户端套接字:以下简称socket_client 地址:address=('127.0.0.1',8000) so

【转】JAVA网络编程之Socket用法

JAVA网络编程之Socket用法 分类: JAVA2012-08-24 15:56 710人阅读 评论(0) 收藏 举报 在客户/服务器通信模式中,客户端需要主动建立与服务器连接的Socket,服务器端收到客户端的连接请求,也会创建与客户端连接的Socket.Socket可以看做是通信连接两端的收发器,客户端和服务店都通过Socket来收发数据. 1.构造Socket public Socket() 通过系统默认类型的 SocketImpl 创建未连接套接字 public Socket(Str

Java网络编程之Socket通信(二)

之前在前面已经介绍了Socket通信的一些基本原理,以及如何让客户端与服务器端建立通信,和实现通信的一些基本步骤(包括首先使得服务器端与客户端建立连接,建立连接之后,服务器端开始侦听客户端的请求,侦听到客户端的请求之后,通过输入输出流处理相关信息实现通信,最后通信完毕结束通信等一系列流程). 但是之前只是单个客户端与服务器进行通信,而我们实际应用中单个客户端的情况几乎不存在,都是多个客户端同时与服务器进行交互(这里同时交互就会出现并发性的问题,对于并发性的问题暂时还不是很懂,只知道有这个概念),

网络编程之Socket &amp; ServerSocket

网络编程之Socket & ServerSocket Socket:网络套接字,网络插座,建立网络通信连接至少要一对端口号(socket).socket本质是编程接口(API),对TCP/IP的封装,TCP/IP也要提供可供程序员做网络开发所用的接口,这就是Socket编程接口:socket用于描述IP地址和端口,是一个通信链的句柄,可以用来实现不同虚拟机或不同计算机之间的通信. 1.客户端Socket类 此类实现客户端套接字 构造方法 构造方法 作用 Socket(String host, i

【python之路35】网络编程之socket相关

Socket socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. socket起源于Unix,而Unix/Linux基本哲学之一就是"一切皆文件",对于文件用[打开][读写][关闭]模式来操作.socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO.打开.关闭) socket和file的区别: fil

python之路--网络编程之socket

我们使用qq.微信和别人聊天,通过浏览器来浏览页面.看京东的网站,通过优酷.快播(此处只是怀念一下)看片片啥的等等,通过无线打印机来打印一个word文档等,只要有无线.有网.有4G,我们就能好好的聊天,好好的看片片.好好的购物什么的,对吧,那么这些操作都叫做网络通信,确切来说都需要使用网络通信,前提是你要有网(大家记着这个'网',我下面会给大家详解),原来生活中处处使用了网络通信,我们通过网络通信的不同形式:比如说qq是我们下载到电脑或者手机上的应用程序(qq应用程序就是人家腾讯开发的软件,放到

python网络编程之UDP实现

一.简介: python udp是无连接,没有TCP的三次握手,错误重传机制,发的只管发,收的只管收,效率比TCP高,运用于对数据帧不高的地方,如视频,音频的传输 二.实现过程: 服务器端过程如下: 1.建立UDP的SOCKET 2.绑定一个接口,让客户端连接 3.接受数据 客户端过程如下: 1.创建一个socket 2.收发数据报 三.代码实现 1.服务器端: import socket from time import ctime def udpServer(): buffer=2048 a