zoukankan      html  css  js  c++  java
  • day8 socket

    代码:

    例子1:socket tcp 通讯

      server端

    import socket
    server = socket.socket()
    ip_port = ("127.0.0.1",8001)
    server.bind(ip_port)
    server.listen()
    conn,addr = server.accept()
    print(conn)
    print(addr)
    from_client_msg = conn.recv(1024)
    print(from_client_msg)
    conn.send(b"Hello it's me")
    conn.close()
    server.close()

    client端

    import socket
    client = socket.socket()
    client.connect(("127.0.0.1",8001))
    client.send(b"Who are you")
    from_server_msg = client.recv(1024)
    print(from_server_msg)


    例子2:socket udp 通讯

    server端
    import socket
    udp_server = socket.socket(type=socket.SOCK_DGRAM)
    ip_port = ('127.0.0.1',8001)
    udp_server.bind(ip_port)
    msg,addr = udp_server.recvfrom(1024)
    print("来自客户端消息:",msg)
    udp_server.sendto(b'I am udpserver',addr)
    udp_server.close()
    client端
    import socket
    udp_client = socket.socket(type=socket.SOCK_DGRAM)
    server_ip_port = ("127.0.0.1",8001)
    udp_client.sendto(b"I am udpclient",server_ip_port)
    print(udp_client)
    from_server_msg = udp_client.recvfrom(1024)
    print("来自服务端",from_server_msg)
    udp_client.close()

    查看缓冲区大小
    import socket
    server = socket.socket()

    size = server.getsockopt(socket.SOL_SOCKET,socket.SO_SNDBUF) ps:查看发送缓冲区大小
    print(size)

    size1 = server.getsockopt(socket.SOL_SOCKET,socket.SO_RCVBUF) ps:查看接收缓冲区大小
    print(size1)

    例子3:Tcp 服务端和客户端通信
    服务端
    import socket
    server = socket.socket()
    ip_port = ("127.0.0.1",8001)
    server.bind(ip_port)
    server.listen()
    conn,addr = server.accept()
    print(conn)
    print(addr)
    while 1:
    from_client_msg = conn.recv(1024)
    print("来自客户端的信息:", from_client_msg.decode("utf-8"))
    server_msg = input("服务端说:")
    conn.send(server_msg.encode("utf-8"))

    conn.close()
    server.close()

    客户端一号
    import socket
    client_01 = socket.socket()
    ip_port = ('127.0.0.1',8001)
    client_01.connect(ip_port)
    while 1:
    client_msg = input("客户端一号说:")
    client_01.send(client_msg.encode("utf-8"))
    from_server_msg = client_01.recv(1024)
    print(from_server_msg.decode("utf-8"))

    客户端2号
    import socket
    clinet_02 = socket.socket()
    ip_port = ("127.0.0.1",8001)
    clinet_02.connect(ip_port)
    while True:
    clinet_02_msg = input("客户端2号说: ")
    clinet_02.send(clinet_02_msg.encode("utf-8"))
    from_server_msg = clinet_02.recv(1024)
    print(from_server_msg.decode("utf-8"))
    ps:tcp一次只能连接一个client在这个例子里面

    例子4:多个udp客户端和单个upd服务端通信

    服务端
    import socket
    server = socket.socket(type=socket.SOCK_DGRAM)
    ip_port = ("127.0.0.1",8001)
    server.bind(ip_port)

    while 1:
    from_client_msg,addr = server.recvfrom(1024)
    print("客户端说:",from_client_msg.decode("utf-8"))
    server_msg = input("服务端说:")
    server.sendto(server_msg.encode("utf-8"),addr)

    客户端01号说:
    import socket
    client_01 = socket.socket(socket.AF_INET,type=socket.SOCK_DGRAM)
    ip_port = ("127.0.0.1",8001)
    while 1:
    client_01_say = input("客户端一号说:")
    client_01.sendto(client_01_say.encode("utf-8"),ip_port)
    msg,addr = client_01.recvfrom(1024)
    print("来自服务端的消息:",msg.decode("utf-8"),addr)

    客户端2号
    import socket
    client_02 = socket.socket(type=socket.SOCK_DGRAM)
    ip_port = ("127.0.0.1",8001)
    while 1:
    msg = input("客户端2号说:")
    send_to_server = client_02.sendto(msg.encode("utf-8"),ip_port)
    rev_from_server,addr = client_02.recvfrom(1024)
    print(rev_from_server.decode("utf-8"))

    ps:在这个例子中,upd客户端都可以跟服务端通讯,但是服务端需要回复了上一个客户端发来的消息才能收到第二个客户端发来的消息

    例5:模拟粘包1
    服务端
    import socket
    server = socket.socket()
    ip_port = ("127.0.0.1",8001)
    server.bind(ip_port)
    server.listen()
    conn,addr = server.accept()
    print(conn)
    print("-----------华丽丽的分割线—————————————")
    print(addr)
    from_msg_client01 = conn.recv(1024)
    from_msg_client02 = conn.recv(1024)
    print("from_msg_client01",from_msg_client01.decode("utf-8"))
    print("from_msg_client02",from_msg_client02.decode("utf-8"))
    conn.close()
    server.close()
    #server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) 地址复用

    客户端
    import socket
    client = socket.socket()
    ip_port = ("127.0.0.1",8001)
    client.connect(ip_port)

    client.send(b"dating")
    client.send(b"girl")

    打印结果

        模拟粘包2

      服务端

    import socket
    import subprocess
    server = socket.socket()
    ip_port = ("127.0.0.1",8001)
    server.bind(ip_port)
    server.listen()
    conn,addr = server.accept()
    while 1:
    from_client_msg = conn.recv(1024).decode("gbk")
    sub_conn = subprocess.Popen(
    from_client_msg,
    shell = True,
    stdout = subprocess.PIPE,
    stderr=subprocess.PIPE
    )
    cmd_result = sub_conn.stdout.read()
    conn.send(cmd_result)

    客户端
    import socket
    client = socket.socket()
    ip_port = ("127.0.0.1",8001)
    client.connect(ip_port)
    while 1:
    send_msg = input("请输入指令:").strip()
    client.send(send_msg.encode("gbk"))
    from_server_msg = client.recv(1024)
    print(from_server_msg.decode("gbk"))

    ps:第二种粘包会造成结果混乱例如输入ipconfig返回的信息不全,然后在输入dir此时返回的信息是ipconfig的一部分和dir结果的一部分,再次输入ipconfig此时返回的是dir的结果

    例6:解决粘包问题方案一 struct模块
    通过strct模块里的pack和unpack来解决 首先计算数据的长度 然后通过pack打包成四个字节发送 然后在发送实际字节
    服务端
    import socket
    import subprocess
    import struct
    server = socket.socket()
    ip_port = ("127.0.0.1",8001)
    server.bind(ip_port)
    server.listen()
    conn,addr = server.accept()
    while 1:
    from_client_msg = conn.recv(1024).decode("gbk")
    sub_conn = subprocess.Popen(
    from_client_msg,
    shell = True,
    stdout = subprocess.PIPE,
    stderr=subprocess.PIPE
    )
    cmd_result = sub_conn.stdout.read()
    len_bytes = struct.pack("i",len(cmd_result))
    conn.send(len_bytes)
    conn.send(cmd_result)
    客户端
    import socket
    import struct
    client = socket.socket()
    ip_port = ("127.0.0.1",8001)
    client.connect(ip_port)
    while 1:
    send_msg = input("请输入指令:").strip()
    client.send(send_msg.encode("gbk"))

    from_server_msg = client.recv(4)

    a = struct.unpack('i',from_server_msg)[0]
    from_server_msg1 = client.recv(a)
    print(from_server_msg1.decode("gbk"))
    解决粘包方法2:sendall循环
    接收端不知道发送端将要传送的字节流的长度,所以解决粘包的方法就是围绕,如何让发送端在发送数据前,把自己将要发送的字节流总大小让接收端知晓
    ,然后接收端发一个确认消息给发送端,然后发送端再发送过来后面的真实内容,接收端再来一个死循环接收完所有数据。

    server端
    import socket,subprocess
    ip_port=('127.0.0.1',8080)
    s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

    s.bind(ip_port)
    s.listen(5)

    while True:
    conn,addr=s.accept()
    print('客户端',addr)
    while True:
    msg=conn.recv(1024)
    if not msg:break
    res=subprocess.Popen(msg.decode('utf-8'),shell=True,
    stdin=subprocess.PIPE,
    stderr=subprocess.PIPE,
    stdout=subprocess.PIPE)
    err=res.stderr.read()
    if err:
    ret=err
    else:
    ret=res.stdout.read()
    data_length=len(ret)
    conn.send(str(data_length).encode('utf-8'))
    data=conn.recv(1024).decode('utf-8')
    print(data)
    if data == 'recv_ready':
    conn.sendall(ret)
    conn.close()
    客户端:
    import socket,time
    s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    res=s.connect_ex(('127.0.0.1',8080))

    while True:
    msg=input('>>: ').strip()
    if len(msg) == 0:continue
    if msg == 'quit':break

    s.send(msg.encode('utf-8'))
    length=int(s.recv(1024).decode('utf-8'))
    s.send('recv_ready'.encode('utf-8'))
    send_size=0
    recv_size=0
    data=b''
    while recv_size < length:
    data+=s.recv(1024)
    recv_size+=len(data)


    print(data.decode('gbk'))

    例6:socketserver实现高并发
    import socketserver
    class MyServer(socketserver.BaseRequestHandler):
    def handle(self):
    while 1:
    from_client_msg = self.request.recv(1024) # conn
    print(from_client_msg.decode('utf-8'))
    msg = input('to_client_msg>>>')
    self.request.send(msg.encode('utf-8'))

    if __name__ == '__main__':
    ip_port = ('127.0.0.1',8001)
    server = socketserver.ThreadingTCPServer(ip_port,MyServer)
    server.serve_forever()
    ps:客户端的正常写就ok

    例子7:ftp客户端上传文件到ftp服务端
    服务端
    import socket
    import struct
    import json
    server = socket.socket()
    bufsize = 1024
    server.bind(("127.0.0.1",8090))
    server.listen(5)
    conn,addr = server.accept()

    head_len = conn.recv(4) #第一次接受4个字节
    head_len = struct.unpack("i",head_len)[0] #解包得到的值是一个元组,所以要加索引取值
    json_head = conn.recv(head_len).decode("utf-8") #反序列化
    head = json.loads(json_head)
    file_size = head['filesize'] #获取长度

    with open(head["filename"],'wb') as f:
    while file_size:
    if file_size >= bufsize:
    content = conn.recv(bufsize)
    f.write(content)
    else:
    content = conn.recv(bufsize)
    f.write(content)
    break
    conn.close()
    server.close()

    客户端
    import os
    import json
    import socket
    import struct
    client = socket.socket()
    client.connect(("127.0.0.1",8090))
    bufsize = 1024
    head = {
    'filepath':r'G:python_projectday07',
    'filename':'ftp_test',
    'filesize':None
    }
    file_path = os.path.join(head["filepath"],head["filename"]) #拼接文件和目录
    filesize = os.path.getsize(file_path) #获取文件的大小
    head["filesize"] = filesize #把文件大小的值写到head字典里面

    json_head = json.dumps(head) #序列化头部信息
    bytes_head = json_head.encode("utf-8") #对头部信息进行编码操作
    print(json_head)
    print(bytes_head)

    head_len = len(bytes_head) #统计头部信息的长度
    pack_len = struct.pack("i",head_len) #把头部信息打包成4个字节
    print(head_len)
    print(pack_len)

    client.send(pack_len)
    client.send(bytes_head)

    with open(file_path,'rb') as f:
    while filesize:
    if filesize >= bufsize:
    content = f.read(bufsize)
    client.send(content)
    filesize -= bufsize
    else:
    content = f.read(filesize)
    client.send(content)
    break
    client.close()


     


    We are down, but not beaten. tested but not defeated.
  • 相关阅读:
    Java中读取.properties配置文件的通用类
    静态工厂方法中单例的延迟加载技术
    AVL树C++实现
    初探Java反射机制
    项目中一个 1 毫秒引发的问题
    用Java操作数据库Datetime数据
    【转】Linux中的EAGAIN含义
    【转】关于编译链接——gcc/g++
    《Linux多线程编程手册》读书笔记
    《Linux多线程服务端编程——使用muduo C++网络库》读书笔记
  • 原文地址:https://www.cnblogs.com/guniang/p/10927437.html
Copyright © 2011-2022 走看看