Python基础-面向对象-网络传输套接字

简介

socket是应用层与TCP/IP协议通信的中间的软件抽象层,它是一组接口。把复杂的TCP/IP协议足隐藏在接口后面,对用户来说,一组简单的接口就是全部,socket去组织数据,以符合指定的协议

  • recv在缓冲区为空时,阻塞
  • recvfrom在缓冲区为空时,接收为空的字节

基于文件的套接字 AF_UNIX

基于文件的套接字调用的就是底层的文件系统来取数据,两个套接字进程运行在统一机器,可以通过访问同一个文件系统间接完成通信~

基于网络类型的套接字 AF_INET

基于网络作为介质实现通信,还有AD_INET6,被用于ipv6等其它网络类型套接字

示意图

TCP客户端                       TCP服务端

socket()                        socket()
    |                               ↓
    |                            bind()
    |                               ↓
    |                           listen()
    ↓                               ↓
connect()   <--建立连接-->       accept()
    ↓                               ↓   阻塞,直到有客户端连接
write()     <--请求数据-->        read()
    ↓                               ↓   处理请求
read()      <--回应数据---       write()
    ↓                               ↓
close()     ---结束连接-->        read()
                                    ↓
                                  close()

TCP传输套接字

简单示例

服务端

# -*- coding:utf8 -*-
import socket
test = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#定义socket通信方式和通信协议。socket.AF_INET基于网络通信,socket.SOCK_STREAM基于TCP协议
test.bind(('127.0.0.1',8000))      #定义通信ID
test.listen(5)                     #定义最大通信监听数
conn,addr = test.accept()          #定义对话连接
msg = conn.recv(1024)              #定义接收字节信息
print('客户端发送的消息是:',msg)
conn.send(msg.upper())              #定义发送消息
conn.close()                        #连接关闭
test.close()                        #程序关闭
客户端发送的消息是: b'hello'

客户端

# -*- coding:utf8 -*-
import socket
test = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#定义socket通信方式和通信协议。socket.AF_INET基于网络通信,socket.SOCK_STREAM基于TCP协议
test.connect(('127.0.0.1',8000))           #定义通信ID,服务器的地址和端口
test.send('hello'.encode('utf-8'))         #定义发送内容
data = test.recv(1024)                     #定义接收字节信息
print('收到服务端的发来的消息是:',data)   
收到服务端的发来的消息是: b'HELLO'

TCP网络传输套接字示例

原示例

import socket
test = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

优化示例

form socket import *
test = socket(AF_INET,SOCK_STREAM)

==也可以将值以变量形式写入到配置文件中导入==

服务端优化示例

# -*- coding:utf8 -*-
from socket import *

test = socket(AF_INET,SOCK_STREAM)
ip_port = ('127.0.0.1',8000)
back_log = 5
buffer_size = 1024

test.bind(ip_port)                 #定义通信ID
test.listen(back_log)              #定义最大通信监听数
conn,addr = test.accept()          #定义对话连接

msg = conn.recv(1024)  # 定义接收字节信息
print('客户端发送的消息是:',msg)
conn.send(msg.upper())              #定义发送消息
conn.close()                        #连接关闭
test.close()                        #程序关闭

循环发送示例

服务端

# -*- coding:utf8 -*-
from socket import *

tcp_servive = socket(AF_INET,SOCK_STREAM)
ip_port = ('127.0.0.1',8000)
back_log = 5
buffer_size = 1024

tcp_servive.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)       #防止服务端再次启用导致端口被占用错误
tcp_servive.bind(ip_port)                               #定义通信ID
tcp_servive.listen(back_log)                            #定义最大通信监听数

while True:
    print("服务端程序运行中。。。")
    conn, addr = tcp_servive.accept()       #定义对话连接(循环收发消息)
    while True:
        try:                                #客户端异常断开处理
            msg = conn.recv(buffer_size)    #定义接收字节信息
            print('客户端发送的消息是:',msg.decode('utf-8'))
            conn.send(msg.upper())          #定义发送消息
        except Exception:
            print("客户端强制断开!")
            break
conn.close()                               #连接关闭
tcp_servive.close()                        #程序关闭

客户端

# -*- coding:utf8 -*-
from socket import *

ip_port = ('127.0.0.1',8000)
buffer_size = 1024

tcp_client = socket(AF_INET,SOCK_STREAM)
tcp_client.connect(ip_port)                  #定义通信ID,服务器的地址和端口

while True:
    msg = input(">>>请输入需要发送的消息!".strip())
    if not msg:continue                                 #判断值是否为空
    tcp_client.send(msg.encode('utf-8'))                #定义发送内容
    print('客户端已经发送消息:',msg)
    data = tcp_client.recv(buffer_size)                 #定义接收字节信息
    print('收到服务端的发来的消息是:', data.decode('utf-8'))
tcp_client.close()

TCP协议远程执行命令示例

粘包特性

服务端

from socket import *
import subprocess
ip_port = ('127.0.0.1',8080)
back_log = 5
buffer_size = 4096

tcp_server = socket(AF_INET,SOCK_STREAM)
tcp_server.bind(ip_port)
tcp_server.listen(back_log)

