一、网络编程中send函数的用途
1、发送数据
在网络编程中,send函数主要用于发送数据,将数据(一般是字符串)打包后通过网络传输到另一端,该函数格式如下:
socket.send(bytes[, flags])
其中,bytes表示需要发送的数据,flags为可选参数,可以指定一些标志,如MSG_DONTWAIT、MSG_EOR等。它们将在后面的小标题中做详细介绍。
2、发送文件
在网络编程中,send函数还可以用于发送文件。一般是通过二进制方式读取文件,然后调用send函数将文件数据传输到另一端,示例代码如下:
with open('filename', 'rb') as f: while True: data = f.read(1024) # 每次读取1024个字节 if not data: break sock.send(data)
二、与socket结合的send函数使用方式
1、结合socket.send()方法使用
在与socket结合使用时,send函数可以与socket.send()方法结合使用,socket.send()只会将数据放入TCP/IP发送缓冲区,而当缓冲区有足够的空间时,send函数会将数据从缓冲区中发送出去,这样可以保证数据的完整性。示例代码如下:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('www.example.com', 80)) s.send(b'GET /index.html HTTP/1.1\r\nHost: www.example.com\r\n\r\n') resp = b'' while True: r = s.recv(1024) if not r: break resp += r print(resp.decode())
2、与socket.sendall()方法使用
与socket.send()方法不同,sendall方法会一直发送数据,直到数据发送完成。如果发送的数据量大于缓冲区大小,数据可能会分成多段发送。当所有数据发送完成后,函数会返回None。示例代码如下:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('www.example.com', 80)) s.sendall(b'GET /index.html HTTP/1.1\r\nHost: www.example.com\r\n\r\n') resp = b'' while True: r = s.recv(1024) if not r: break resp += r print(resp.decode())
三、send函数在异步编程中的应用
1、异步IO操作中的send函数
在异步编程中,协程一般会配合asyncio模块使用。send函数可以在异步IO操作中作为协程的接收者,每次调用时,协程会向send函数传入一个值,然后send函数会继续执行,直到下一次遇到yield关键字停下来。示例代码如下:
import asyncio async def my_coroutine(): print('Coroutine started') value = await asyncio.sleep(1) print(f'Coroutine resumed, value: {value}') return 'Coroutine returned' async def main(): cor = my_coroutine() print('Main coroutine started') try: print(await cor.send(None)) # 向协程my_coroutine传入None并调用send函数,协程会开始执行 print(await cor.send(42)) # 向协程传入42并调用send函数,协程会继续执行 except StopIteration as e: print(f'Coroutine raised an exception: {e.value}') asyncio.run(main())
2、生成器中的send函数
在生成器中,send函数的作用与协程中的send函数类似,它可以向生成器中传入一个数据,并让生成器继续执行。随后生成器会返回一个数据给调用方。生成器中的send函数比它的“兄弟”yield要强大很多。示例代码如下:
def my_generator(): value = yield 1 print(f'Value received: {value}') yield 2 gen = my_generator() print(next(gen)) # 输出1 print(gen.send('hello')) # 输出Value received: hello,然后输出2
四、send函数中常用flags参数详解
1、MSG_DONTWAIT
MSG_DONTWAIT参数被用来在非阻塞IO模式下立即返回。如果发送操作无法即时完成,函数将返回EAGAIN或EWOULDBLOCK错误码。示例代码如下:
import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setblocking(False) # 设置为非阻塞IO模式 try: s.send(b'Hello, world!', socket.MSG_DONTWAIT) except socket.error as e: print(e)
2、MSG_EOR
MSG_EOR参数在SOCK_SEQPACKET类型的套接字中使用,它指定在发送缓冲区中的数据包的末尾处插入EOR标记。示例代码如下:
import socket s = socket.socket(socket.AF_INET, socket.SOCK_SEQPACKET) s.send(b'Hello, world!', socket.MSG_EOR)
3、MSG_MORE
MSG_MORE参数在SOCK_STREAM类型的套接字中使用,它指定这不是最后一部分数据,内核会在数据末尾添加TCP_NOPUSH标志,并将数据存储在发送缓冲区中。示例代码如下:
import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('www.example.com', 80)) s.send(b'GET /index.html HTTP/1.1\r\n', socket.MSG_MORE) s.send(b'Host: www.example.com\r\n\r\n') resp = b'' while True: r = s.recv(1024) if not r: break resp += r print(resp.decode())
五、总结
通过以上几个方面的介绍,我们可以看出,send函数在python的编程中应用非常广泛,从网络编程到异步编程,再到生成器等等场景,都可以发挥重要作用。 相信通过本文,读者可以更好地理解send函数的诸多应用场景,并以此来提高自己的编程技术。
最新评论