python网络编程案例_Python基础:网络编程socket基本篇

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

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

AAffA0nNPuCLAAAAAElFTkSuQmCC

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

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

创建一个socket格式:

socket(family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None)参数名选项名称作用

familyAF_UNIXunix系统进程间传输数据

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连续的数据包传输(已废弃)

proto0默认是0,根据地址簇和套接类别自动选择合适的协议

fileno默认是NoneIf 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处理过的数据是字符型的,decode后可以进行send。

5、传输大数据,使用长度时,要注意len的对象是原数据,还是encode后的数据,接收方也得计算相应的数据。否则会造成文件长度不匹配

方法名对象作用

bind(地址)服务端绑定服务端地址,IPv4下,是元组的形式(地址,端口)

listen(backlog)服务端设定客户端连接数量,数字

accept()服务端完整的接收信息:

(, ('127.0.0.1', 58775))

<>部分是套接字信息

后面元组是客端地址。

connect(地址)客户端绑定服务端地址,IPv4下,是元组的形式(地址,端口)

connect_ex()客户端功能与connect相同,但是成功返回0,失败返回errno的值。

s.recv(bufsize[,flag])服务和客户端接受TCP套接字的数据。数据以字符串形式返回,bufsize指定要接收的最大数据量。flag提供有关消息的其他信息,通常可以忽略。

bufsize官方建议8192,不同系统最大数值不同,一般一次可以收10M左右。

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(b'00000') # 字符前面加r,变成字节数据,才可以传输

# 这里就是互相通信的主体,可以有多个recv和send,需要注意的是,一收一发,要和客户端对应

# 服务端和客户端不能同时收或同时发。

break # 结束此客户端,继续listen其它客户端

客户端连接实例:

import socket

client = socket.socket() # 创建套接字对象

client.connect(('localhost',6666)) # 连接的主机名和端 口,也可以是字符串的ip地址 "127.0.0.1"

while True:

client.send(b'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序列化后原来是字节的!

“粘包”:A给B连续发送两个send,B接收到的两个数据都混在一起,分不清第一次还是第二次接收的

原因是,A发送时存在缓存区,大约0.5S后缓存消失

如果想要分开两次的数据,A使用send后立即执行recv,接收B的send,然后再发送第二句。

'''更好的解决粘包'''

# recv_file_size 已经接收的大小

# file_size 文件总大小

# base_recv 每次接收的大小

base_recv = 1024

recv_file_size = 0

while recv_file_size

data = conn.recv(base_recv).decode()

if file_size-recv_file_size < base_recv:

base_recv = file_size-recv_file_size

recv_file_size =+ len(data)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值