千家信息网

socket&socket实现ftp的get方法、socke

发表于:2025-12-02 作者:千家信息网编辑
千家信息网最后更新 2025年12月02日,首先了解socket工作原理,client-server模式1、socket客户端:2、socket类型3、socket数据流4、实验(1)写一个client服务端启动监听ip和端口admindeMa
千家信息网最后更新 2025年12月02日socket&socket实现ftp的get方法、socke

首先了解socket工作原理,client-server模式


1、socket客户端:

2、socket类型

3、socket数据流

4、实验

(1)写一个client

服务端启动监听ip和端口

admindeMacBook-Air-62:~ admin$ nc -l 1234

客户端连接服务端,发数据,关闭socket

pycharm中添加一个socket_client.py并之行:

import socketHOST = '127.0.0.1'PORT = 1234s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)s.connect((HOST,PORT))s.sendall('hello world')s.close()

服务端退出socket

admindeMacBook-Air-62:~ admin$ nc -l 1234hello worldadmindeMacBook-Air-62:~ admin$

客户端发送10次

socket_client10.py

#-*-coding: UTF-8 -*-#coding=utf-8import socketimport timeHOST = '127.0.0.1'PORT = 1234s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #元祖(网络socket,tcp) s.connect((HOST,PORT))for i in range(10):    s.sendall('%s  hello, world\n' %i)    time.sleep(1)s.close()

服务端打印10次退出

admindeMacBook-Air-62:~ admin$ nc -l 12340  hello, world1  hello, world2  hello, world3  hello, world4  hello, world5  hello, world6  hello, world7  hello, world8  hello, world9  hello, worldadmindeMacBook-Air-62:~ admin$

(2)写一个server

socket_server01.py

#coding=UTF-8import socketimport timeHOST = '' #表示监听0.0.0.0PORT = 1234s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #网络,tcps.bind((HOST,PORT))s.listen(1)    #一次接受一个,写2也是一次接受一个connect, address = s.accept()  #接受客户端的请求,返回的是一个连结句柄connect+地址print 'connent',connectprint 'Connected by', addresswhile 1:    data = connect.recv(1024)    if not data: break    connect.sendall(data.upper())connect.close()
admindeMacBook-Air-62:host_performance-monitor admin$ python socket_server01.py

启动程序并查看端口

admindeMacBook-Air-62:~ admin$ netstat -an | grep 1234tcp4       0      0  *.1234                 *.*                    LISTEN

客户端:

socket-client for server.py

#-*-coding: UTF-8 -*-#coding=utf-8import socketimport timeHOST = '127.0.0.1'PORT = 1234s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #网络socket,tcps.connect((HOST,PORT))s.sendall('hello, world') #客户端发送1024字节data = s.recv(1024) #接受服务器发送过来的数据s.close()print  'Received', repr(data) #打印服务端发送过来的数据print data


客户端之行发送hello world,接受HELLO WORLD

python socket-client for server.pyReceived 'HELLO, WORLD'HELLO, WORLDadmindeMacBook-Air-62:host_performance-monitor admin$ python socket_server01.pyconnent Connected by ('127.0.0.1', 63878)

现在让客户端一直发,服务端一直接受数据,一端关闭socket连接,另一端也自动关闭连接

server端代码基本上不变

socket_server01.py

#coding=UTF-8import socketimport timeHOST = '' #表示监听0.0.0.0PORT = 1234s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #网络,tcps.bind((HOST,PORT))s.listen(1)    #一次接受一个,写2也是一次接受一个connect, address = s.accept()  #接受客户端的请求,返回的是一个连结句柄connect+地址print 'connent',connectprint 'Connected by', addresswhile 1:    data = connect.recv(1024)    print data    if not data: break    connect.sendall(data.upper())connect.close()


启动server,并查看端口:

admindeMacBook-Air-62:host_performance-monitor admin$ python socket_server01.pyadmindeMacBook-Air-62:~ admin$ netstat -an | grep 1234tcp4       0      0  *.1234                 *.*                    LISTEN

client端代码:

vim clinet_not_stop.py#-*-coding: UTF-8 -*-#coding=utf-8import socketimport timeHOST = '127.0.0.1'PORT = 1234s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #网络socket,tcps.connect((HOST,PORT))while True:s.sendall('hello, world') #客户端发送1024字节data = s.recv(1024) #接受服务器发送过来的数据print datatime.sleep(1)s.close()
admindeMacBook-Air-62:host_performance-monitor admin$ python  python clinet_not_stop.py  client接受到server大写返回HELLO, WORLDHELLO, WORLDHELLO, WORLDHELLO, WORLDHELLO, WORLDHELLO, WORLDHELLO, WORLDHELLO, WORLD

