首先了解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 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()
服务端退出socket
admindeMacBook-Air-62:~ admin$ nc -l 1234 hello world admindeMacBook-Air-62:~ admin$
客户端发送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) #元祖(网络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 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)写一个server
socket_server01.py
#coding=UTF-8 import socket import time HOST = ‘‘ #表示监听0.0.0.0 PORT = 1234 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #网络,tcp s.bind((HOST,PORT)) s.listen(1) #一次接受一个,写2也是一次接受一个 connect, address = s.accept() #接受客户端的请求,返回的是一个连结句柄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
启动程序并查看端口
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) #网络socket,tcp s.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.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)
现在让客户端一直发,服务端一直接受数据,一端关闭socket连接,另一端也自动关闭连接
server端代码基本上不变
socket_server01.py
#coding=UTF-8 import socket import time HOST = ‘‘ #表示监听0.0.0.0 PORT = 1234 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #网络,tcp s.bind((HOST,PORT)) s.listen(1) #一次接受一个,写2也是一次接受一个 connect, address = s.accept() #接受客户端的请求,返回的是一个连结句柄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()
启动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) #网络socket,tcp s.connect((HOST,PORT)) while True: s.sendall(‘hello, world‘) #客户端发送1024字节 data = s.recv(1024) #接受服务器发送过来的数据 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
同时可以看到server端的来自client的发送数据,全部小写的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终止传输
新的需求,客户端发送命令,服务端接收命令并之行,并返回结果,客户端使用exit或者quit,退出。
server:socket_server_command.py
#-*-coding: UTF-8 -*- #coding=UTF-8 import socket from subprocess import Popen,PIPE HOST = ‘‘ #表示监听0.0.0.0 PORT = 1234 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #网络,tcp s.bind((HOST,PORT)) s.listen(1) #一次接受一个,写2也是一次接受一个 connect, address = s.accept() #接受客户端的请求,返回的是一个连结句柄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) #网络socket,tcp s.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 data s.close()
server启动服务:(有客户端连接会显示连接句柄)
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)
客户端启动并之行命令:
admindeMacBook-Air-62:host_performance-monitor admin$ python socket_clinet_command.py Please input cmd:date 2017年 6月10日 星期六 18时34分21秒 CST Please input cmd:pwd /Users/admin/Desktop/project/host_performance-monitor Please 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-8 import socket from subprocess import Popen,PIPE HOST = ‘‘ #表示监听0.0.0.0 PORT = 1234 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #网络,tcp s.bind((HOST,PORT)) s.listen(1) #一次接受一个,写2也是一次接受一个 connect, address = s.accept() #接受客户端的请求,返回的是一个连结句柄connect+地址 print ‘connent‘,connect print ‘Connected by‘, address while 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: 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) #网络socket,tcp s.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 break s.close()
启动服务端:
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)
启动客户端:
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是一个类,自带多线程
编写一个hander类,继承BaseRequestHander,重写handle()方法
针对tcp还是udp生成一个server对象
调用server对象的handle_request或者sever_forver方法
socket&socket实现ftp的get方法、socketserver