• Python,socket编程


    TCP协议 IP+端口

    应用层协议做的事不同,但都离不开数据的交换,本质上都是收和发~
    为什么要三次握手?
    目标机器可能不存在,握手期间,发送方也可能down掉。
    客户端————服务器,先发请求的那个是客户端,客户端发送的信息的端口是随机的。。服务器端的端口是固定的
    先要有接收端,相当于服务器
    接收端要申请端口号,服务要启动正常运行开始监听该端口

    地址簇Socket Families

    相当于网络层的一个东西
    socket.AF_UNIX unix本机进程间通信
    socket.AF_INET IPV4
    socket.AF_INET6 IPV6

    a进程和b进程想通信,没有网络的情况下。
    a先dump,b再load。通过硬盘的话速度慢,默认在内存中a进程是不能访问b进程数据的,想快速通信可以借助AF_UNIX,本地启动一个socket在七层协议里转一圈
    a进程传给b

    Socket Types

    socket.SOCK_STREAM #for tcp
    socket.SOCK_DGRAM #for udp
    socket.SOCK_RAW
    #原始套接字,普通的套接字无法处理ICMP、IGMP等网络报文,而SOCK_RAW可以;
    其次,SOCK_RAW也可以处理特殊的IPv4报文;此外,利用原始套接字,可以通过IP_HDRINCL套接字选项由用户构造IP头。
    牛逼了可以伪造IP地址,DDOS攻击,洪水攻击,发送大量请求导致服务关闭
    a访问b要三次握手,a发第一次,后a改自己的IP再发请求,b的回应到不了a
    导致b端该连接出现挂起,a再改IP地址发请求..再挂起..
    socket.SOCK_RDM
    #是一种可靠的UDP形式,即保证交付数据报但不保证顺序。SOCK_RAM用来提供对原始协议的低级访问,
    在需要执行某些特殊操作时使用,如发送ICMP报文。SOCK_RAM通常仅限于高级用户或管理员运行的程序使用。
    socket.SOCK_SEQPACKET #废弃了

    实例:先启动服务器监听端口,再启动客户端:

    # 服务器
    import socket
    
    server = socket.socket()
    server.bind(("localhost",7000))#只是绑定要监听的端口
    server.listen() #监听,我要监听这个端口
    print("我开始监听7000端口了---")
    conn,addr = server.accept()  #等电话,conn就是连接实例,addr为源IP地址随机的
    
    print("请求来了")
    # data = server.recv(1024) #接收1024
    # 通话中又来一个电话要切换,server.switch()要知道先后顺序,可以给每个请求标记就是上面的conn
    data = conn.recv(1024)
    print("recv:",data)
    conn.send(data.upper())
    server.close()
    '''输出:
    我开始监听7000端口了---
    请求来了
    recv: b'helloworld'
    '''
    #客户端
    import socket
    
    client = socket.socket()
    #声明socket类型,同时生成socket对象
    #定义协议类型默认是family=AF_INET, type=SOCK_STREAM
    client.connect(("localhost",7000))
    client.send(b"helloworld")
    data = client.recv(1024)
    print("recv:", data)
    client.close()
    
    #输出:recv: b'HELLOWORLD'

     可以看出上面这种,客户端和服务器端说一句话就断了,那么我想不停地通信怎么办呢?????可以加上死循环

    # 服务器
    import socket
    
    server = socket.socket()
    server.bind(("localhost",7000))
    server.listen() 
    print("我开始监听7000端口了---")
    conn,addr = server.accept()  
    print("请求来了")
    
    while True:
        data = conn.recv(1024)
        print("recv:",data)
        conn.send(data.upper())
    server.close()
    #客户端
    import socket
    
    client = socket.socket()
    client.connect(("localhost",7000))
    while True:
        msg = input(">>:").strip()
        client.send(msg.encode("utf8"))
        data = client.recv(1024)
        print("recv:", data.decode())
    client.close()

    perfect~~~试了几次之后。。。

    又发现一个问题:客户端断了服务器端为什么也断了?

    Windows服务器出错:ConnectionResetError: [WinError 10054] 远程主机强迫关闭了一个现有的连接。

    Linux服务器:会进入进入死循环,recv不到数据(recv到""空),可以服务器端判断data接收的是否为空,是空break死循环

    那么请问,该如何让某一个客户端断了之后其他客户端可以继续连接呢?

    先试试。。可以再在conn上加一层死循环

    ,加了之后Windows还是报10054的错误,Linux里面只能一个通话,另一个占线(挂起),上一个断开了才能跟挂起的那个通话

    后面排着队,上一个结束到下一个,异步的情况下listen(3)里面可以给数字,表示最多挂起几个,。一般不要超过10个

    客户端如果发一个空过去(直接回车),就卡死了,怎么回事呢?是服务器没收到还是什么呢?

    所以不能send空,不能send空,不能send空,重要的事说三遍。。。所以就要在客户端判断一下

    那么可以把客户端模拟成SSH呢?

    服务器端搞成os.popen().read()就可以了,如果某命令执行结果超过1024byte,客户端还在继续发命令。。那么服务器端还是会不停执行

    但客户端每次只能接收1024字节,数据全存在缓冲区排队了

    那么,让客户端一次能接收很大的数据会怎样呢???

    发一个大文件,虽然客户端一次可以接很大,但是服务器端每次只能发32768,依据操作系统而定,so

    让客户端全发,循环发sendall()会怎样呢?

    但是神奇了,客户端接收开始有限制了,好像每次最多10M,依系统区别这个也有区别(在centos上试的,而有的系统还会出错)

    so...看来。。。没办法一次收过来,带宽有限制,网卡也有限制。。recieve有限制的,send也有限制的。

  • 相关阅读:
    使用 libevent 和 libev 提高网络应用性能
    An existing connection was forcibly closed by the remote host
    各种浏览器的兼容css
    vs输出窗口,显示build的时间
    sass
    网站设置404错误页
    List of content management systems
    css footer not displaying at the bottom of the page
    强制刷新css
    sp_executesql invalid object name
  • 原文地址:https://www.cnblogs.com/revo/p/7401536.html
Copyright © 2020-2023  润新知