加入收藏 | 设为首页 | 会员中心 | 我要投稿 济南站长网 (https://www.0531zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 教程 > 正文

Python网络编程socket模块实例介绍

发布时间:2021-11-12 14:08:53 所属栏目:教程 来源:互联网
导读:网络也是IO的一种,在Python中有专门的socket模块用来处理网络操作的。 socket通常也称作套接字,用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过套接字向网络发出请求或者应答网络请求。 socket起源于Unix,而Unix/Linux基本哲学之一就是一切

网络也是IO的一种,在Python中有专门的socket模块用来处理网络操作的。
 
socket通常也称作”套接字”,用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过”套接字”向网络发出请求或者应答网络请求。
 
socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,对于文件用【打开】【读写】【关闭】模式来操作。socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭)。
 
(1)利用socket进行简单的链接
 
Python里面的socket支持UDP、TCP、以及进程间的通信,socket可以把我们想要发送的东西封装起来,发送过去,然后反解成原来的样子,事实上网路通信可以理解成都是建立在socket之上,下面的代码是演示利用socket进行简单的链接
 
#要成一次通信,至少要有两个人,也就是一个服务端,一个客户端
 
#服务端
'''必须先开启着,等待客户端来进行链接请求,所以自己要先有个地址,也就是IP,也要现有自己的端口,没有端口进不去'''
 
import socket
sk= socket.socket()#创建对象
 
sk.bind(('127.0.0.1',9999,))#绑定IP和端口,以一个元组的方式传进去
sk.listen(5)#在前面链接已经建立的情况下,后面最多让五个人等待
while True:#让服务器端处于可以永远处于接受客户端请求的状态
 
    conn,address=sk.accept()
    print(conn,address)
'''
监听端口,等待以及接受客户端的请求,有可能会阻塞,主要功能是建立链接,以及接受客户端信息
conn相当于双方建立的这个链接,之后互相的通信要依靠这个链接;
address指的的对方的IP和端口
'''
 
下面是客户端代码
 
#客户端
import socket
obj =socket.socket()
'''相对于客户端,制定要链接谁就好了
'''
 
obj.connect(('127.0.0.1',9999,))#链接服务端
obj.close()#链接之后关闭
 
我们先让服务器端启动,然后再启动客户端,结果如图所示
 
Python网络编程socket模块实例解析
 
<socket.socket fd=4, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 36126)> ('127.0.0.1', 36126)
<socket.socket fd=5, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 36128)> ('127.0.0.1', 36128)
<socket.socket fd=4, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 36130)> ('127.0.0.1', 36130)
 
成功打印出了每次的链接,以及客户端的IP以及端口号
 
(2)基于socket实现简单的传送消息
 
#服务器端
import socket
sk= socket.socket()
 
sk.bind(('127.0.0.1',9999,))#绑定IP和端口,以一个元组的方式传进去
sk.listen(5)#在前面链接已经建立的情况下,后面最多让五个人等待
while True:#让服务器端处于可以永远处于接受客户端请求的状态
 
    conn,address=sk.accept()#基于conn这个链接发送东西
    conn.sendall(bytes('有空来Linux公社www.linuxidc.com天天给你新知识',encoding='utf-8'))#Python3要用bytes类型,发送字节
    '''建立一次链接,服务器就发送这个字段'''
    print(conn,address)
 
然后用是客户端代码
 
#客户端
import socket
obj =socket.socket()
'''相对于客户端,制定要链接谁就好了
'''
 
obj.connect(('127.0.0.1',9999,))#链接服务端
'''
客户端去链接服务端,如果服务器端没有返回消息给客户端,则客户端会一直
在recv状态,一直等待服务器的消息
'''
result1= obj.recv(2014)#表示最多接收1024个字节,超过了下次接收、
result2= str(result1,encoding='utf-8')
print(result2)
obj.close()#链接之后关闭
 
当启动一次客户端建立一次链接,就会收到消息,结果如图
 
Python网络编程socket模块实例解析
 
(3)基于socket实现聊天机器人
 
#服务器端
import socket
sk= socket.socket()
 
sk.bind(('127.0.0.1',9999,))#绑定IP和端口,以一个元组的方式传进去
sk.listen(5)#在前面链接已经建立的情况下,后面最多让五个人等待
while True:#让服务器端处于可以永远处于接受客户端请求的状态
 
    conn,address=sk.accept()#基于conn这个链接发送东西
    conn.sendall(bytes('你好www.linuxidc.com,链接已经建立',encoding='utf-8'))#Python3要用bytes类型,发送字节
    # '''建立一次链接,服务器就先发送这个字段'''
    while True:#让通信状态不中断
        ret_bytes = conn.recv(1024)
        ret_str = str(ret_bytes,encoding='utf-8')
        if ret_str =='q':#如果收到q,则终止链接
            break
        conn.sendall(bytes(ret_str+' 已收到该信息',encoding='utf-8'))
    #print(conn,address)
 
下面是客户端代码
 
#客户端
import socket
obj =socket.socket()
'''相对于客户端,制定要链接谁就好了
'''
 
obj.connect(('127.0.0.1',9999,))#链接服务端
'''
客户端去链接服务端,如果服务器端没有返回消息给客户端,则客户端会一直
在recv状态,一直等待服务器的消息
'''
 