同时可以看到server端的来自client的发送数据,全部小写的hello world

admindeMacBook-Air-62:host_performance-monitor admin$ python socket_server01.pyconnent Connected by ('127.0.0.1', 64589)hello, worldhello, worldhello, worldhello, worldhello, worldhello, worldhello, worldhello, world

按ctrl+c终止传输


新的需求,客户端发送命令,服务端接收命令并之行,并返回结果,客户端使用exit或者quit,退出。

server:socket_server_command.py

#-*-coding: UTF-8 -*-#coding=UTF-8import socketfrom subprocess import Popen,PIPEHOST = '' #表示监听0.0.0.0PORT = 1234s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #网络,tcps.bind((HOST,PORT))s.listen(1)    #一次接受一个,写2也是一次接受一个connect, address = s.accept()  #接受客户端的请求,返回的是一个连结句柄connect+地址print 'connent',connectprint 'Connected by', addresswhile 1:    cmd = connect.recv(1024)    p = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True)    stdout = p.stdout.read()    stderr = p.stderr.read()    if stdout:        connect.sendall(stdout)    if stderr:        connect.sendall(stderr)    if not cmd: breakconnect.close()


client:socket_clinet_command.py

#-*-coding: UTF-8 -*-#coding=utf-8import socketimport timeimport tab #参考:http://daixuan.blog.51cto.com/5426657/1934112HOST = '127.0.0.1'PORT = 1234s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #网络socket,tcps.connect((HOST,PORT))while True:    cmd = raw_input("Please input cmd:").strip() #把空字符串命令去掉,做一个判断,非空再发送    if cmd.lower() == 'exit' or cmd.lower() == 'quit':        break    if cmd:        s.sendall(cmd) #客户端发送命令        data = s.recv(1024) #接受服务器发送过来的数据        print datas.close()


server启动服务:(有客户端连接会显示连接句柄)

admindeMacBook-Air-62:host_performance-monitor admin$ python socket_server_command.pyconnent Connected by ('127.0.0.1', 65512)

客户端启动并之行命令:

admindeMacBook-Air-62:host_performance-monitor admin$ python socket_clinet_command.pyPlease input cmd:date2017年 6月10日 星期六 18时34分21秒 CSTPlease input cmd:pwd/Users/admin/Desktop/project/host_performance-monitorPlease input cmd:exit


5、实现FTP下载功能:

1、get source dest

2、重复文件,加.new

3、打印出来get下来的文件名是/tmp/hosts 还是/tmp/hosts.new

服务端:socket_server_ftp.py

#-*-coding: UTF-8 -*-#coding=UTF-8import socketfrom subprocess import Popen,PIPEHOST = '' #表示监听0.0.0.0PORT = 1234s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #网络,tcps.bind((HOST,PORT))s.listen(1)    #一次接受一个,写2也是一次接受一个connect, address = s.accept()  #接受客户端的请求,返回的是一个连结句柄connect+地址print 'connent',connectprint 'Connected by', addresswhile 1:    cmd = connect.recv(1024)    cmd_list = cmd.split()    if cmd_list[0] == 'get':   #如果是get方法,读数据        with open(cmd_list[1]) as fd:            while True:   #循环读取1024字节,然后返回一个数                data = fd.read(1024)                connect.sendall(data)                if not data:   #数据读完了,跳出while循环                    connect.sendall('EOF')                    break    if not cmd: breakconnect.close()


客户端:socket_clinet_ftp.py

