• 1.socket网络编程


    套接字工作流程

    先从服务器端说起。服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束。

    Socket Families(地址簇)

    socket.AF_UNIX unix本机进程间通信 

    socket.AF_INET IPV4 

    socket.AF_INET6  IPV6

    Socket Types

    socket.SOCK_STREAM  #for tcp

    socket.SOCK_DGRAM   #for udp

    Socket 参数

    s.bind(address)     绑定(host,port)

    s.listen(backlog)   开始监听传入连接。backlog指定在拒绝连接之前,可以挂起的最大连接数量

    s.accept()             接受连接并返回(conn,address),其中conn是新的套接字对象,可以用来接收和发送数据。address是连接客户端的地址。

    s.connect(address)      address的格式为元组(hostname,port)

    s.setblocking(bool)    是否阻塞(默认True),如果设置False,那么accept和recv时一旦无数据,则报错。

    s.close()                  关闭套接字

    s.recv(bufsize)        bufsize指定最多可以接收的数量

    s.send(string)          将string中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能小于string的字节大小。即:可能未将指定内容全部发送。

    s.sendall(string)       将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常。

                                     内部通过递归调用send,将所有内容发送出去。

    s.settimeout(timeout)  设置套接字操作的超时期,timeout是一个浮点数,单位是秒。值为None表示没有超时期。一般,超时期应该在

                                        刚创建套接字时设置,因为它们可能用于连接的操作(如 client 连接最多等待5s )

    s.getpeername()         返回连接套接字的远程地址。返回值通常是元组(ipaddr,port)

    服务端

    1. 创建socket对象
    2. 绑定IP和端口 绑定 bind()
    3. 开始监听链接 监听 listen()
    4. 阻塞 , 等待客户端成功连接 阻塞 accept()
    5. 接收请求数据 接收 recv()
    6. 处理并发送请求数据 发送 send()
    7. 关闭 close()

    客户端

    1. 创建socket对象
    2. 连接服务端 , 按照IP和端口连接 连接 connet()
    3. 发送请求数据 发送 send()
    4. 接收请求数据 接收 recv()
    5. 关闭 close()

    简单socket

     server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)   重用ip和端口 ,但其它client只是挂起状态。只有一个能交互

    import socket
    # 创建socket对象
    sock = socket.socket()
    # 绑定IP和端口,参数是一个元组(ip,port)
    sock.bind(('localhost', 8080))
    # 开始监听,最大挂起5个
    sock.listen(5)
    # 阻塞,等待连接
    conn,addr = sock.accept()
    # 接收请求数据,接收大小为1024字节
    content = conn.recv(1024)
    print(content.decode())
    # 发送请求结果,必须以bytes类型
    conn.send(b'jieshouwanbi')
    # 关闭链接
    conn.close()
    s.server
    import socket
    # 创建socket对象
    sock = socket.socket()
    # 建立链接
    sock.connect(('localhost', 8080))
    # 发送请求数据,必须以bytes类型
    sock.send(b"hello")
    # 接收请求结果
    content = sock.recv(1024)
    print(content.decode())
    # 关闭套接字
    sock.close()
    s.client

    SSH

     1 import socket ,os
     2 server = socket.socket()   #创建socket对象
     3 server.bind(('localhost',9999) )  #绑定ip和port
     4 server.listen()          #开始监听
     5
     6 while True:
     7     conn, addr = server.accept()   #阻塞 等待连接
     8     print("new conn:",addr)
     9     while True:
    10         print("等待新指令")
    11         data = conn.recv(1024)      #接收客户端发过来的命令
    12         if not data:
    13             break
    14         print("执行指令:",data)
    15         cmd_res = os.popen(data.decode()).read() #执行客户端发过来的命令,返回信息长度(接收字符串,执行结果也是字符串)
    16         print("before send",len(cmd_res))      #信息的长度
    17         if len(cmd_res) ==0:
    18             cmd_res = "cmd has no output..."
    19
    20         conn.send( str(len(cmd_res.encode())).encode("utf-8")    )   #先发命令执行的结果信息大小给客户端
    21         client_ack = conn.recv(1024)       #防止粘包,客户端ack
    22         conn.send(cmd_res.encode("utf-8"))    #发送信息
    23         print("send done")
    24
    25 server.close()
    server_ssh
     1 import socket
     2 client = socket.socket()
     3 client.connect(('localhost',9999))
     4
     5 while True:
     6     cmd = input(">>:").strip()         #输入命令
     7     if len(cmd) == 0: continue
     8     client.send(cmd.encode("utf-8"))   #发送命令给server端
     9     cmd_res_size = client.recv(1024)   #接受server端发过来的命令结果信息长度
    10     print("命令结果大小:",cmd_res_size)
    11     client.send("准备接受".encode('utf-8'))   #防止粘包
    12     received_size = 0    #已经接受数据的大小
    13     received_data = b''
    14     while received_size < int(cmd_res_size.decode()):
    15         data = client.recv(1024)   #只要小于,就一直接收
    16         received_size += len(data) #每次收到的有可能小于1024,所以
    17                                                  必须用len判断
    18         #print(data.decode())
    19         received_data += data
    20     else:
    21         print("cmd res receive done...",received_size)
    22         print(received_data.decode())
    23
    24
    25 client.close()
    client

    ftp传文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    ftp server
        1. 读取文件名
        2. 检测文件是否存在
        3. 打开文件
        4. 检测文件大小
        5. 发送文件大小给客户端
        6. 等客户端确认
        7. 开始边读边发数据
        8. 发送md5 
     1 import socket ,os
     2 server = socket.socket()
     3 server.bind(('localhost',9999))
     4 server.listen()
     5
     6 while True:
     7     conn, addr = server.accept()
     8     print("new conn:",addr)
     9     while True:
    10         print("等待新指令")
    11         data = conn.recv(1024)
    12         if not data:
    13             print("客户端已断开")
    14             break
    15         cmd,filename = data.decode().split()
    16         print(filename)
    17         if os.path.isfile(filename):   #判断是否是文件
    18            f = open(filename,"rb")     #打开文件
    19            file_size = os.stat(filename).st_size      #文件大小
    20            conn.send( str(file_size).encode() )       #send file size  防止粘包
    21            conn.recv(1024)                            #wait for ack
    22            for line in f:
    23               conn.send(line)                         #开始发送
    24            f.close()
    25         print("send done")
    26
    27 server.close()
    ftp_server
     1 import socket
     2 import hashlib
     3 client = socket.socket()
     4 client.connect(('localhost', 9999))
     5
     6 while True:
     7     cmd = input(">>:").strip()
     8     if len(cmd) == 0: continue
     9
    10     if cmd.startswith("get"):                   #判断是否以字符串‘get’ 开头
    11         client.send(cmd.encode())               #把需要下载的文件发给server端
    12         server_response = client.recv(1024)     #接收server端发过来的文件大小
    13         print("servr response:", server_response)     #打印文件大小
    14         client.send(b"ready to recv file")            #防止粘包
    15         file_total_size = int(server_response.decode())
    16         received_size = 0                  #已经接收的大小
    17         filename = cmd.split()[1]
    18         f = open(filename + ".new", "wb")      #创建新文件  用于保存
    19
    20         while received_size < file_total_size:
    21             if file_total_size - received_size > 1024:  # 要收不止一次
    22                 size = 1024
    23             else:  # 最后一次了,剩多少收多少
    24                 size = file_total_size - received_size
    25                 print("last receive:", size)
    26
    27             data = client.recv(size)
    28             received_size += len(data)
    29             f.write(data)
    30             # print(file_total_size,received_size)
    31         else:
    32             print("file recv done", received_size, file_total_size)
    33             f.close()
    34 client.close()
    ftp_client
     1 import hashlib
     2 import socket ,os,time
     3 server = socket.socket()
     4 server.bind(('localhost',9999))
     5 server.listen()
     6 while True:
     7     conn, addr = server.accept()
     8     print("new conn:",addr)
     9     while True:
    10         print("等待新指令")
    11         data = conn.recv(1024)
    12         if not data:
    13             print("客户端已断开")
    14             break
    15         cmd,filename = data.decode().split()
    16         print(filename)
    17         if os.path.isfile(filename):
    18            f = open(filename,"rb")
    19            m = hashlib.md5()
    20            file_size = os.stat(filename).st_size
    21            conn.send( str(file_size).encode() ) #send file size
    22            conn.recv(1024) #wait for ack
    23            for line in f:
    24               m.update(line)
    25               conn.send(line)
    26            print("file md5", m.hexdigest())
    27            f.close()
    28            conn.send(m.hexdigest().encode()) #send md5
    29         print("send done")
    30
    31 server.close()
    md5_ftp_server
     1 import socket
     2 import hashlib
     3 client = socket.socket()
     4 client.connect(('localhost', 9999))
     5
     6 while True:
     7     cmd = input(">>:").strip()
     8     if len(cmd) == 0: continue
     9     if cmd.startswith("get"):
    10         client.send(cmd.encode())
    11         server_response = client.recv(1024)
    12         print("servr response:", server_response)
    13         client.send(b"ready to recv file")
    14         file_total_size = int(server_response.decode())
    15         received_size = 0
    16         filename = cmd.split()[1]
    17         f = open(filename + ".new", "wb")
    18         m = hashlib.md5()
    19
    20         while received_size < file_total_size:
    21             if file_total_size - received_size > 1024:  # 要收不止一次
    22                 size = 1024
    23             else:  # 最后一次了,剩多少收多少
    24                 size = file_total_size - received_size
    25                 print("last receive:", size)
    26
    27             data = client.recv(size)
    28             received_size += len(data)
    29             m.update(data)
    30             f.write(data)
    31             print(file_total_size,received_size)
    32         else:
    33             new_file_md5 = m.hexdigest()
    34             print("file recv done", received_size, file_total_size)
    35             f.close()
    36         server_file_md5 = client.recv(1024)
    37         print("server file md5:", server_file_md5)
    38         print("client file md5:", new_file_md5)
    39
    40 client.close()
    md5_ftp_cli
  • 相关阅读:
    go系列(6)- beego日志模块的使用
    shell学习(8)- ulimit调优系统参数
    新年开工
    No module named yum错误的解决办法
    如何杀死defunct进程
    图灵机器人微信自动聊天功能
    go系列(5)- beego自己写controller
    Hadoop/Spark 集群都启动了哪些 Java 程序
    Spark 不允许在 Worker 中访问 SparkContext
    Spark 安装
  • 原文地址:https://www.cnblogs.com/cmd61/p/11094311.html
Copyright © 2020-2023  润新知