Python基础:网络编程socket基本篇

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python基础:网络编程socket基本篇相关的知识,希望对你有一定的参考价值。

socket也叫套接字,是对各种协议的封装,实现收发数据。


Python里socket工作过程:(图片来自网络)

技术分享图片


socket在Python中实际上是一个模块,实现发送和接收数据的功能。


因为socket是一个类,所以只导入模块需要使用socket.socket()创建一个socket对象。


  • 创建一个socket格式:

socket(family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None)

参数名选项名称作用
familyAF_UNIX
unix系统进程间传输数据
AF_INETIPv4网络传输数据
AF_INET6IPv6网络传输数据
typeSOCK_STREAM
流式数据,TCP

SOCK_DGRAM数据报式数据,UDP

SOCK_RAW
原始套接字,普通的套接字无法处理ICMP、IGMP等网络报文,而SOCK_RAW可以;其次,SOCK_RAW也可以处理特殊的IPv4报文;此外,利用原始套接字,可以通过IP_HDRINCL套接字选项由用户构造IP头。

SOCK_RDM
是一种可靠的UDP形式,即保证交付数据报但不保证顺序。SOCK_RAM用来提供对原始协议的低级访问,在需要执行某些特殊操作时使用,如发送ICMP报文。SOCK_RAM通常仅限于高级用户或管理员运行的程序使用。

SOCK_SEQPACKET
连续的数据包传输
proto
0默认是0,根据地址簇和套接类别自动选择合适的协议
fileno默认是None
If fileno is specified, the other arguments are ignored, causing the socket with the specified file descriptor to return. Unlike socket.fromfd(), fileno will return the same socket and not a duplicate. This may help close a detached socket using socket.close().



  • socket对象的方法:

    1、socket分为服务端和客户端。

    2、TCP传输不需要IP,UDP传输需要IP地址。

    3、socket传输字符串需要变成byte型。

    4、列表、字典等数据也需要成变byte型。json处理过的函数就byte型的,可以进接send。


方法名对象作用
bind(地址)
服务端绑定服务端地址,IPv4下,是元组的形式(地址,端口)
listen(backlog)服务端设定客户端连接数量,数字
accept()服务端

完整的接收信息:

(<socket.socket fd=316, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 6666), raddr=('127.0.0.1', 58775)>, ('127.0.0.1', 58775))

<>部分是套接字信息

后面元组是客端地址。

connect(地址)客户端绑定服务端地址,IPv4下,是元组的形式(地址,端口)
connect_ex()客户端功能与connect相同,但是成功返回0,失败返回errno的值。
s.recv(bufsize[,flag])服务和客户端接受TCP套接字的数据。数据以字符串形式返回,bufsize指定要接收的最大数据量。flag提供有关消息的其他信息,通常可以忽略。
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表示没有超时期。一般,超时期应该在刚创建套接字时设置,因为它们可能用于连接的操作(如 client 连接最多等待5s )
sk.fileno()套接字的文件描述符


  • 服务端连接实例:

import socket

server = socket.socket()
server.bind("localhost",6666)   # localhost是本地主机,也可以写172.0.0.1
server.listen(6)                # 同时允许5个客户端

while True:                     # 此位置的while是为了客户端结束后,再等待其它客户端进入。
    conn,addr = server.accept() # 接收一套接字信息,和地址。对应的是客户端的connect
    
    while True:
        conn.recv(1024)         # 服务端先接收数据,可以改变每次接收的数值,但是不要小于客户端发送的值。
        conn.send(r'00000')              # 字符前面加r,变成字节数据,才可以传输
        # 这里就是互相通信的主体,可以有多个recv和send,需要注意的是,一收一发,要和客户端对应
        
                break                            # 结束此客户端,继续listen其它客户端


  • 客户端连接实例:

import socket

client = socket.socket()                        # 创建套接字对象
client.connect(('localhost',6666))              # 连接的主机名和端 口,也可以是字符串的ip地址  "127.0.0.1"
while True:
    client.send(r'11111')
    client.recv(1024)
    # 这里就是互相通信的主体,可以有多个recv和send,需要注意的是,一收一发,要和客户端对应
    break

client.close()                                  # 客户端关闭连接。


  • 简单FTP制作的问题点

json.decoder.JSONDecodeError: Extra data: 

因为传输的过程中有二进制数据,所以json无法decode。


传输文件完成时怎么返回?

客户端都一收一发。并且在传输个列表,第一项是标志,第二项是True,当两项不匹配时,提示错误,并返回选项列表。



有时候服务器运行程序时间长,没有到接收语句,而客户端发送数据太快,导致出错

在客户端加个sleep...



logging使用filehandler中文乱码

创建filehandler时,写入encode参数

file_handler = logging.FileHandler(log_path,encoding='utf-8')


调用logging模块,重复输出

1、使用removeHandler()把这个logger里的handler移除掉

2、在log方法里做判断,如果这个logger已有handler,则不再添加handler。


字典、列表无法传输

使用json序列化后传输。json序列化后原来是字节的!




以上是关于Python基础:网络编程socket基本篇的主要内容,如果未能解决你的问题,请参考以下文章

python_day8 socket 网络编程 基本篇

python全栈开发基础第十八篇网络编程(socket)

Python学习笔记——基础篇第七周———FTP作业(面向对象编程进阶 & Socket编程基础)

Python网络编程之socket应用

python之-- socket 基础篇

socket网络编程-基础篇