- 浏览: 119870 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
masuweng:
暂作标记,以后或许用的着.
filter实现登录验证,并且过滤servlet -
jfllxjj:
请问,如果导入的是excel2003格式的表,导入不成功会报错 ...
用poi3.6 读取excel -
wdhxinxin:
...
Java 操作 Excel (读取Excel2003 2007,Poi实现)
服务器端代码:
1。服务器端的图形化类
package service;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Toolkit;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
@SuppressWarnings("serial")
public class Main extends JFrame {
private Main main;
private JButton start;
private JButton stop;
private JTextField port;
private JTextArea result;
public Main(){
this.setLayout(new BorderLayout());
//top
JPanel topPanel = new JPanel();
JLabel lable1 = new JLabel("Port");
this.port = new JTextField();
port.setColumns(10);
port.setText("45678");
this.start = new JButton("Listen");
start.setName("Listen");
this.stop = new JButton("Stop");
stop.setName("Stop");
stop.setEnabled(false);
topPanel.add(lable1);
topPanel.add(port);
topPanel.add(start);
topPanel.add(stop);
//center
JPanel centerPanel = new JPanel();
this.result = new JTextArea(15,50);
this.result.setLineWrap(true);
this.result.setFont(new Font("仿宋",Font.BOLD,12));
JScrollPane jsp = new JScrollPane(this.result);
this.result.setAutoscrolls(true);
this.result.setEnabled(false);
centerPanel.add(jsp);
this.add(centerPanel,BorderLayout.CENTER);
this.add(topPanel,BorderLayout.NORTH);
this.setTitle("Service");
this.setResizable(false);
this.setSize(600, 350);
Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize();
int screenWidth = (int) dimension.getWidth();
int screenHeight = (int) dimension.getHeight();
this.setLocation((screenWidth - this.getWidth())/2, (screenHeight - this.getHeight())/2);
this.setVisible(true);
this.addWindowListener(new MyWindowAdapter());
start.addMouseListener(new MyMouseAdapter());
stop.addMouseListener(new MyMouseAdapter());
this.main = this;
}
public void printMessage(String message){
//System.out.println(message);
this.result.append(message + "\n");
}
public static void main(String[] args) {
new Main();
}
/**
* 开始监听,停止监听
*/
class MyMouseAdapter extends MouseAdapter{
@Override
public void mouseClicked(MouseEvent e) {
if(e.getSource() instanceof JButton){
JButton button = (JButton) e.getSource();
if(button == start && button.isEnabled()){
stop.setEnabled(true);
start.setEnabled(false);
main.printMessage("服务器启动中...");
Service.instance(Integer.valueOf(port.getText()), main);
}else if(button == stop && button.isEnabled()){
start.setEnabled(true);
stop.setEnabled(false);
main.printMessage("服务器关闭中...");
Service.close();
}
}
}
}
/**
* 控制窗体关闭
*/
class MyWindowAdapter extends WindowAdapter{
@Override
public void windowClosing(WindowEvent e) {
Service.close();
System.exit(0);
super.windowClosing(e);
}
}
}
2.服务器端的,Socket类
package service;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress;
import java.util.List;
public class Service{
private static Service service;
private static int port;
private static Main main;
private static AcceptClient ac;
private Service(){
ac = new AcceptClient();
ac.start();
}
/**
* 单例
*/
public static Service instance(int port,Main main){
Service.port = port;
Service.main = main;
if(service == null){
service = new Service();
}
return service;
}
public static void close(){
ac.stopThread();
Service.service = null;
}
class AcceptClient extends Thread{
private boolean isRun = true;
public void stopThread(){
this.isRun = false;
}
@Override
public void run() {
Socket socket = null;
try {
ServerSocket serviceSocket = new ServerSocket();
SocketAddress address = new InetSocketAddress(port);
serviceSocket.bind(address);
while(true && isRun){
socket = serviceSocket.accept();
main.printMessage("监听到客户端:" + socket.getInetAddress().getHostAddress());
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
//ObjectInputStream ois = new ObjectInputStream(bis);
DataInputStream dis = new DataInputStream(bis);
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
//ObjectOutputStream oos = new ObjectOutputStream(bos);
DataOutputStream dos = new DataOutputStream(bos);
String clientVersion = dis.readUTF();//1.readUTF
Service.main.printMessage("客户端:" + socket.getInetAddress().getHostAddress()
+ " 的版本是 " + clientVersion);
ServiceFile sf = new ServiceFile();
dos.writeUTF(sf.getServiceVersion());//writeInt
if(sf.isNeedUpdate(clientVersion)){
dos.writeUTF("Yes");//2.wrietUTF
dos.flush();
List<String> files = sf.getUpdateFiles();
dos.writeInt(files.size());//2.wrietUTF
dos.flush();
for(int i = 0 ; i < files.size() ; i ++){
String filePath = files.get(i);
filePath = new String(filePath.getBytes("UTF-8"));
dos.writeUTF(filePath);//3.writeUTF
dos.flush();
}
List<Long> fileSizes = sf.getUpdateFilesSize();
for(int i = 0 ; i < files.size() ; i ++){
Long fileSize = fileSizes.get(i);
dos.writeLong(fileSize);//3.writeLong
dos.flush();
}
for(int i = 0 ; i < files.size() ; i ++){
String filePath = files.get(i);
filePath = new String(filePath.getBytes("UTF-8"));
FileInputStream fis = sf.getFileInputStream(filePath);
//DataInputStream dfis = new DataInputStream(fis);
int length = 0;
byte[] b = new byte[102400];
while((length = fis.read(b)) != -1){
dos.write(b,0,length);//4.write
//dos.flush();
}
fis.close();
dos.flush();
}
}else{
dos.writeUTF("No");//2.wrietUTF
dos.flush();
}
socket.close();
}
serviceSocket.close();
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
3。 服务器端的后台文件操作类
package service;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
public class ServiceFile {
private String version;//服务器版本号
/**
* 查找服务器上最新版本
*/
public String getServiceVersion(){
Properties p = new Properties();
try {
p.load(new FileInputStream("./service_version/version.properties"));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
this.version = p.getProperty("version");
return this.version;
}
/**
* 判断是否需要更新文件
*/
public boolean isNeedUpdate(String oldVersion){
String[] newVersions = getServiceVersion().split("\\.");
String[] oldVersions = oldVersion.split("\\.");
for(int i = 0; i < newVersions.length; i ++){
int n = 0;
int o = 0;
if(newVersions[i] != null){
n = Integer.valueOf(newVersions[i]);
}
if(oldVersions[i] != null){
o = Integer.valueOf(oldVersions[i]);
}
if(n > o){
return true;
}
}
return false;
}
public List<String> getUpdateFiles(){
if(this.version == null){
this.version = this.getServiceVersion();
}
String baseDir = "./service_version/" + this.version + "/";
return this.listFiles(baseDir);
}
private List<String> listFiles(String path){
List<String> filePaths = new ArrayList<String>();
File baseFile = new File(path);
if(baseFile.isFile()){
filePaths.add(this.filterFilePth(baseFile.getPath()));
}else{
File[] files = baseFile.listFiles();
for(int i = 0 ; i < files.length ; i ++){
List<String> tempFilePath = this.listFiles(files[i].getPath());
filePaths.addAll(tempFilePath);
}
}
return filePaths;
}
public List<Long> getUpdateFilesSize(){
List<Long> filesSizes = new ArrayList<Long>();
List<String> filePaths = this.getUpdateFiles();
String baseDir = "./service_version/" + this.version + "/";
for(int i = 0; i < filePaths.size(); i ++){
File file = new File(baseDir + filePaths.get(i));
filesSizes.add(file.length());
}
return filesSizes;
}
private String filterFilePth(String path){
int position = path.indexOf(this.version);
path = path.substring(position + this.version.length() + 1);
return path;
}
public FileInputStream getFileInputStream(String filePath){
if(this.version == null){
this.version = this.getServiceVersion();
}
FileInputStream fis = null;
try {
fis = new FileInputStream("./service_version/" + this.version + "/" + filePath);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return fis;
}
public static void main(String[] args) {
ServiceFile sf = new ServiceFile();
List<String> paths = sf.getUpdateFiles();
for(int i = 0; i < paths.size(); i ++){
System.out.println(paths.get(i));
}
}
}
客户端代码 与服务的同样的架构层
1.前端的图形界面类
package client;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Toolkit;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
@SuppressWarnings("serial")
public class Main extends JFrame {
private Main main;
private JButton update;
private JTextField address;
private JTextField port;
private JTextArea result;
private JScrollPane jsp;
private JProgressBar jpb;
public Main(){
this.setLayout(new BorderLayout());
//top
JPanel topPanel = new JPanel();
JLabel lable1 = new JLabel("IP");
JLabel lable2 = new JLabel("Port");
this.address = new JTextField();
address.setColumns(20);
address.setText("127.0.0.1");
this.port = new JTextField();
port.setColumns(10);
port.setText("45678");
this.update = new JButton("Update");
update.setName("Update");
topPanel.add(lable1);
topPanel.add(address);
topPanel.add(lable2);
topPanel.add(port);
topPanel.add(update);
//center
JPanel centerPanel = new JPanel();
this.result = new JTextArea(15,50);
this.result.setLineWrap(true);
this.result.setFont(new Font("仿宋",Font.BOLD,12));
this.jsp = new JScrollPane(this.result);
this.result.setAutoscrolls(true);
this.result.setEnabled(false);
centerPanel.add(jsp);
//botton
this.jpb = new JProgressBar(0,Integer.MAX_VALUE);
this.jpb.setSize(600, 50);
this.jpb.setVisible(false);
this.jpb.setStringPainted(true);
JPanel bottonPanel = new JPanel();
bottonPanel.add(this.jpb);
this.getContentPane().add(topPanel,BorderLayout.NORTH);
this.getContentPane().add(bottonPanel,BorderLayout.SOUTH);
this.getContentPane().add(centerPanel,BorderLayout.CENTER);
this.setTitle("Client");
this.setResizable(false);
this.setSize(600, 350);
Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize();
int screenWidth = (int) dimension.getWidth();
int screenHeight = (int) dimension.getHeight();
this.setLocation((screenWidth - this.getWidth())/2, (screenHeight - this.getHeight())/2);
this.setVisible(true);
this.addWindowListener(new MyWindowAdapter());
update.addMouseListener(new MyMouseAdapter());
this.main = this;
}
public void printMessage(String message){
//System.out.println(message);
this.result.append(message + "\n");
this.result.selectAll();
}
public void setEnableUpdateButton(){
this.update.setEnabled(true);
}
public void initProcessBar(Long max){
int temMax = (int)(max/1024/1024);
this.jpb.setVisible(true);
this.jpb.setMinimum(1);
this.jpb.setMaximum(temMax);
this.jpb.updateUI();
}
public void setProcessBarValue(Long value){
int temValue = (int)(value/1024/1024);
this.jpb.setString("当前进度:" + ((temValue * 100)/this.jpb.getMaximum()) + "%");
this.jpb.setValue(temValue);
}
public static void main(String[] args) {
new Main();
}
/**
* 开始监听,停止监听
*/
class MyMouseAdapter extends MouseAdapter{
@Override
public void mouseClicked(MouseEvent e) {
if(e.getSource() instanceof JButton){
JButton button = (JButton) e.getSource();
if(button == update && button.isEnabled()){
update.setEnabled(false);
String ip = address.getText();
int p = Integer.valueOf(port.getText());
new Client(ip, p, main);
}
}
}
}
/**
* 控制窗体关闭
*/
class MyWindowAdapter extends WindowAdapter{
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
super.windowClosing(e);
}
}
}
2。 客户端的Socket操作类
package client;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.util.ArrayList;
import java.util.List;
public class Client extends Thread{
private String ip;
private int port;
private Main main;
public Client(String ip ,int port, Main main){
this.ip = ip;
this.port = port;
this.main = main;
new Thread(this).start();
}
@Override
public void run() {
try {
//InetAddress inetAddress = InetAddress.getByName(ip);
SocketAddress address = new InetSocketAddress(ip,port);
Socket socket = new Socket();
socket.connect(address);
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
//ObjectInputStream ois = new ObjectInputStream(bis);
DataInputStream dis = new DataInputStream(bis);
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
//ObjectOutputStream oos = new ObjectOutputStream(bos);
DataOutputStream dos = new DataOutputStream(bos);
ClientFile cf = new ClientFile();
String clientVersion = cf.getClientVersion();
this.main.printMessage("客户端的版本是 " + clientVersion);
dos.writeUTF(clientVersion);//1.writeUTF
dos.flush();
String serviceVersion = dis.readUTF();//readUTF
this.main.printMessage("服务器最新版本为:" + serviceVersion);
String isNeedUpdate = dis.readUTF();//2.readUTF
int updateFileSize = 0;
if("Yes".equals(isNeedUpdate)){
updateFileSize = dis.readInt();
this.main.printMessage("总共有更新文件数量:" + updateFileSize);
List<String> filePaths = new ArrayList<String>();
List<Long> fileSizes = new ArrayList<Long>();
for(int i = 0; i < updateFileSize; i ++){
String filePath = dis.readUTF();//3.readUTF
filePaths.add(filePath);
}
Long maxSize = 0L;
for(int i = 0; i < updateFileSize; i ++){
Long fileSize = dis.readLong();//3.readLong
fileSizes.add(fileSize);
maxSize += fileSize;
}
this.main.initProcessBar(maxSize);
Long currentDownLoadSize = 0L;
for(int i = 0; i < updateFileSize; i ++){
File file = cf.isExistOrCreate(filePaths.get(i));
FileOutputStream fos = cf.getFileOutputStream(file);
int length = 0;
byte[] b = new byte[102400];
while((length + b.length) <= fileSizes.get(i)){
dis.read(b);
fos.write(b, 0, b.length);
length = length + b.length;
}
int leftLength = (int)(fileSizes.get(i) - length);
dis.read(b,0,leftLength);
fos.write(b,0,leftLength);
fos.close();
currentDownLoadSize += fileSizes.get(i);
this.main.setProcessBarValue(currentDownLoadSize);
this.main.printMessage(filePaths.get(i) + "..............." + fileSizes.get(i) + "B");
}
cf.setClientVersion(serviceVersion);
this.main.printMessage("已经升级为最新版本");
}else{
this.main.printMessage("客户端是最新版本,不需要升级");
}
this.main.setEnableUpdateButton();
dos.close();
dis.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
3。本地文件的后台操作类
package client;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
public class ClientFile {
private String version;//客户端版本号
private String installDir;//安装路径
/**
* 查找客户端上最新版本
*/
public String getClientVersion(){
Properties p = new Properties();
try {
p.load(new FileInputStream("./client_version/version.properties"));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
this.version = p.getProperty("version");
return this.version;
}
public void setClientVersion(String version){
Properties p = new Properties();
try {
FileInputStream fis = new FileInputStream("./client_version/version.properties");
p.load(fis);
Enumeration<String> e = (Enumeration<String>) p.propertyNames();
while(e.hasMoreElements()){
String key = e.nextElement();
String value = p.getProperty(key);
p.put(key, value);
}
p.put("version", version);
FileOutputStream fos = new FileOutputStream("./client_version/version.properties");
p.store(fos, "update from service");
fis.close();
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public String getInstallDir(){
Properties p = new Properties();
try {
p.load(new FileInputStream("./client_version/version.properties"));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
this.installDir = p.getProperty("installDir");
return this.installDir;
}
public File isExistOrCreate(String filePath){
if(this.installDir == null){
this.installDir = this.getInstallDir();
}
File file = new File(this.installDir + filePath);
//System.out.println("path: " + this.installDir + filePath);
if(file.exists()){
return file;
}else{
int end = filePath.lastIndexOf("\\");
if(end != -1){
//System.out.println("parent Dir : " + file.getParent());
File folder = new File(file.getParent());
folder.mkdirs();
folder.setReadable(true);
folder.setWritable(true);
}
}
file = new File(this.installDir + filePath);
if(file.exists()){
return file;
}
try {
file.createNewFile();
file.setReadable(true);
file.setWritable(true);
} catch (IOException e) {
e.printStackTrace();
}
return file;
}
public FileOutputStream getFileOutputStream(File file){
FileOutputStream fos = null;
try {
fos = new FileOutputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return fos;
}
}
目录结构,和运行截图
下载地址:可以去我的下载地址,我已经传我下载空间了!!
相关推荐
总的来说,理解和掌握Zookeeper的客户端使用,特别是图形化界面查看节点信息,对于开发和运维分布式系统至关重要。它能帮助开发者更好地监控和管理分布式环境中的数据和状态,确保服务的稳定运行。
在IT行业中,客户端软件的自动更新是保持软件稳定性和功能最新化的重要环节。本文将深入讲解如何使用C# WinFrom客户端结合WebService实现自动更新升级的功能。 首先,我们要理解C# WinFrom客户端。C#是一种面向对象...
在这个压缩包中,包含的是MySQL 5.5的Windows 32位安装程序以及一个图形化界面工具。 首先,`mysql-5.5.22-win32.msi` 文件是MySQL 5.5.22的安装程序,适用于Windows操作系统。在安装过程中,用户可以选择安装类型...
总的来说,Java 实现的 Telnet 客户端程序结合了网络编程、多线程和图形用户界面设计等技术,为用户提供了一种方便的远程操作工具。通过分析和学习这个程序,我们可以深入了解这些技术的运用,同时也可以将其作为...
在IT行业中,Qt是一个广泛应用的跨平台C++图形用户界面库,它提供了丰富的API和工具,使得开发者可以创建出美观且功能强大的桌面和移动应用程序。本文将深入探讨如何使用Qt来实现一个自动升级系统,包括服务器端和...
Java图形自动更新程序是利用Java Swing库来构建的用户界面,结合Socket通信技术,实现软件的后台自动更新功能。在现代软件开发中,保持应用程序的最新状态至关重要,以确保用户可以享受到最新的特性和安全修复。Java...
描述中提到“和使用命令一样好用”,意味着该工具虽然以图形化界面呈现,但功能强大,可以媲美命令行工具,如`mysql`客户端,用户可以在GUI环境中执行大部分命令行能做的任务,如创建数据库、表,插入、更新和删除...
在本文中,我们将深入探讨如何安装MySQL服务端,并重点介绍如何安装和使用图形界面的MySQL客户端,以便更高效、直观地管理数据库。 首先,让我们了解如何安装MySQL服务端。在大多数Linux发行版中,可以通过包管理器...
这样设置后,当你执行Oracle的安装程序,图形界面应该会在客户端机器上弹出。 然而,如果在图形界面弹出后,安装过程中遇到错误,比如Oracle 11g安装时提示需要填写hosts,那可能是因为在/etc/hosts文件中没有设置...
"Linux上网登陆客户端(图形界面)"指的是专为Linux设计的,带有图形用户界面(GUI)的DRCOM登录程序,用于连接并认证到网络。在本例中,提供的压缩包文件"drcom-pum-1.0"可能就是这样一个客户端工具。 DRCOM是一种...
在MySQL的环境中,客户端界面程序扮演着至关重要的角色,它为用户提供了图形化的用户界面(GUI),使得数据库的管理和操作变得更加直观和便捷。本篇文章将深入探讨MySQL的客户端界面程序,特别是提及的"navicat8_...
52mud图形客户端是一款专为网络文字游戏52mud设计的图形化用户界面,它旨在为玩家提供更直观、更便捷的游戏体验,将传统的纯文本输入模式转化为视觉效果丰富的图形界面。这款客户端的出现,极大地提升了游戏的互动性...
总之,这个程序结合了QT的图形界面设计能力、MySQL的数据存储功能,以及数据统计和可视化技术,为用户提供了高效的学习管理工具。通过理解和应用这些知识点,开发者可以创建出强大而实用的应用程序。
基本要求:将DES加密算法应用于网络通信,使用RSA算法自动分配密钥,设计好界面,可验证自动生成的密钥和加解密正确的结果。 具体实现要求:客户端和服务器建立连接后,客户端生成一个随机DES密钥;服务器生成一个...
在Mac OS Sierra操作系统中,管理和操作数据库通常需要借助于图形用户界面(GUI)工具,以提高效率并简化数据库管理任务。对于PostgreSQL和MySQL这两种广泛使用的开源关系型数据库管理系统,存在许多优秀的GUI客户端...
它使用面向对象的编程模型,提供图形化的界面设计工具,使得开发者可以快速构建桌面应用程序。 - **自动更新机制**:这是软件工程中的一种常见实践,旨在确保用户始终运行的是最新和最安全的版本。自动更新程序通常...
"多客户端图形工具.rar" 这个标题暗示了我们正在讨论一个能够支持多个客户端同时使用的图形界面应用程序。通常这类工具是为分布式系统设计的,可能是一个跨平台的应用,允许用户通过图形界面进行交互。"rar" 是一种...
#### 五、Web客户端自动化测试工具——I-bench I-bench是一种专门用于测试Internet浏览器及其插件性能的自动化测试工具。它通过模拟Web客户端与Web服务器之间的通信环境,利用测试用例中的Java/JavaScript代码来...
首先,InfluxDB Studio是常用的图形化界面工具,可用于管理InfluxDB实例,执行查询,创建数据库,配置用户等。在这个场景中,我们看到两个配置文件`InfluxDBStudio.exe.config`和`InfluxDBStudio.vshost.exe.config`...
2. **命令行模式**:除了图形界面,WinSCP还支持命令行模式,适用于自动化场景。 3. **集成开发环境**:可以与Visual Studio、Eclipse等IDE集成,方便开发者进行代码版本控制和部署。 ### 六、总结 WinSCP作为一款...