#-*-coding: UTF-8 -*-#coding=utf-8import socketimport timeimport tab  #参考:http://daixuan.blog.51cto.com/5426657/1934112import osHOST = '127.0.0.1'PORT = 1234s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #网络socket,tcps.connect((HOST,PORT))while True:   cmd = raw_input("Please input cmd:").strip() #把空字符串命令去掉,做一个判断,非空再发送   if cmd.lower() == 'exit' or cmd.lower() == 'quit':       break   cmd_list = cmd.split()   if len(cmd_list) != 3:       print "Ex: get file1 file2"       continue   else:       s.sendall(cmd) #客户端发送命令       if not os.path.exists(cmd_list[2]):           dst_file = cmd_list[2]       else:           dst_file = cmd_list[2]+'.new'       n = 1   #定义一个变量,第一次打开文件是wb方式,第二次打开文件是a(追加)的方式打开。       while True:           data_rev = s.recv(1024)  # 接受服务器发送过来的数据,但是服务器发送完数据,客户端仍在等待,就会卡住。用EOF,就break           if data_rev.endswith('EOF'):               data = data_rev[:-3]           else:               data = data_rev           if n == 1:               with open(dst_file, 'wb')  as fd:                   fd.write(data)           else:               with open(dst_file, 'a') as fd:                   fd.write(data)                   print data           n +=1           print "destination file is %s" %dst_file           if data_rev[-3:] == 'EOF':  #如果最后三个字符是EOF,退出ftp               breaks.close()


启动服务端:

admindeMacBook-Air-62:host_performance-monitor admin$ python socket_server_ftp.pyconnent Connected by ('127.0.0.1', 53858)

启动客户端:

admindeMacBook-Air-62:host_performance-monitor admin$ python socket_clinet_ftp.pyPlease input cmd:get /etc/hosts /tmp/hostsdestination file is /tmp/hostsPlease input cmd:get /etc/hosts /tmp/hostsdestination file is /tmp/hosts.new


6、SocketServer

socketserver是一个类,自带多线程

编写一个hander类,继承BaseRequestHander,重写handle()方法

针对tcp还是udp生成一个server对象

调用server对象的handle_request或者sever_forver方法

(1)socket server官方的例子,一个脚本中服务端核客户端

https://docs.python.org/2.7/library/socketserver.html?highlight=socketserver

vim socket-threading-thread.pyimport socketimport threadingimport SocketServerclass ThreadedTCPRequestHandler(SocketServer.BaseRequestHandler):    def handle(self):        data = self.request.recv(1024)        cur_thread = threading.current_thread()        response = "%s %s" % (cur_thread.name, data)        self.request.sendall(response)class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):   passdef client(ip, port, message):   sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)   sock.connect((ip, port))   try:       sock.sendall(message)       response = sock.recv(1024)       print response   finally:       sock.close()if __name__ == "__main__":   # Port 0 means to select an arbitrary unused port   HOST, PORT = "localhost", 0   server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)   ip, port = server.server_address   # Start a thread with the server -- that thread will then start one   # more thread for each request   server_thread = threading.Thread(target=server.serve_forever)   # Exit the server thread when the main thread terminates   server_thread.daemon = True   server_thread.start()   print "Server loop running in thread:", server_thread.name   client(ip, port, "Hello World 1")   client(ip, port, "Hello World 2")   client(ip, port, "Hello World 3")   server.shutdown()   server.server_close()
admindeMacBook-Air-62:host_performance-monitor admin$ python socket-threading-thread.pyServer loop running in thread: Thread-1Thread-2 Hello World 1Thread-3 Hello World 2Thread-4 Hello World 3

(2)多个客户端同时连接一个服务器

服务器不退出

任何一个客户端都会有返回的结果

服务端代码:

vim socket_clinet_command.py#-*-coding: UTF-8 -*-#coding=UTF-8import socketimport threadingimport SocketServerclass ThreadedTCPRequestHandler(SocketServer.BaseRequestHandler):    def handle(self):        while True:            self.data = self.request.recv(1024).strip()            print self.client_address[0]            print self.data            self.request.sendall(self.data.upper())            if not self.data:                breakclass ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):    passif __name__ == "__main__":    # Port 0 means to select an arbitrary unused port    #HOST, PORT = "localhost", 9999    HOST = 'localhost'    PORT = 9999    server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)    # Start a thread with the server -- that thread will then start one    # more thread for each request    server_thread = threading.Thread(target=server.serve_forever)    # Exit the server thread when the main thread terminates    server_thread.daemon = True    server_thread.start()    print "Server loop running in thread:", server_thread.name    ##主要进程不退出    server.serve_forever()

客户端代码:

socketserver_clinet.py#-*-coding: UTF-8 -*-#coding=utf-8import socketimport timeimport tab  #参考:http://daixuan.blog.51cto.com/5426657/1934112import osHOST = 'localhost'PORT = 9999s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)s.connect((HOST,PORT))while True:    s.sendall('hello, world')    data = s.recv(1024)    print data    time.sleep(1)s.close()


