26、套接字

Socket层

Socket套接字,是从osi七层抽象出来的抽象层,抽象了网络层和传输层,跟语言无关,任何语言都会有socket的封装。Socket是专门给开发人员用的

一、基于Tcp的socket套接字(重点)

1.1、服务端

import socket  # 导入socket模块
'''
第一个socket是模块名,第二个socket是模块下的类名。
server=socket.socket(family=socket.AF_INET,type=socket.SOCK_STREAM)
我们参数可以不写,不写默认就是TCP服务端
'''
server = socket.socket()
# 绑定地址跟端口,传一个元组,监听的地址,监听的端口
server.bind(('127.0.0.1', 8008))  # 192.168.12.44
# 监听,半连接池是5,可以缓冲5个
server.listen(5)
# 等待用户连接(看源码,有两个返回结果)
# sock是连接对象,以后这个服务端和客户端交互,使用这个对象交互。 addr是客户端地址(ip和端口)
sock, addr = server.accept()
# 接收客户端发给我的消息
data = sock.recv(1024)
print(data)  # 打印

# 服务端给客户端发送消息(必须是byte格式)
sock.send(b'hello,world')

sock.close()  # 关闭连接对象
server.close()  # 关闭服务

1.2、客户端

import socket

# 创建socket对象
client = socket.socket()
# 连接服务端
client.connect(('127.0.0.1', 8008))
# 给服务端发送信息
client.send(b'sb')
# 收到了服务端的信息
data = client.recv(1024)
print(data)  # 打印
client.close()  # 关闭

二、加入链接循环的套接字服务端

我们需要服务端服务客户端完毕之后,继续服务下一个客户,而不是服务一次就关闭,则需要加入链接循环。

2.1 服务端

import socket  # 导入socket模块

'''
type=socket.SOCK_STREAM -是TCP服务端
type=socket.SOCK_DGRAM  -是UDP服务端
'''
server = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
server.bind(('127.0.0.1', 8008))  # 绑定地址跟端口
server.listen(5)  # 监听

while True:
    sock, addr = server.accept()  # 等待用户连接
    data = sock.recv(1024)  # 接受客户端传来的信息
    print(data)  # 打印
    sock.send('hello,world'.encode('utf-8'))  # 给客户端发送信息
    sock.close()  # 关闭连接对象

server.close()  # 关闭服务

2.2 客户端

import socket

client = socket.socket()
client.connect(('127.0.0.1', 8008))

client.send('sb'.encode('utf-8'))

data = client.recv(1024)
print(data)

client.close()

三、加入通信循环的套接字服务端

我们需要服务端服务客户端时,客户端可以不停的发送消息,服务端一直为客户端服务。一个客户端结束后,服务端还可以继续服务下一个,需要加入通信循环

3.1 服务端

import socket  # 导入socket模块

server = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
server.bind(('127.0.0.1', 8008))  # 绑定地址跟端口
server.listen(5)  # 监听

print('开始等待客户端连接')
while True:
    sock, addr = server.accept()  # 等待用户连接

    while True:
        try:
            data = sock.recv(1024)  # 接受客户端传来的信息
            if len(data) == 0:  # 表示客户端正常断开了,结束通信循环
                break
            print(data.decode('utf-8'))  # 解码,打印用户消息
            sock.send('hello,world'.encode('utf-8'))  # 服务端给客户端发送消息
        except Exception as e:  # 表示客户端非正常断开,需要异常捕获
            print(e)
            break
    sock.close()  # 关闭连接对象
server.close()  # 关闭服务

3.2 客户端

import socket

client = socket.socket()
client.connect(('127.0.0.1', 8008))

while True:
    input_data = input('请输入发送给客户端的内容(输入q退出):')
    if input_data == 'q':
        break
    client.send(input_data.encode('utf-8'))

    data = client.recv(1024)
    print(data.decode('utf-8'))

client.close()

四、基于UDP的套接字客户端和服务端

4.1 服务端

import socket

# udp的服务端
server = socket.socket(type=socket.SOCK_DGRAM)

# 监听地址和端口
server.bind(('127.0.0.1', 82))

# 不需要listen,直接建立链接
print('等待客户端发送数据:')
while True:
#recvfrom回返回数据和客户端的地址
    data,addr = server.recvfrom(1024)
    print(data)
    print(addr)
    server.sendto(data.upper(), addr)

server.close()

4.2 客户端

import socket

client = socket.socket(type=socket.SOCK_DGRAM)
client.sendto(b'sb',('127.0.0.1',82))
# data,addr=client.recvfrom(1024)
# data,_=client.recvfrom(1024)
data = client.recv(1024)
print(data)
# print(addr)

client.close()

五、客户端从服务端下载文件

5.1、服务端

import socket
server = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
server.bind(('127.0.0.1', 81))
server.listen(1)

print('开始等待客户端连接了')
while True:
    sock, addr = server.accept()
    print(sock)
    print('客户端的地址是:', addr)

    # 等待客户端发送过来的数据,如果客户端没有发送数据,会一直等着
    while True:
        try:
            data = sock.recv(1024)
            if len(data) == 0:  # 这个表示客户端正常断开了,结束通信循环
                break
            print(data.decode('utf-8'))

            # 客户端传入一个文件名,直接打开文件,发送给客户端
            with open(data, 'rb') as f:
                sock.send(f.read())
        except Exception as e:
            print(e)  # 客户端非正常断开,需要异常捕获
            break

    sock.close()
server.close()

5.2、客户端

import socket

client=socket.socket()
client.connect(('127.0.0.1',81))

while True:
    input_data=input('''
    请选择要下载的文件
        1.txt
        2.txt
        3.txt
    按q退出
    ''')
    if input_data=='q':
        break
    client.send(input_data.encode('utf-8'))

    data=client.recv(1024)
    with open('download_'+input_data,'wb') as f:
        f.write(data)
    print('%s下载成功'%input_data)

client.close()
posted @ 2021-04-21 20:49  黑影Poco  阅读(90)  评论(0)    收藏  举报