Python--socket库介绍&客户端传送数据给服务端

Python--socket库介绍&客户端传送数据给服务端

在 Python 开发中,socket 库是一个非常重要的工具,它允许我们进行网络编程。通过 socket,程序可以在不同的机器之间进行通信,这为我们构建分布式系统、网络服务等提供了基础。无论是开发一个简单的聊天程序,还是构建复杂的网络服务架构,socket 都是不可或缺的。本文将结合详细的 Python 代码,全面介绍 socket 库的使用方法,让你轻松掌握网络编程的核心技能。

什么是 socket?

socket(套接字)是通信的端点,它是一个通信会话的抽象。在计算机网络中,两台计算机之间要进行通信,就需要在双方建立 socket 连接,通过这个双向通道进行数据的发送和接收。

socket 的类型

主要有两种常见的 socket 类型:

SOCK_STREAM :提供面向连接的、可靠的字节流服务,基于 TCP 协议。它确保数据按照顺序到达,并且在数据传输过程中不会出现重复。

SOCK_DGRAM :提供无连接的、不可靠的 datagram 服务,基于 UDP 协议。这种类型的数据传输不保证可靠性,数据可能会丢失或乱序到达,但它的传输速度相对较快,适用于对实时性要求较高但对数据丢失不太敏感的场景,如视频流传输。

在Internet上的主机一般运行了多个服务软件,同时提供几种服务。每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务。python中socket模块为操作系统的socket实现提供了一个python接口。

在Python中,import socket后,用socket.socket()方法来创建套接字,语法格式如下:

sk = socket.socket([family[, type[, proto]]])

参数说明:

♥family: 套接字家族,可以使AF_UNIX或者AF_INET。

♥type: 套接字类型,根据是面向连接的还是非连接分为SOCK_STREAM或SOCK_DGRAM,也就是TCP和UDP的区别。

♥protocol: 一般不填默认为0。

直接socket.socket(),则全部使用默认值。

socket 的作用和可以实现的功能主要包括:

网络通信:socket 可以让计算机之间通过网络发送和接收数据,就像人们通过电话交谈一样。

文件传输:使用 socket,可以在不同的计算机之间传输文件,就像发送电子邮件附件一样。

远程控制:socket 可以实现远程控制功能,比如远程桌面,你可以在家里的电脑上控制办公室的电脑。

在线游戏:网络游戏中的数据交换就是通过 socket 实现的,它允许玩家之间实时互动。

即时通讯:像QQ、微信这样的即时通讯软件,它们的消息传输也是通过 socket 实现的。

网站浏览:当你在浏览器中输入一个网址时,浏览器通过 socket 与网站服务器通信,获取网页内容并显示给你。

网络服务:各种网络服务,如电子邮件、天气预报等,都是通过 socket 提供服务的。

关于s=socket.socket(family,type)还有一些实例方法

(1)s.bind((address,port))

将socket绑定到一个地址和端口上,通常用于socket服务端;

address必须是一个双元素元组,((host,port)),主机名或者IP地址+端口号。如果端口号正在被使用或者主机名或IP地址错误,则引发socket.error异常。端口号的使用是有限制的,在linux或者unix之中只有系统管理员才能使用1024以下的端口,这些端口号用于标准服务。

import socket

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

s.bind(("172.16.0.18",30000))

(2)s.getsockname()

s.getsockname()返回一个客户机socket,带有客户机端的地址信息。accept方法返回一个双元素元组,形如(IP,port)。第一个元素是客户的IP地址,第二个元素是端口号。

(3)s.listen(backlog)

将socket设置成监听模式,可以监听backlog外来的连接请求,让服务器开始监听客户端发来的连接请求

这个方法设置服务器为监听状态,backlog制定了最多的连接数,至少为1。接到连接请求后,这些请求必须排队,如果队列达到backlog的数值,则拒绝接下来的连接请求。

import socket

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

s.bind(("172.16.0.18",555))

s.listen(10)

(4)s.connect((address,port)) 与s.connect_ex((address,port))

将socket连接到定义的主机和端口上,通常用于socket客户端

import socket

sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

state=sock.connect(("172.16.0.18",136))

二者的区别是:connect_ex 函数在遇到C层面的异常时不会抛出异常,而是返回状态码,0状态码表示正常,你也可以使用connect方法进行连接,但这样,就需要使用异常捕获机制来捕获ConnectionRefusedError 异常。

(5)s.recv(buflen[,flags])

从socket中接收数据,最多接收buflen个字符,一般填写1024个

import socket

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

s.connect(("172.16.0.18",555))

data=s.recv(1024)

(6)s.send(data[,flags])

