python基础2-socket编程

 

服务端
server = socket.socket(family=AF_INET,type=SOCK_STREAM,proto=0,fileno=None)
                        地址簇,           tcp/ip
server.bind(localhost,9999)   绑定端口
server.listen()      监听

while True:
    conn,addr = server.accept()     #阻塞
    while True:
        print("new conn",addr)
        data = conn.recv(1024)      #conn是开启的连接的实例,官方建议不超过8192,#recv默认是阻塞的
        if not data:
            break  #客户端已断开,conn.recv收到的就都是空数据
        print(data)
        conn.send(data.upper())



详解:
family address
AF_INET     ipv4
AF_INET6    ipv6
AF_UNIX    local

socket protocol type
sock.SOCK_STREAM    tcp/ip
sock.SOCK_DGRAM     udp


客户端
client = socket.socket()
client.connect(server.ip,server.port)
client.send(data)
client.recv(1024)
View Code

 

 

 

简单实例:

1.socket_client.py

#客户端
import socket
client = socket.socket() #声明socket类型,同时生成socket连接对象
client.connect(("localhost",6969))
client.send(b"hello,world")
data = client.recv(1024)
print("recv:",data)
client.close()

  返回:

recv: b'HELLO,WORLD'

  

2.socket_server.py

#服务端
import socket
server = socket.socket()
server.bind(("localhost",6969))        #绑定要监听的端口
server.listen()    #监听
print("我要开始等待电话")
conn,addr = server.accept()      #等电话打进来
#conn就是客户端连过来而在服务器端为其生成的一个连接实例
#accept会返回俩个值,一个flag,一个地址
print(conn,addr)

print("电话来啦")
data = conn.recv(1024)
print("recv:",data)
conn.send(data.upper())
# server.close()

  返回:

我要开始等待电话
<socket.socket fd=272, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 6969), raddr=('127.0.0.1', 52351)> ('127.0.0.1', 52351)
电话来啦
recv: b'hello,world'

  

 3.socket——ssh远程命令返回结果实例

socket_ssh_server.py

import socket,os
server = socket.socket()
server.bind(('localhost',9999))
server.listen()
while True:
    conn,addr = server.accept()
    print("new conn:",addr)
    while True:
        print("等待新指令")
        data = conn.recv(1024)
        if not data:
            print("客户端已断开")
            break
        print("执行指令:",data)
        cmd_res = os.popen(data.decode()).read()    #接收字符串,执行结果也是字符串
        print("before send",len(cmd_res))
        if len(cmd_res) == 0:
            cmd_res = "cmd has no output..."

        conn.send(  str(len(cmd_res.encode())).encode("utf-8")   )   #先发大小给客户端
        conn.send(cmd_res.encode("utf-8"))
        print("send done")

server.close()

socket_ssh_client.py

import socket
client = socket.socket()
client.connect(('localhost',9999))
while True:
    cmd = input(">>:").strip()
    if len(cmd) == 0:continue
    client.send(cmd.encode("utf-8"))
    cmd_res_size = client.recv(1024)     #接收命令结果的长度
    print("命令结果大小:",cmd_res_size)
    received_size = 0
    received_data = b''
    while received_size != int(cmd_res_size.decode()):
        data = client.recv(1024)
        received_size += len(data)     #每次收到的有可能小于1024,所以必须用len判断
        # print(data.decode())
        received_data += data
        print(received_size)
    else:
        print("cmd res received done...",received_size)
        print(received_data.decode())
    # cmd_res = client.recv(1024)
    # print(cmd_res.decode())
client.close()

 

4.解决socket粘包