result1= obj.recv(2014)#表示最多接收1024个字节,超过了下次接收、
result2= str(result1,encoding='utf-8')
print(result2)
while True:
    data = input('请输入你要发送的内容:')
    if data == 'q':
        obj.sendall(bytes(data, encoding='utf-8'))
        print('链接断开')
        break
    else:
        obj.sendall(bytes(data,encoding='utf-8'))
        rec_byte = obj.recv(1024)#发了之后,接收信息
        rec_str = str(rec_byte,encoding='utf-8')
        print(rec_str)
 
obj.close()#链接之后关闭
 
结果如图所示
 
Python网络编程socket模块实例解析
 
 (4)利用socket传送图片文件
 
#服务器端
import socket
sk= socket.socket()
 
sk.bind(('127.0.0.1',9999,))#绑定IP和端口,以一个元组的方式传进去
sk.listen(5)#在前面链接已经建立的情况下,后面最多让五个人等待
while True:#
    conn,address= sk.accept()
    conn.sendall(bytes('链接已建立,可以发送数据了',encoding='utf-8'))
    file_size = str(conn.recv(1024),encoding='utf-8')#接收文件大小
    print('接收的文件字节数:'+file_size)
    total_size = int(file_size)
    has_recv = 0#默认已接收了0个字节
    f = open('linuxidc.com.png','wb')
    #先接收文件大小,再开始接收文件
    while True:
        if total_size ==has_recv:#如果已接收的文件大小与客户端发送的一样大,则表示已经接收完毕
            break
 
        data = conn.recv(1024)
 
        f.write(data)
        has_recv +=len(data)
    print('文件接收成功')
    f.close()
 
下面是客户端
 
#客户端
import os
import socket
obj =socket.socket()
 
obj.connect(('127.0.0.1',9999,))#链接服务端
'''
客户端去链接服务端,如果服务器端没有返回消息给客户端,则客户端会一直
在recv状态,一直等待服务器的消息
# '''
#obj.sendall(bytes('你好',encoding='utf-8'))
ret_bytes = obj.recv(1024)
ret_str = str(ret_bytes,encoding='utf-8')
print(ret_str)
 
#发送文件大小
size=os.stat('linuxidc.png').st_size#获取文件大小
obj.sendall(bytes(str(size),encoding='utf-8'),)#文件大小的int型,要先转化为字符串
with open('linuxidc.png','rb')as f:
    for line in f:
        obj.sendall(line)
obj.close()
 
结果如图
 
Python网络编程socket模块实例解析
 
(5)socket粘包问题
 
发送文件需要依赖双方的缓冲区,就是我们先把文件写到缓冲区,然后再发送过去,但是我们一般不知道什么时候发过去,这容易造成粘包问题。例如上面的例子,客户端先发送文件大小,然后读文件写进缓冲区,假如文件读取特别快,第一次发送过去的可能既有文件大小又有文件内容,造成错误,这叫粘包,简而言之就是收到的信息比原本应收的多。
 
那么怎么解决粘包问题呢,通过发送以及接收确认包,还是以上面的例子说明,客户在发送文件大小之后不要马上发送文件,先recv接收一下,等待服务器发送已收到文件大小的确认包之后,再读取文件、发送文件,这样文件的发送和之前数据的发送就
完全独立开来了。
 
#服务器端
import socket
sk= socket.socket()
 
sk.bind(('127.0.0.1',9999,))#绑定IP和端口,以一个元组的方式传进去
sk.listen(5)#在前面链接已经建立的情况下,后面最多让五个人等待
while True:#
    conn,address= sk.accept()
    conn.sendall(bytes('链接已建立,可以发送数据了',encoding='utf-8'))
 
    file_size = str(conn.recv(1024),encoding='utf-8')#接收文件大小
    print('接收的文件字节数:'+file_size)
    total_size = int(file_size)
    has_recv = 0#默认已接收了0个字节
    conn.sendall(bytes('文件大小已收到,可以开始发送数据了',encoding='utf-8'))#解决粘包问题,已经收到了文件大小,后面就可以单独发文件了
    f = open('linuxidc.com.png','wb')
    #先接收文件大小,再开始接收文件
 
    while True:
        if total_size ==has_recv:#如果已接收的文件大小与客户端发送的一样大,则表示已经接收完毕
            break
 
        data = conn.recv(1024)
 
        f.write(data)
        has_recv +=len(data)
    print('文件接收成功')
    f.close()
 
下面是客户端
 
#客户端
import os
import socket
obj =socket.socket()
 
obj.connect(('127.0.0.1',9999,))#链接服务端
'''
客户端去链接服务端,如果服务器端没有返回消息给客户端,则客户端会一直
在recv状态,一直等待服务器的消息
# '''
#obj.sendall(bytes('你好www.linuxidc.com',encoding='utf-8'))
ret_bytes = obj.recv(1024)
ret_str = str(ret_bytes,encoding='utf-8')
print(ret_str)
 
#发送文件大小
size=os.stat('linuxidc.png').st_size#获取文件大小
obj.sendall(bytes(str(size),encoding='utf-8'),)#文件大小的int型,要先转化为字符串
ack_packet=obj.recv(1024)
print(str(ack_packet,encoding='utf-8'))
with open('linuxidc.png','rb')as f:
    for line in f:
        obj.sendall(line)
obj.close()

(编辑:济南站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读