通过socket发送指定的数据

import socket

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

s.bind(("172.16.0.18",555))

s.listen(10)

connection,address=s.accept()

print( connectionsocket._socketobject object at 0x01DDDCE0>

>>> print address

('172.16.0.18', 21586)

s.send('hello,I am lybbn.cn')

Traceback (most recent call last):

File "", line 1, in

socket.error: [Errno 10057] 由于套接字没有连接并且(当使用一个 sendto 调用发送数

据报套接字时)

由上可见,s.send()发送数据的时候需要先建立socket连接,不然会出现error。使用recv方法和send方法发送和接受消息。发送和接收都是采用的字符串的形式。send方法返回已发送的字符个数。调用recv的时候,必须制定一个整数来控制本次调用所接受的最大的数据量。

recv方法接收数据时会进入阻塞状态,最后返回一个字符串,表示收到的数据。如果发送数据超过recv所允许,数据会被截断。多余的数据将缓冲于接收端。以后调用recv时,多余的数据会从缓冲区删除。

(7)s.close()

关闭socket连接,传输结束,通过调用close方法关闭连接。

TCP 服务器端server.py代码示例

#!/usr/bin/env python

# -*- coding:utf-8 -*-

import socket

ip_port = ("172.16.0.18", 30000)

try:

sk = socket.socket() # 创建套接字

sk.bind(ip_port) # 绑定服务地址、绑定端口

sk.listen(5) # 监听连接请求

print('启动socket服务端服务,等待客户端连接...')

conn, address = sk.accept() # 等待连接,此处自动阻塞

while True: # 一个死循环,直到客户端发送‘exit’的信号,才关闭连接

client_data = conn.recv(1024).decode() # 接收信息

if client_data == "exit": # 判断是否退出连接

exit("通信结束")

print("来自%s的客户端向你发来信息:%s" % (address, client_data))

conn.sendall('服务器已经收到你的信息'.encode()) # 回馈信息给客户端

conn.close() # 关闭连接

except Exception as msg:

print('socket,服务端发送失败{}!'.format(msg))

TCP客户端client.py:

#!/usr/bin/env python

# -*- coding:utf-8 -*-

import socket

ip_port = ("172.16.0.18", 30000)

s = socket.socket() # 创建套接字

s.connect(ip_port) # 连接服务器

while True: # 通过一个死循环不断接收用户输入,并发送给服务器

inp = input("请输入要发送的信息:").strip()

if not inp: # 防止输入空信息,导致异常退出

continue

s.sendall(inp.encode())

if inp == "exit": # 如果输入的是‘exit’,表示断开连接

print("结束通信!")

break

server_reply = s.recv(1024).decode()

print(server_reply)

s.close() # 关闭连接

代码分析

在服务器端,bind() 方法用于绑定 IP 地址和端口,使得服务器能够监听指定地址和端口上的连接请求。listen() 方法则让服务器进入监听状态,等待客户端的连接。

accept() 方法是一个阻塞方法,它会等待客户端的连接。当客户端连接成功后,会返回一个新的 socket 对象(用于和客户端进行通信)和客户端的地址信息。

客户端通过 connect() 方法连接到服务器的指定 IP 地址和端口。

数据的发送和接收分别通过 send() 和 recv() 方法实现,需要注意数据是以字节流的形式传输,所以在发送之前要使用 encode() 方法将字符串编码为字节,接收后使用 decode() 方法解码为字符串。

目前实盘中,需要向外网传输不同数据类型的数据,会将不能类型维护成不同的字段,进行传输,

if sockname=='mail':

df_dict = send_data.to_dict('records')

json_data = "bb#" + json.dumps(df_dict) + "bb#"

print('send_maild', json_data)

tcp_client.send(json_data.encode('utf-8'))

# 4. 等待服务端数据返回 最大接收1024个字节

recv_data = tcp_client.recv(1024)

print(recv_data.decode('utf-8'))

服务端将会对不同类型,在进行拆分,邮件发送给不同的人

当时,本文主要是掌握socket的传输,如何传输、传输什么内容、实时监控是否传输、异常响应等都需要再此基础上进行挖掘,暂不过多介绍,有更新在进行拆分详解。

相关推荐

澳柯玛集成吊顶(澳柯玛集成吊顶加盟)

澳柯玛集成吊顶(澳柯玛集成吊顶加盟)

必定赢365线路检测 10-28
阅读更多
Nokia 8 - 规格

Nokia 8 - 规格

365 体育投注 08-08
阅读更多
2K14 2019年男篮世界杯球场补丁

2K14 2019年男篮世界杯球场补丁

365 体育投注 08-02
阅读更多