启动服务端

Server loop running in thread: Thread-1127.0.0.1hello, world127.0.0.1hello, world127.0.0.1hello, world127.0.0.1hello, world

分别启动两个客户端:

返回结果都是大写helloworld,且相互不影响。

HELLO, WORLDHELLO, WORLDHELLO, WORLDHELLO, WORLDHELLO, WORLDHELLO, WORLDHELLO, WORLDHELLO, WORLD


(3)使用socketserver的threading多线程实现ftp功能(多客户端)

服务器端代码:

#-*-coding: UTF-8 -*-#coding=UTF-8import socketimport threadingimport SocketServerclass ThreadedTCPRequestHandler(SocketServer.BaseRequestHandler):    def handle(self):        while True:            self.cmd = self.request.recv(1024).strip()            self.cmd_list = self.cmd.split()            if self.cmd_list[0] == 'get':  # 如果是get方法,读数据                with open(self.cmd_list[1]) as fd:                    while True:  # 循环读取1024字节,然后返回一个数                        self.data = fd.read(1024)                        self.request.sendall(self.data)                        if not self.data:  # 数据读完了,跳出while循环                            self.request.sendall('EOF')                            break            if not self.cmd:                breakclass ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):    passif __name__ == "__main__":    # Port 0 means to select an arbitrary unused port    #HOST, PORT = "localhost", 9999    HOST = ''    PORT = 12345    server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)    # Start a thread with the server -- that thread will then start one    # more thread for each request    server_thread = threading.Thread(target=server.serve_forever)    # Exit the server thread when the main thread terminates    server_thread.daemon = True    server_thread.start()    print "Server loop running in thread:", server_thread.name    ##主要进程不退出    server.serve_forever()

启动服务端监听端口:

/System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7 /Users/admin/Desktop/project/host_performance-monitor/socket-threading-thread-server-ftp.pyServer loop running in thread: Thread-1


客户端代码:

socket_clinet_ftp.py

#-*-coding: UTF-8 -*-#coding=utf-8import socketimport timeimport tab  #参考:http://daixuan.blog.51cto.com/5426657/1934112import osHOST = '127.0.0.1'PORT = 12345s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #网络socket,tcps.connect((HOST,PORT))while True:    cmd = raw_input("Please input cmd:").strip() #把空字符串命令去掉,做一个判断,非空再发送    if cmd.lower() == 'exit' or cmd.lower() == 'quit':        break    cmd_list = cmd.split()    if len(cmd_list) != 3:        print "Ex: get file1 file2"        continue    else:        s.sendall(cmd) #客户端发送命令        if not os.path.exists(cmd_list[2]):            dst_file = cmd_list[2]        else:            dst_file = cmd_list[2]+'.new'        n = 1   #定义一个变量,第一次打开文件是wb方式,第二次打开文件是a(追加)的方式打开。        while True:            data_rev = s.recv(1024)  # 接受服务器发送过来的数据,但是服务器发送完数据,客户端仍在等待,就会卡住。用EOF,就break            if data_rev.endswith('EOF'):                data = data_rev[:-3]            else:                data = data_rev            if n == 1:                with open(dst_file, 'wb')  as fd:                    fd.write(data)            else:                with open(dst_file, 'a') as fd:                    fd.write(data)                    print data            n +=1            print "destination file is %s" %dst_file            if data_rev[-3:] == 'EOF':  #如果最后三个字符是EOF,退出ftp                breaks.close()

分别启动两个客户端,可以同时使用get方法,断开其中一个客户端对服务端无影响。

客户端1:/System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7 /Users/admin/Desktop/project/host_performance-monitor/socket_clinet_ftp.pyPlease input cmd:lsEx: get file1 file2Please input cmd:get /tmp/1.txt /tmp/2.txtdestination file is /tmp/2.txtPlease input cmd:客户端2:/System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7 /Users/admin/Desktop/project/host_performance-monitor/socket_clinet_ftp.pyPlease input cmd:get /tmp/1.txt /tmp/2.txtdestination file is /tmp/2.txt.newdestination file is /tmp/2.txt.newPlease input cmd:Ex: get file1 file2Please input cmd:get /tmp/1.txt /tmp/2.txtdestination file is /tmp/2.txt.newdestination file is /tmp/2.txt.newPlease input cmd:


0