首先是socket的概念
网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。
建立网络通信连接至少要一对端口号(socket)。socket本质是编程接口(API),对TCP/IP的封装,TCP/IP也要提供可供程序员做网络开发所用的接口,这就是Socket编程接口;HTTP是轿车,提供了封装或者显示数据的具体形式;Socket是发动机,提供了网络通信的能力。
设计界面展示:
加盟商文件建立
加盟商界面展示
关键字及精准搜索
创建文件夹及文件保存
可以直接在总部文件里面改奶茶信息
营业额统计及txt文件生成
客户端(加盟商)设计思路:客户端与服务端建立连接,选择客户端本地文件,先将文件名及大小等属性发送给服务端,再将文件通过流的方式传输给服务端。传输的进度打印到控制台中,直到传输完成。
主要代码: // 接收文件
public void recFile(String savePath) {
try {
dis = new DataInputStream(socket.getInputStream());
String fileName = dis.readUTF();
long fileLength = dis.readLong();
File file = new File(savePath);
fos = new FileOutputStream(file);
byte[] bytes = new byte[1024];
int length = 0;
while ((length = dis.read(bytes, 0, bytes.length)) != -1) {
fos.write(bytes, 0, length);
fos.flush();
}
System.out.println("======== 文件接收成功 [File Name:" + fileName + "]" + "[Size:" + getFormatFileSize(fileLength) + "] ========");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fos != null) {
fos.close();
}
服务端(总部)设计思路:服务端接收客户端的请求(阻塞式),每接收到一个客户端请求连接后,就新开一个处理文件的线程,开始写入流,将文件到服务器的指定目录下,并与传输过来的文件同名。
使用线程处理每个加盟商传输的文件,我们的总部处理加盟商的连接请求是同步进行的,每次接收到来自加盟商的连接请求后,都要先跟当前的加盟商通信完之后才能再处理下一个连接请求。 这在并发比较多的情况下会严重影响程序的性能,为此,我们可以改为如下这种异步处理与加盟商通信的方式,每接收到一个Socket就建立一个新的线程来处理它。
// 启动服务器,线程部分重点代码
public void load() throws Exception {
while (true) {
Socket socket = this.accept();
new Thread(new Task(socket)).start();
}
}
TXT文件的读写
//使用FileInputStream实现读取txt文件内容
//使用FileOutputStream实现写入txt文件内容
// 设置文件读取路径
public static void setReadFolder(String path) {
readFolderPath = path;
turnoverPath = path + "/" + "Turnover.txt";
miklTeaPath = path + "/" + "MilkTea.txt";
}
}
Socket通信部分:
Client:
public class Client extends Socket {
private Socket socket;
private SocketTool socketTool;
public Client() throws Exception {
super(Config.serverIp, Config.serverPort);
this.socket = this;
socketTool = new SocketTool(socket);
System.out.println("Cliect[port:" + socket.getLocalPort() + "] 成功连接服务端");
}
// 获取文件
public void getFile(String savePath) {
socketTool.sendMessage("#get");
new SocketTool(socket).recFile(savePath);
}
// 发送文件
public void sendFile(String sendFilePath) {
socketTool.sendMessage("#send");
new SocketTool(socket).sendFile(sendFilePath);
}
}
Server:
public class Server extends ServerSocket {
private HeadquartersUI headquartersUI = null;
public Server() throws Exception {
super(Config.serverPort);
}
public Server(HeadquartersUI headquartersUI) throws Exception {
super(Config.serverPort);
this.headquartersUI = headquartersUI;
}
// 启动服务器
public void load() throws Exception {
while (true) {
Socket socket = this.accept();
new Thread(new Task(socket)).start();
}
}
// 服务器任务
class Task implements Runnable {
private Socket socket;
private SocketTool socketTool;
public Task(Socket socket) {
this.socket = socket;
socketTool = new SocketTool(socket);
}
@Override
public void run() {
try {
String message = socketTool.recMessage();
if (message.startsWith("#get")) {
new SocketTool(socket).sendFile(Config.miklTeaPath);
} else if (message.startsWith("#send")) {
new SocketTool(socket).recFile(Config.turnoverFolderPath + "/" + StrTool.geUUID() + ".csv");
}
if (headquartersUI != null) {
headquartersUI.rfTable();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}