python socket编程基础

socket 是一组接口,将复杂的TCP/IP协议封装在接口内,我们只需要遵循socket的规定去编程就可以了。

套接字:

基于文件类型的套接字:AF_UNIX

在Unix系统上,基于文件的套接字运行在同一台机器上,通过访问同一个文件间接完成通信。

基于网络类型的套接字:AF_INET

套接字工作流程:

socket()模块函数用法

服务端套接字函数:

s.bind() 绑定(主机,端口号)到套接字

s.listen() 开始TCP监听

s.accept() 被动接受TCP客户的连接,(阻塞式)等待连接的到来

客户端套接字函数:

s.connect()  主动初始化TCP服务器连接

s.connect_ex()  connect()函数的扩展版本,出错时返回错误,而不是抛出异常。

公共用途的套接字函数:

s.recv()   接收TCP数据

s.send()   发送TCP数据(send在待发送数据量大于己端缓存剩余空间时,数据丢失,不会发完)

s.sendall()  发送TCP数据(在待发送数据量大于己端缓存区剩余空间时,数据不会丢失,循环调用send直到发完)

s.recvfrom()  接收UDP数据

s.sendto()     发送UDP数据

s.getpeername() 连接当前套接字的远端地址

s.getsocketname() 当前套接字的地址

s.getsockopt  返回当前套接字的参数

s.setsockopt() 设置指定套接字的参数

s.close()  关闭套接字

面向锁的套接字方法:

s.setblocking() 设置套接字的阻塞与非阻塞方式

s.settimeout() 设置套接字操作的超时时间

s.gettimeout()  得到阻塞套接字操作的超时时间

面向文件的套接字的函数:


s.fileno()  套接字的文件描述符

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

实例:利用打电话模拟socket通信

简单的套接字:

import socket
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)#买电话
phone.bind(('192.168.20.6',8090))
phone.listen(5)

print('string......')
conn,client_adrr = phone.accept()#等电话,三次握手得到的双向链接,和客户端的IP及端口组成的元祖分别赋值给conn client_addr
print(conn,client_adrr)

#收,发消息   服务端是先收再发
data = conn.recv(1024)#设置最大接收为1024个字节
print('client data:<%s>'%data)
conn.send(data.upper())

conn.close()
phone.close()
服务端
import socket
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)#买手机
phone.connect(('192.168.20.6',8090))#绑定手机卡

#发,收 消息
phone.send('hello sb'.encode('utf-8'))
data = phone.recv(1024)
print('sever back res <%s>'%data)

phone.close()
客户端

循环通信:

import socket
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.bind(('192.168.20.6',9080))
phone.listen(5)

print('string.....')
conn,client_adrr = phone.accept()
print(conn,client_adrr)#通信建立成功打印
while True:
    data = conn.recv(1024)
    print('client data:<%s>'%data)
    conn.send(data.upper())

conn.close()
phone.close()
服务端
import socket
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect(('192.168.20.6',9080))

#发,收消息
while True:
    msg = input('>>>:')
    if not msg:continue
    phone.send(msg.encode('utf-8'))
    data = phone.recv(1024)
    print('sever back data:<%s>'%data)

phone.close()
客户端

加上链接的循环,上面两种方法一次都只能有一个客户端访问,利用链接循环,挨个访问

import socket
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
phone.bind(('192.168.20.6',8889))
phone.listen(5)
while True:
    print('string.....')
    conn,client_addr = phone.accept()
    print(conn,client_addr)

    while True:
        try:
            data = conn.recv(1024)
            if not data:break
            print('client data:<%s>'%data)
            conn.send(data.upper())
        except Exception:
            break


    conn.close()
phone.close()
服务端
import socket
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect(('192.168.20.6',8889))

while True:

    msg = input(">>>:").strip()
    if not msg:continue
    phone.send(msg.encode('utf-8'))
    data  = phone.recv(1024)
    print('server back res:<%s>'%data)
phone.close()
客户端1
import socket
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect(('192.168.20.6',8889))

while True:

    msg = input(">>>:").strip()
    if not msg:continue
    phone.send(msg.encode('utf-8'))
    data  = phone.recv(1024)
    print('server back res:<%s>'%data)
phone.close()
客户端2
import socket
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect(('192.168.20.6',8889))

while True:

    msg = input(">>>:").strip()
    if not msg:continue
    phone.send(msg.encode('utf-8'))
    data  = phone.recv(1024)
    print('server back res:<%s>'%data)
phone.close()
客户端3

模拟ssc远程控制:

import socket
import subprocess  #导入模块,执行模拟ssc远程控制命令
import hashlib
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
phone.bind(('192.168.20.6',8909))
phone.listen(5)
print('staring.....')
conn,client_addr = phone.accept()
while True:
    username = conn.recv(10240).decode('utf-8')
    print(username)
    password = conn.recv(10240).decode('utf-8')
    print(password)
    user_md5 = '34d75c9634ae59d1581a5251b981f98c'
    paw_md5 = '98699a6ffb4200d29ff79e7f0c20a7db'
    user = hashlib.md5()
    paw = hashlib.md5()

    user.update(bytes("szq"+username+"hello",encoding='utf-8'))

    paw.update(bytes("szq"+password+"hello",encoding='utf-8'))
    if user.hexdigest()==user_md5 and paw.hexdigest()== paw_md5:

        conn.send('ok'.encode('utf-8'))

        while True:
            try:
                cmd = conn.recv(1024)
                if not cmd: break
                res = subprocess.Popen(cmd.decode('utf-8'),shell=True,
                                       stdout=subprocess.PIPE,#标准正确输入流
                                       stderr=subprocess.PIPE)#标准错误输出流
                stdout = res.stdout.read()
                stderr = res.stderr.read()

                conn.send(stdout+stderr)
            except Exception:
                break
        conn.close()
    else:
        conn.send('no'.encode('utf-8'))
phone.close()
服务端
import socket
import getpass
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect(("192.168.20.6",8909))

for i in range(3):
    print('用户验证')
    user = input('admin:').strip()
    phone.send(user.encode('utf-8'))
    paw = input('password:').strip()
    phone.send(paw.encode('utf-8'))
    data = phone.recv(10240)
    if data.decode('utf-8') == 'ok':
        print('login successful')
        while True:
            cmd=input('>>>>:').strip()
            if not cmd:continue
            phone.send(cmd.encode('utf-8'))
            cmd_res=phone.recv(10240)
            print(cmd_res.decode('gbk'))

    else:
        print('login failed,您还有{}次机会!'.format(2-i))
phone.close()
客户端
原文地址:https://www.cnblogs.com/shengzhongqiu/p/7411139.html