zoukankan      html  css  js  c++  java
  • socket网络编程

    c/s架构:客户端/服务器架构

    C/S架构与socket的关系:

    我们学习socket就是为了完成C/S架构的开发

     

    为何学习socket一定要先学习互联网协议:

    1.首先:本节课程的目标就是教会你如何基于socket编程,来开发一款自己的C/S架构软件

    2.其次:C/S架构的软件(软件属于应用层)是基于网络进行通信的

    3.然后:网络的核心即一堆协议,协议即标准,你想开发一款基于网络通信的软件,就必须遵循这些标准。

    4.最后:就让我们从这些标准开始研究,开启我们的socket编程之旅

    socket层

     socket是什么

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

    所以,我们无需深入理解tcp/udp协议,socket已经为我们封装好了,我们只需要遵循socket的规定去编程,写出的程序自然就是遵循tcp/udp标准的。

     套接字发展史及分类

    套接字起源于 20 世纪 70 年代加利福尼亚大学伯克利分校版本的 Unix,即人们所说的 BSD Unix。 因此,有时人们也把套接字称为“伯克利套接字”或“BSD 套接字”。一开始,套接字被设计用在同 一台主机上多个应用程序之间的通讯。这也被称进程间通讯,或 IPC。套接字有两种(或者称为有两个种族),分别是基于文件型的和基于网络型的。 

    基于文件类型的套接字家族

    套接字家族的名字:AF_UNIX

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

    基于网络类型的套接字家族

    套接字家族的名字:AF_INET

    (还有AF_INET6被用于ipv6,还有一些其他的地址家族,不过,他们要么是只用于某个平台,要么就是已经被废弃,或者是很少被使用,或者是根本没有实现,所有地址家族中,AF_INET是使用最广泛的一个,python支持很多种地址家族,但是由于我们只关心网络编程,所以大部分时候我么只使用AF_INET)

    套接字工作流程

    服务端套接字函数
    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,sendall在待发送数据量大于己端缓存区剩余空间时,数据不丢失,循环调用send直到发完)
    s.recvfrom() 接收UDP数据
    s.sendto() 发送UDP数据
    s.getpeername() 连接到当前套接字的远端的地址
    s.getsockname() 当前套接字的地址
    s.getsockopt() 返回指定套接字的参数
    s.setsockopt() 设置指定套接字的参数
    s.close() 关闭套接字

    面向锁的套接字方法
    s.setblocking() 设置套接字的阻塞与非阻塞模式
    s.settimeout() 设置阻塞套接字操作的超时时间
    s.gettimeout() 得到阻塞套接字操作的超时时间

    面向文件的套接字的函数
    s.fileno() 套接字的文件描述符
    s.makefile() 创建一个与该套接字相关的文件
    import socket
    phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    phone.bind(('192.168.20.105',8080))
    phone.listen(5)
    while 1:
        conn,addr=phone.accept()
        print('线路是%s' % conn)
        print('地址是',addr)
        while 1:
            try:
                cmd = conn.recv(1024)
                conn.send(cmd.upper())
            except Exception:
                break
        conn.close()
    phone.close()
    tcp服务端
    import socket
    phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    phone.connect(('192.168.20.105',8080))
    while 1:
        sends = input('>>:')
        if not sends:continue
        phone.send(sends.encode('utf-8'))
        mess = phone.recv(1024)
        print(mess)
    
    phone.close()
    tcp客户端
    #_*_coding:utf-8_*_
    __author__ = 'Linhaifeng'
    from socket import *
    import subprocess
    
    ip_port=('127.0.0.1',8080)
    BUFSIZE=1024
    
    tcp_socket_server=socket(AF_INET,SOCK_STREAM)
    tcp_socket_server.bind(ip_port)
    tcp_socket_server.listen(5)
    
    while True:
        conn,addr=tcp_socket_server.accept()
        print('客户端',addr)
    
        while True:
            cmd=conn.recv(BUFSIZE)
            if len(cmd) == 0:break
    
            res=subprocess.Popen(cmd.decode('utf-8'),shell=True,
                             stdout=subprocess.PIPE,
                             stdin=subprocess.PIPE,
                             stderr=subprocess.PIPE)
    
            stderr=act_res.stderr.read()
            stdout=act_res.stdout.read()
            conn.send(stderr)
            conn.send(stdout)
    模拟远程ssh
    #_*_coding:utf-8_*_
    __author__ = 'Linhaifeng'
    import socket
    BUFSIZE=1024
    ip_port=('127.0.0.1',8080)
    
    s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    res=s.connect_ex(ip_port)
    
    while True:
        msg=input('>>: ').strip()
        if len(msg) == 0:continue
        if msg == 'quit':break
    
        s.send(msg.encode('utf-8'))
        act_res=s.recv(BUFSIZE)
    
        print(act_res.decode('utf-8'),end='')
    ssh客户端
    import socket
    import hashlib
    import subprocess
    import os
    
    phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)   #重用地址
    phone.bind(('192.168.20.105',8081))
    phone.listen(5)
    while 1:
        conn,addr=phone.accept()
        print('线路是%s' % conn)
        print('地址是',addr)
        tag = True
        while 1:
            while tag:
                user = conn.recv(1024).decode('utf-8')
                pwd = conn.recv(1024).decode('utf-8')
                md5_obj = hashlib.md5(user.encode('utf-8'))
                s = pwd+user
                print(s)
                md5_obj.update(s.encode('utf-8'))
                pwd = md5_obj.hexdigest()
                print(pwd)
                if user == 'egon'and pwd=='82bdb4164c14585f32e70ec0a37b3569':
                    conn.send('right'.encode('utf-8'))
                    tag = False
                    break
                else:
                    conn.send('用户名或密码错误,请重新输入!'.encode('utf-8'))
            try:
                cmd = conn.recv(1024)
                res = subprocess.Popen(cmd.decode('utf-8'),shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
                mes = res.stdout.read()
                mesr = res.stderr.read()
                conn.send(str(len(mes+mesr)).encode('utf-8'))
                conn.send(mes+mesr)
            except Exception:
                break
        conn.close()
    phone.close()
    增加登陆认证和解决粘包
    import socket
    import time
    
    phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    phone.connect(('192.168.20.105',8081))
    tag = True
    while 1:
        while tag:
            user = input('username:')
            pwd = input('password:')
            phone.send(user.encode('utf-8'))
            phone.send(pwd.encode('utf-8'))
            time.sleep(1)
            mes = phone.recv(1024).decode('utf-8')
            print(mes)
            if mes =='right':
                tag = False
                break
        cmd = input('>>:')
        if not cmd:continue
        phone.send(cmd.encode('utf-8'))
        lens = phone.recv(1024).decode('utf-8')
        mes = phone.recv(1024)
        while 1:
            if int(lens)>len(mes):
                mes+=phone.recv(1024)
            else:
                break
        print(mes.decode('gbk'))
    
    phone.close()
    客户端
  • 相关阅读:
    ADODB.Recordset错误800a0cb3"的解决方
    C++ primer第一章 C++概述 纪要
    [收藏]一些电平转换方法
    “当传递具有已修改行的 DataRow 集合时,更新要求有效的 UpdateCommand”错误解决
    关于句柄的一些知识 Handle (computing) Wiki
    “/”应用程序中的服务器错误。当前标识(NT AUTHORITY/NETWORK SERVICE)没有对“C:/WINDOWS/Microsoft.NET/Framework/v2.0.50727/Temporary ASP.NET Files”的写访问权
    C++中 __stdcall,__cdecl, __fastcal区别简介
    [How To]使用Wildfish进行开发新Solution配置篇
    关于ISeries的代码生成器
    [How To]如何使用Wildfish进行ISeries项目开发数据库建立部分
  • 原文地址:https://www.cnblogs.com/pythonclass/p/7405228.html
Copyright © 2011-2022 走看看