while True:
    conn,addr=tcp_server.accept()           #建立连接
    print('新的客户端链接',addr)
    while True:
            #接收信息
        try:
            cmd=conn.recv(buffer_size)
            if not cmd:break
            print('收到客户端的命令',cmd.decode('utf-8'))
            #执行命令
            res=subprocess.Popen(cmd.decode('utf-8'),shell=True,
                                 stderr=subprocess.PIPE,
                                 stdout=subprocess.PIPE,
                                 stdin=subprocess.PIPE)
            err=res.stderr.read()
            if err:
                cmd_res=err
            else:
                cmd_res=res.stdout.read()

            #发送信息
            if not cmd_res:
                cmd_res='执行成功'.encode('gbk')
            conn.send(cmd_res)
        except Exception as e:
            print(e)
            break

客户端

from socket import *
ip_port = ('127.0.0.1',8080)
back_log = 5
buffer_size = 4096

tcp_client = socket(AF_INET,SOCK_STREAM)
tcp_client.connect(ip_port)

while True:
    cmd=input('>>请输入需要执行的命令: ').strip()
    if not cmd:continue
    if cmd == 'quit':break

    tcp_client.send(cmd.encode('utf-8'))
    cmd_res=tcp_client.recv(buffer_size)
    print('命令的执行结果是 ',cmd_res.decode('gbk'))
tcp_client.close()

UDP网络传输套接字

简单示例

服务端

udp_service = socket()      #创建一个服务器套接字
udp_service.bind()          #绑定服务器套接字
while True:                 #服务器通讯循环
    udp_service.recvfrom()  #服务端接收消息
    udp_sendto.recvfrom()   #服务端发送消息
udp_service.close()         #关闭服务端套接字

客户端

udp_client = socket()       #创建一个客户端套接字
while True:                 #客户端通讯循环
    udp_service.recvfrom()  #服务端接收消息
    udp_sendto.recvfrom()   #服务端发送消息
udp_client.close()          #关闭客户端套接字

UDP网络传输套接字示例示例

服务端示例

# -*- coding:utf-8 -*-
from socket import *
ip_port = ('127.0.0.1',8080)                    #定义通信ID
buffer_size = 4096                              #定义接收字节信息
udp_service = socket(AF_INET,SOCK_DGRAM)        #定义socket通信方式和通信协议。socket.AF_INET基于网络通信,socket.SOCK_STREAM基于TCP协议

udp_service.bind(ip_port)                       #通信ID

print("服务端运行中...")
while True:
    msg,addr = udp_service.recvfrom(buffer_size)     #定义接收字节信息(元组形式)
    print("接收到的消息是:",msg.decode('utf-8'))    #打印接受到的字节信息
    udp_service.sendto(msg.upper(),addr)             #返回并修改传输值

客户端示例

# -*- coding:utf-8 -*-
from socket import *
ip_port = ('127.0.0.1',8080)                    #定义通信ID
buffer_size = 4096                              #定义接收字节信息
udp_client = socket(AF_INET,SOCK_DGRAM)         #定义socket通信方式和通信协议。socket.AF_INET基于网络通信,socket.SOCK_STREAM基于TCP协议

while True:
    msg = input(">>>请输入您要发送的内容".strip())
    udp_client.sendto(msg.encode('utf-8'),ip_port)  #定义发送内容和到达地址

    msg,addr = udp_client.recvfrom(buffer_size)     #定义接收字节信息(元组形式)
    print(msg.decode('utf-8'))                      #打印返回的字节信息

UDP协议远程执行命令示例

不粘包特性

服务端

from socket import *
import subprocess
ip_port=('127.0.0.1',8080)
back_log=5
buffer_size=4096

udp_server=socket(AF_INET,SOCK_DGRAM)
udp_server.bind(ip_port)

while True:
    #接收消息
    cmd,addr=udp_server.recvfrom(buffer_size)

    # 执行命令,得到命令的运行结果cmd_res
    res = subprocess.Popen(cmd.decode('utf-8'), shell=True,
                           stderr=subprocess.PIPE,
                           stdout=subprocess.PIPE,
                           stdin=subprocess.PIPE)
    err = res.stderr.read()
    if err:
        cmd_res = err
    else:
        cmd_res = res.stdout.read()

    if not cmd_res:
        cmd_res='执行成功'.encode('gbk')

    #发送消息
    udp_server.sendto(cmd_res,addr)

客户端

from socket import *
ip_port=('127.0.0.1',8080)
back_log=5
buffer_size=4096

udp_client=socket(AF_INET,SOCK_DGRAM)

while True:
    cmd=input('>>请输入需要执行的命令: ').strip()
    if not cmd:continue
    if cmd == 'quit':break

    udp_client.sendto(cmd.encode('utf-8'),ip_port)
    cmd_res,addr=udp_client.recvfrom(buffer_size)
    print('命令的执行结果是 ',cmd_res.decode('gbk'),end='')

udp_client.close()

猜你喜欢

转载自my.oschina.net/zhaojunhui/blog/1806544