您好,登錄后才能下訂單哦!
首先了解socket工作原理,client-server模式
1、socket客戶端:
2、socket類型
3、socket數(shù)據(jù)流
4、實(shí)驗(yàn)
(1)寫一個(gè)client
服務(wù)端啟動(dòng)監(jiān)聽ip和端口
admindeMacBook-Air-62:~ admin$ nc -l 1234
客戶端連接服務(wù)端,發(fā)數(shù)據(jù),關(guān)閉socket
pycharm中添加一個(gè)socket_client.py并之行:
import socket HOST = '127.0.0.1' PORT = 1234 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((HOST,PORT)) s.sendall('hello world') s.close()
服務(wù)端退出socket
admindeMacBook-Air-62:~ admin$ nc -l 1234 hello world admindeMacBook-Air-62:~ admin$
客戶端發(fā)送10次
socket_client10.py
#-*-coding: UTF-8 -*- #coding=utf-8 import socket import time HOST = '127.0.0.1' PORT = 1234 s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #元祖(網(wǎng)絡(luò)socket,tcp) s.connect((HOST,PORT)) for i in range(10): s.sendall('%s hello, world\n' %i) time.sleep(1) s.close()
服務(wù)端打印10次退出
admindeMacBook-Air-62:~ admin$ nc -l 1234 0 hello, world 1 hello, world 2 hello, world 3 hello, world 4 hello, world 5 hello, world 6 hello, world 7 hello, world 8 hello, world 9 hello, world admindeMacBook-Air-62:~ admin$
(2)寫一個(gè)server
socket_server01.py
#coding=UTF-8 import socket import time HOST = '' #表示監(jiān)聽0.0.0.0 PORT = 1234 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #網(wǎng)絡(luò),tcp s.bind((HOST,PORT)) s.listen(1) #一次接受一個(gè),寫2也是一次接受一個(gè) connect, address = s.accept() #接受客戶端的請求,返回的是一個(gè)連結(jié)句柄connect+地址 print 'connent',connect print 'Connected by', address while 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
啟動(dòng)程序并查看端口
admindeMacBook-Air-62:~ admin$ netstat -an | grep 1234 tcp4 0 0 *.1234 *.* LISTEN
客戶端:
socket-client for server.py
#-*-coding: UTF-8 -*- #coding=utf-8 import socket import time HOST = '127.0.0.1' PORT = 1234 s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #網(wǎng)絡(luò)socket,tcp s.connect((HOST,PORT)) s.sendall('hello, world') #客戶端發(fā)送1024字節(jié) data = s.recv(1024) #接受服務(wù)器發(fā)送過來的數(shù)據(jù) s.close() print 'Received', repr(data) #打印服務(wù)端發(fā)送過來的數(shù)據(jù) print data
客戶端之行發(fā)送hello world,接受HELLO WORLD
python socket-client for server.py Received 'HELLO, WORLD' HELLO, WORLD admindeMacBook-Air-62:host_performance-monitor admin$ python socket_server01.py connent <socket._socketobject object at 0x10427ec20> Connected by ('127.0.0.1', 63878)
現(xiàn)在讓客戶端一直發(fā),服務(wù)端一直接受數(shù)據(jù),一端關(guān)閉socket連接,另一端也自動(dòng)關(guān)閉連接
server端代碼基本上不變
socket_server01.py
#coding=UTF-8 import socket import time HOST = '' #表示監(jiān)聽0.0.0.0 PORT = 1234 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #網(wǎng)絡(luò),tcp s.bind((HOST,PORT)) s.listen(1) #一次接受一個(gè),寫2也是一次接受一個(gè) connect, address = s.accept() #接受客戶端的請求,返回的是一個(gè)連結(jié)句柄connect+地址 print 'connent',connect print 'Connected by', address while 1: data = connect.recv(1024) print data if not data: break connect.sendall(data.upper()) connect.close()
啟動(dòng)server,并查看端口:
admindeMacBook-Air-62:host_performance-monitor admin$ python socket_server01.py admindeMacBook-Air-62:~ admin$ netstat -an | grep 1234 tcp4 0 0 *.1234 *.* LISTEN
client端代碼:
vim clinet_not_stop.py #-*-coding: UTF-8 -*- #coding=utf-8 import socket import time HOST = '127.0.0.1' PORT = 1234 s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #網(wǎng)絡(luò)socket,tcp s.connect((HOST,PORT)) while True: s.sendall('hello, world') #客戶端發(fā)送1024字節(jié) data = s.recv(1024) #接受服務(wù)器發(fā)送過來的數(shù)據(jù) print data time.sleep(1) s.close()
admindeMacBook-Air-62:host_performance-monitor admin$ python python clinet_not_stop.py client接受到server大寫返回 HELLO, WORLD HELLO, WORLD HELLO, WORLD HELLO, WORLD HELLO, WORLD HELLO, WORLD HELLO, WORLD HELLO, WORLD
同時(shí)可以看到server端的來自client的發(fā)送數(shù)據(jù),全部小寫的hello world
admindeMacBook-Air-62:host_performance-monitor admin$ python socket_server01.py connent <socket._socketobject object at 0x10baedc20> Connected by ('127.0.0.1', 64589) hello, world hello, world hello, world hello, world hello, world hello, world hello, world hello, world
按ctrl+c終止傳輸
新的需求,客戶端發(fā)送命令,服務(wù)端接收命令并之行,并返回結(jié)果,客戶端使用exit或者quit,退出。
server:socket_server_command.py
#-*-coding: UTF-8 -*- #coding=UTF-8 import socket from subprocess import Popen,PIPE HOST = '' #表示監(jiān)聽0.0.0.0 PORT = 1234 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #網(wǎng)絡(luò),tcp s.bind((HOST,PORT)) s.listen(1) #一次接受一個(gè),寫2也是一次接受一個(gè) connect, address = s.accept() #接受客戶端的請求,返回的是一個(gè)連結(jié)句柄connect+地址 print 'connent',connect print 'Connected by', address while 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: break connect.close()
client:socket_clinet_command.py
#-*-coding: UTF-8 -*- #coding=utf-8 import socket import time import tab #參考:http://daixuan.blog.51cto.com/5426657/1934112 HOST = '127.0.0.1' PORT = 1234 s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #網(wǎng)絡(luò)socket,tcp s.connect((HOST,PORT)) while True: cmd = raw_input("Please input cmd:").strip() #把空字符串命令去掉,做一個(gè)判斷,非空再發(fā)送 if cmd.lower() == 'exit' or cmd.lower() == 'quit': break if cmd: s.sendall(cmd) #客戶端發(fā)送命令 data = s.recv(1024) #接受服務(wù)器發(fā)送過來的數(shù)據(jù) print data s.close()
server啟動(dòng)服務(wù):(有客戶端連接會(huì)顯示連接句柄)
admindeMacBook-Air-62:host_performance-monitor admin$ python socket_server_command.py connent <socket._socketobject object at 0x109192de0> Connected by ('127.0.0.1', 65512)
客戶端啟動(dòng)并之行命令:
admindeMacBook-Air-62:host_performance-monitor admin$ python socket_clinet_command.py Please input cmd:date 2017年 6月10日 星期六 18時(shí)34分21秒 CST Please input cmd:pwd /Users/admin/Desktop/project/host_performance-monitor Please input cmd:exit
5、實(shí)現(xiàn)FTP下載功能:
1、get source dest
2、重復(fù)文件,加.new
3、打印出來get下來的文件名是/tmp/hosts 還是/tmp/hosts.new
服務(wù)端:socket_server_ftp.py
#-*-coding: UTF-8 -*- #coding=UTF-8 import socket from subprocess import Popen,PIPE HOST = '' #表示監(jiān)聽0.0.0.0 PORT = 1234 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #網(wǎng)絡(luò),tcp s.bind((HOST,PORT)) s.listen(1) #一次接受一個(gè),寫2也是一次接受一個(gè) connect, address = s.accept() #接受客戶端的請求,返回的是一個(gè)連結(jié)句柄connect+地址 print 'connent',connect print 'Connected by', address while 1: cmd = connect.recv(1024) cmd_list = cmd.split() if cmd_list[0] == 'get': #如果是get方法,讀數(shù)據(jù) with open(cmd_list[1]) as fd: while True: #循環(huán)讀取1024字節(jié),然后返回一個(gè)數(shù) data = fd.read(1024) connect.sendall(data) if not data: #數(shù)據(jù)讀完了,跳出while循環(huán) connect.sendall('EOF') break if not cmd: break connect.close()
客戶端:socket_clinet_ftp.py
#-*-coding: UTF-8 -*- #coding=utf-8 import socket import time import tab #參考:http://daixuan.blog.51cto.com/5426657/1934112 import os HOST = '127.0.0.1' PORT = 1234 s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #網(wǎng)絡(luò)socket,tcp s.connect((HOST,PORT)) while True: cmd = raw_input("Please input cmd:").strip() #把空字符串命令去掉,做一個(gè)判斷,非空再發(fā)送 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) #客戶端發(fā)送命令 if not os.path.exists(cmd_list[2]): dst_file = cmd_list[2] else: dst_file = cmd_list[2]+'.new' n = 1 #定義一個(gè)變量,第一次打開文件是wb方式,第二次打開文件是a(追加)的方式打開。 while True: data_rev = s.recv(1024) # 接受服務(wù)器發(fā)送過來的數(shù)據(jù),但是服務(wù)器發(fā)送完數(shù)據(jù),客戶端仍在等待,就會(huì)卡住。用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': #如果最后三個(gè)字符是EOF,退出ftp break s.close()
啟動(dòng)服務(wù)端:
admindeMacBook-Air-62:host_performance-monitor admin$ python socket_server_ftp.py connent <socket._socketobject object at 0x104ecbde0> Connected by ('127.0.0.1', 53858)
啟動(dòng)客戶端:
admindeMacBook-Air-62:host_performance-monitor admin$ python socket_clinet_ftp.py Please input cmd:get /etc/hosts /tmp/hosts destination file is /tmp/hosts Please input cmd:get /etc/hosts /tmp/hosts destination file is /tmp/hosts.new
6、SocketServer
socketserver是一個(gè)類,自帶多線程
編寫一個(gè)hander類,繼承BaseRequestHander,重寫handle()方法
針對tcp還是udp生成一個(gè)server對象
調(diào)用server對象的handle_request或者sever_forver方法
(1)socket server官方的例子,一個(gè)腳本中服務(wù)端核客戶端
https://docs.python.org/2.7/library/socketserver.html?highlight=socketserver
vim socket-threading-thread.py import socket import threading import SocketServer class 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): pass def 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.py Server loop running in thread: Thread-1 Thread-2 Hello World 1 Thread-3 Hello World 2 Thread-4 Hello World 3
(2)多個(gè)客戶端同時(shí)連接一個(gè)服務(wù)器
服務(wù)器不退出
任何一個(gè)客戶端都會(huì)有返回的結(jié)果
服務(wù)端代碼:
vim socket_clinet_command.py #-*-coding: UTF-8 -*- #coding=UTF-8 import socket import threading import SocketServer class 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: break class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): pass if __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 ##主要進(jìn)程不退出 server.serve_forever()
客戶端代碼:
socketserver_clinet.py #-*-coding: UTF-8 -*- #coding=utf-8 import socket import time import tab #參考:http://daixuan.blog.51cto.com/5426657/1934112 import os HOST = 'localhost' PORT = 9999 s = 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()
啟動(dòng)服務(wù)端
Server loop running in thread: Thread-1 127.0.0.1 hello, world 127.0.0.1 hello, world 127.0.0.1 hello, world 127.0.0.1 hello, world
分別啟動(dòng)兩個(gè)客戶端:
返回結(jié)果都是大寫helloworld,且相互不影響。
HELLO, WORLD HELLO, WORLD HELLO, WORLD HELLO, WORLD HELLO, WORLD HELLO, WORLD HELLO, WORLD HELLO, WORLD
(3)使用socketserver的threading多線程實(shí)現(xiàn)ftp功能(多客戶端)
服務(wù)器端代碼:
#-*-coding: UTF-8 -*- #coding=UTF-8 import socket import threading import SocketServer class 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方法,讀數(shù)據(jù) with open(self.cmd_list[1]) as fd: while True: # 循環(huán)讀取1024字節(jié),然后返回一個(gè)數(shù) self.data = fd.read(1024) self.request.sendall(self.data) if not self.data: # 數(shù)據(jù)讀完了,跳出while循環(huán) self.request.sendall('EOF') break if not self.cmd: break class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): pass if __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 ##主要進(jìn)程不退出 server.serve_forever()
啟動(dòng)服務(wù)端監(jiān)聽端口:
/System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7 /Users/admin/Desktop/project/host_performance-monitor/socket-threading-thread-server-ftp.py Server loop running in thread: Thread-1
客戶端代碼:
socket_clinet_ftp.py
#-*-coding: UTF-8 -*- #coding=utf-8 import socket import time import tab #參考:http://daixuan.blog.51cto.com/5426657/1934112 import os HOST = '127.0.0.1' PORT = 12345 s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #網(wǎng)絡(luò)socket,tcp s.connect((HOST,PORT)) while True: cmd = raw_input("Please input cmd:").strip() #把空字符串命令去掉,做一個(gè)判斷,非空再發(fā)送 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) #客戶端發(fā)送命令 if not os.path.exists(cmd_list[2]): dst_file = cmd_list[2] else: dst_file = cmd_list[2]+'.new' n = 1 #定義一個(gè)變量,第一次打開文件是wb方式,第二次打開文件是a(追加)的方式打開。 while True: data_rev = s.recv(1024) # 接受服務(wù)器發(fā)送過來的數(shù)據(jù),但是服務(wù)器發(fā)送完數(shù)據(jù),客戶端仍在等待,就會(huì)卡住。用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': #如果最后三個(gè)字符是EOF,退出ftp break s.close()
分別啟動(dòng)兩個(gè)客戶端,可以同時(shí)使用get方法,斷開其中一個(gè)客戶端對服務(wù)端無影響。
客戶端1: /System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7 /Users/admin/Desktop/project/host_performance-monitor/socket_clinet_ftp.py Please input cmd:ls Ex: get file1 file2 Please input cmd:get /tmp/1.txt /tmp/2.txt destination file is /tmp/2.txt Please input cmd: 客戶端2: /System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7 /Users/admin/Desktop/project/host_performance-monitor/socket_clinet_ftp.py Please input cmd:get /tmp/1.txt /tmp/2.txt destination file is /tmp/2.txt.new destination file is /tmp/2.txt.new Please input cmd: Ex: get file1 file2 Please input cmd:get /tmp/1.txt /tmp/2.txt destination file is /tmp/2.txt.new destination file is /tmp/2.txt.new Please input cmd:
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。