import socket,os,time
server = socket.socket()
server.bind(('localhost',9999))
server.listen()
while True:
    conn,addr = server.accept()
    print("new conn:",addr)
    while True:
        print("等待新指令")
        data = conn.recv(1024)
        if not data:
            print("客户端已断开")
            break
        print("执行指令:",data)
        cmd_res = os.popen(data.decode()).read()    #接收字符串,执行结果也是字符串
        print("before send",len(cmd_res))
        if len(cmd_res) == 0:
            cmd_res = "cmd has no output..."

        conn.send(  str(len(cmd_res.encode())).encode("utf-8")   )   #先发大小给客户端
        # time.sleep(0.5)
        client_ack = conn.recv(1024)      #wait client to confirm 在俩个send之间插入一个交互
        print("ack from client:",client_ack)
        conn.send(cmd_res.encode("utf-8"))
        print("send done")

server.close()
socket_server_ssh.py
import socket
client = socket.socket()
client.connect(('localhost',9999))
while True:
    cmd = input(">>:").strip()
    if len(cmd) == 0:continue
    client.send(cmd.encode("utf-8"))
    cmd_res_size = client.recv(1024)     #接收命令结果的长度
    print("命令结果大小:",cmd_res_size)
    client.send("准备好接收了,我,可以发啦".encode("utf-8"))
    received_size = 0
    received_data = b''
    while received_size != int(cmd_res_size.decode()):
        data = client.recv(1024)
        received_size += len(data)     #每次收到的有可能小于1024,所以必须用len判断
        # print(data.decode())
        received_data += data
        print(received_size)
    else:
        print("cmd res received done...",received_size)
        print(received_data.decode())
    # cmd_res = client.recv(1024)
    # print(cmd_res.decode())
client.close()
socket_client_ssh.py

注:在linux上执行df命令就很明显的粘包,win端不易发现

 

5.socket实现文件发送,仅实现get,并且是在linux之间实现

import socket,os,time,hashlib
server = socket.socket()
server.bind(('localhost',9999))
server.listen()
while True:
    conn,addr = server.accept()
    print("new conn:",addr)
    while True:
        print("等待新指令")
        data = conn.recv(1024)
        if not data:
            print("客户端已断开")
            break
        cmd,filename = data.decode().split()
        print(filename)
        if os.path.isfile(filename):
            f = open(filename,'rb')
            m = hashlib.md5()
            file_size = os.stat(filename).st_size
            conn.send(str(file_size).encode() ) #send file size
            conn.recv(1024)    #wait for ack
            for line in f:     #f是迭代器的形式
                m.update(line)
                conn.send(line)
            print("file md5",m.hexdigest())
            f.close()
            conn.send(m.hexdigest().encode())   #send md5
        print("send done")

server.close()
server.py
import socket,hashlib
client = socket.socket()
client.connect(('localhost',9999))
while True:
    cmd = input(">>:").strip()
    if len(cmd) == 0:continue
    if cmd.startwith("get"):
        client.send(cmd.encode())
        server_response = client.recv(1024)
        print("server response",server_response)
        client.send(b"ready to recv file")
        file_total_size = int(server_response.decode())
        received_size = 0
        filename = cmd.split()[1]
        f = open(filename + '.new','wb')
        m = hashlib.md5()
        while received_size < file_total_size:
            surplus = file_total_size - received_size   #剩余要收的大小
            if surplus >1024:  #要收不止一次
                size = 1024
            else:   #最后一次剩余多少收多少  #防止与最后的md5值进行粘包
                size = surplus
                print("last receive:",size)
            data = client.recv(size)
            received_size += len(data)
            m.update(data)
            f.write(data)
            # print(file_total_size,received_size)  #每次循环都打印,有点刷屏,显得慢
        else:
            new_file_md5 = m.hexdigest()
            print("file recv done",received_size,file_total_size)
            f.close()
        server_file_md5 = client.recv(1024)
        print("server file md5:",server_file_md5)
        print("client file md5:",new_file_md5)

client.close()
client.py

 

 注:其中有md5校验,故较慢

 

posted @ 2017-10-04 12:57  larlly  阅读(553)  评论(0)    收藏  举报