Python 网络编程
Python 提供了两个级别访问的网络服务。:
今天主讲: 低级别的网络服务支持基本的 Socket,它提供了标准的 BSD Sockets API,可以访问底层操作系统Socket接口的全部方法。
了解一下: 高级别的网络服务模块 SocketServer, 它提供了服务器中心类,可以简化网络服务器的开发
socket是什么
Socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯。
Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议
所以,我们无需深入理解tcp/udp协议,socket已经为我们封装好了,我们只需要遵循socket的规定去编程,写出的程序自然就是遵循tcp/udp标准的。
tcp: 可靠,有状态的,长连接的协议,像打电话一样
udp: 不可靠,无连接,像发短信一样。发送的包的顺序要有编号
socket()函数
Python 中,我们用 socket()函数来创建套接字
语法: socket.socket([family[, type[, proto]]])
参数:
family: 套接字家族可以使AF_UNIX或者AF_INET
type: 套接字类型可以根据是面向连接的还是非连接分为SOCK_STREAM或SOCK_DGRAM
protocol: 一般不填默认为0.
Socket 对象(内建)方法:
一. 服务器端套接字:
s.bind() : 绑定地址(host,port)到套接字, 在AF_INET下,以元组(host,port)的形式表示地址。s.listen() :开始TCP监听。backlog指定在拒绝连接之前,操作系统可以挂起的最大连接数量。该值至少为1,大部分应用程序设为5就可以了。
s.accept() :被动接受TCP客户端连接,(阻塞式)等待连接的到来
二 . 客户端套接字
s.connect() 主动初始化TCP服务器连接,。一般address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。
s.connect_ex() connect()函数的扩展版本,出错时返回出错码,而不是抛出异常
三. 公共用途的套接字函数
s.recv() 接收TCP数据,数据以字符串形式返回,bufsize指定要接收的最大数据量。flag提供有关消息的其他 信息,通常可以忽略。
s.send() 发送TCP数据,将string中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能 小于string的字节大小。s.sendall() 完整发送TCP数据,完整发送TCP数据。将string中的数据发送到连接的套接字,但在返回之前 会尝试发送所有数据。成功返回None,失败则抛出异常。
s.close() 关闭套接字
实列: 服务端 代码
import socket #首先到入模块
#1.创建服务端
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#2.绑定IP和端口
server.bind(("192.168.0.193",8000))
#2.5 设置最大挂起链接数
server.listen(5)
print("服务端,启动等待客户端链接...")
#3.等待客户端连接 如果有链接 将返回一个链接对象和对方的地址
conn,address = server.accept()
while True:
#4.接收客户端发过来 多大字节的数据
msg = conn.recv(1024)
print("客户端: ",msg.decode()) #把接收的bytes转出去
#5.给客户端回复数据
conn.sendall(input('服务端: ').encode('utf-8'))
#6.结束了,直接关闭服务器
conn.close()
server.close()
客户端 代码
import socket
#1.创建客户端
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#2.建立链接
client.connect(("192.168.0.193",8000))
print("客户端,成功连接服务器 n 结束")
while True:
msg = input("客户端: ")
if msg.__eq__('n'): break
# 3.发消息 格式是: bytes 以utf-8的字符集去转成bytes
client.send(msg.encode('utf-8'))
#等待回应 并读取回复
msg = client.recv(1024)
print('服务器: ',msg.decode())
#关闭连接
client.close()
注: 先启动服务端,在启动客户端
这个代码就好比,一个人有俩个手机在进行聊天,有点意思
群聊: 适合很多的
也是分客户端,和服务端的 先来服务端
#群聊的服务端
import socket,threading
#1.创建服务端
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#2.绑定IP和端口
server.bind(("192.168.199.228",8000))
#2.5 设置最大挂起链接数
server.listen(5)
print("服务端,启动等待客户端链接...")
#中间转换数据的变量
message = ''
#创建一把锁
lock = threading.Lock()
Cond = threading.Condition(lock=lock)
#主要代码 不停的收 不停的发
def recv_msg(conn,adress):
while True:
global message
msg = conn.recv(1024)
Cond.acquire() # 上锁
message = str(address)+':'+msg.decode()
print('收到: ',message)
Cond.notify_all() #唤醒其他给我发消息的线程
Cond.release() #释放锁
def send_msg(conn,address):
global message
while True:
Cond.acquire()
Cond.wait()
Cond.release()
conn.sendall(message.encode('utf-8'))
print('发送'+message)
#为每一个连接着提供收和发的线程
while True:
conn, address = server.accept()
threading._start_new_thread(recv_msg,(conn,address)) #不停的收
threading._start_new_thread(send_msg,(conn,address)) #不停的发
客户端:
#创建客户端
import socket,threading
#1.创建客户端
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#2.建立链接
client.connect(("192.168.199.228",8000))
#收取其他用户数据
def recv_msg():
while True:
msg = client.recv(1024)
print("收到: ",msg.decode())
threading._start_new_thread(recv_msg,())
#不停的发
while True:
msg = input('请数据信息: ')
client.send(msg.encode('utf-8'))
勤学苦练!!!!