python--基于socket网络编程

Python 提供了两个基本的 socket 模块。python

第一个是 Socket,它提供了标准的 BSD Sockets API。编程

第二个是 SocketServer, 它提供了服务器中心类,能够简化网络服务器的开发。

一、Scoket类型服务器

套接字格式:网络

socket(family,type[,protocal]) 使用给定的地址族、套接字类型、协议编号(默认为0)来建立套接字。并发

1.一、socket.AF_UNIX #只可以用于单一的Unix系统进程间通讯socket

1.二、socket.AF_INET #服务器之间网络通讯函数

1.三、socket.AF_INET6 #IPv6大数据

1.四、socket.SOCK_STREAM #流式socket , for TCPspa

1.五、socket.SOCK_DGRAM #数据报式socket , for UDP操作系统

1.六、socket.SOCK_RAW #原始套接字,普通的套接字没法处理ICMP、IGMP等网络报文,而SOCK_RAW能够;其次,SOCK_RAW也能够处理特殊的IPv4报文;此外,利用原始套接字,能够经过IP_HDRINCL套接字选项由用户构造IP头。

1.七、socket.SOCK_SEQPACKET #可靠的连续数据包服务

1.八、建立TCP Socket: s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

1.九、建立UDP Socket: s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)


二、Socket 函数
注意点:
1)TCP发送数据时,已创建好TCP链接,因此不须要指定地址。UDP是面向无链接的,每次发送要指定是发给谁。
2)服务端与客户端不能直接发送列表,元组,字典。须要字符串化repr(data)。


2.一、服务端socket函数

s.bind(address) #将套接字绑定到地址, 在AF_INET下,以元组(host,port)的形式表示地址.

s.listen(backlog) #开始监听TCP传入链接。backlog指定在拒绝链接以前,操做系统能够挂起的最大链接数量。该值至少为1,大部分应用程序设为5就能够了。

s.accept() #接受TCP链接并返回(conn,address),其中conn是新的套接字对象,能够用来接收和发送数据。address是链接客户端的地址。

 

2.二、客户端socket函数

s.connect(address) #链接到address处的套接字。通常address的格式为元组(hostname,port),若是链接出错,返回socket.error错误。

s.connect_ex(adddress) #功能与connect(address)相同,可是成功返回0,失败返回errno的值。


2.三、公共socket函数

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表示没有超时期。通常,超时期应该在刚建立套接字时设置,由于它们可能用于链接的操做(如connect())

s.gettimeout() #返回当前超时期的值,单位是秒,若是没有设置超时期,则返回None。

s.fileno() #返回套接字的文件描述符。

s.setblocking(flag) #若是flag为0,则将套接字设为非阻塞模式,不然将套接字设为阻塞模式(默认值)。非阻塞模式下,若是调用recv()没有发现任何数据,或send()调用没法当即发送数据,那么将引发socket.error异常。

s.makefile() #建立一个与该套接字相关连的文件

 

三、socket编程思路


3.一、TCP服务端:

1 建立套接字,绑定套接字到本地IP与端口

# socket.socket(socket.AF_INET,socket.SOCK_STREAM) , s.bind()

2 开始监听链接 #s.listen()

3 进入循环,不断接受客户端的链接请求 #s.accept()

4 而后接收传来的数据,并发送给对方数据 #s.recv() , s.sendall()

5 传输完毕后,关闭套接字 #s.close()


3.二、TCP客户端:

1 建立套接字,链接远端地址

# socket.socket(socket.AF_INET,socket.SOCK_STREAM) , s.connect()

2 链接后发送数据和接收数据 # s.sendall(), s.recv()

3 传输完毕后,关闭套接字 #s.close()


四、模拟聊天机器人实例

4.一、socket_server.py 服务端

#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
Socket服务器端
"""
import socket

sk = socket.socket()
sk.bind(('127.0.0.1', 8080,))
sk.listen(5)
#接收客户端请求
#链接,客户端地址信息
while True:
conn, address = sk.accept() #accept()阻塞
conn.sendall(bytes('欢迎致电10086', encoding='utf-8'))
while True:
ret_byte = conn.recv(1024)
ret_str = str(ret_byte, encoding='utf-8')
if ret_str == 'q':
break
conn.sendall(bytes('工号10086回复您:' + ret_str, encoding='utf-8'))

 

4.二、socket_client.py 客户端

#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
socket客户端
"""
import socket

ck = socket.socket()
ck.connect(('127.0.0.1', 8080))
ret_byte = ck.recv(1024)
ret_str = str(ret_byte, encoding='utf-8')
print(ret_str)
while True:
inp = input("请输入内容,按q退出 \n >>>")
if inp == 'q':
ck.sendall(bytes(inp, encoding='utf-8'))
break
else:
ck.sendall(bytes(inp, encoding='utf-8'))
ret_str = str(ck.recv(1024), encoding='utf-8')
print(ret_str)

ck.close()

 

五、基于socket实现文件上传实例

5.一、ftp_server.py

 
 
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
模拟发送文件的服务器端
"""

import socket

sk = socket.socket()
sk.bind(('127.0.0.1', 8080,)) #绑定套接字到本地IP与端口
sk.listen(5) #开始监听链接
#接收客户端请求
#链接,客户端地址信息
while True:
conn, address = sk.accept() # accept()阻塞
conn.sendall(bytes('欢迎访问个人ftp', encoding='utf-8'))
#先接收文件大小,而后再接收文件
ret_size = str(conn.recv(1024), encoding='utf-8')
conn.sendall(bytes('start', encoding='utf-8')) #给客户端发送一个确认信息,通知客户端开始发送文件,解决数据粘包的问题。
total_size = int(ret_size) #文件总大小
has_recv = 0 #已经接收的文件大小
f = open('new.png', 'wb')
#接收文件内容,直到获取完成
while True:
if total_size == has_recv:
break
data = conn.recv(1024)
f.write(data)
has_recv += len(data)
f.close()
 

 

5.二、ftp_client.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
模拟发送文件的客户端
"""
import socket
import os

ck = socket.socket()
ck.connect(('127.0.0.1', 8080))
ret_byte = ck.recv(1024) #接收服务器端返回的字节数据
ret_str = str(ret_byte, encoding='utf-8') #将字节数据转换成字符串
print(ret_str)
#首先向服务器发送文件的大小
file_size = os.stat('file1.png').st_size
ck.sendall(bytes(str(file_size), encoding='utf-8'))

ck.recv(1024) #接收一下服务器端的确认信息,再开始发送文件,解决数据粘包引发的系统异常问题
#发送文件
with open('file1.png', 'rb') as f:
for line in f:
ck.sendall(line)
ck.close()

 

六、socketserver模块实现并发操做

使用:
一、建立类,必须继承socketserver.BaseRequestHandler
二、定义handle方法
三、server_forever

socketserver模块实现并发操做实例:

#!/usr/bin/env python# -*- coding:utf-8 -*-"""socketserver模块实现并发操做"""import socketserverclass MyServer(socketserver.BaseRequestHandler):    def handle(self):        #self.request, self.client_address, self.server        conn = self.request        conn.sendall(bytes('欢迎致电10086', encoding='utf-8'))        while True:            ret_byte = conn.recv(1024)            ret_str = str(ret_byte, encoding='utf-8')            if ret_str == 'q':                break            conn.sendall(bytes('工号10086回复您:' + ret_str, encoding='utf-8'))if __name__ == '__main__':    server = socketserver.ThreadingTCPServer(('127.0.0.1', 8080), MyServer)    server.serve_forever()
相关文章
相关标签/搜索