nodejs如何实现简单的文件服务器

编程

文件名的长度(两个字节)

文件名(长度不定,由前两个字节决定)

文件内容的长度(8个字节)

内容 (长度不定,由前8个字节决定)

 

使用nodejs 实现服务端

var net = require("net");

var fs = require( "fs" );

var server = net.createServer();

server.on("connection", function(client){

console.log("client connected to server。IP:%s,port%s", client.remoteAddress, client.remotePort);

var isFirst = true ;

var fd ;

var contentLength = 0 ;

var dataTotalLength =0;

var receiveData = Buffer.alloc(0);

// data长度不可控,需要自己合并多个data直至指定的要求或者发送的socket发送FIN

client.on("data", function(data){

if (isFirst) {

receiveData = Buffer.concat([receiveData, data]);

if (receiveData.length < 2) {

console.error("奇葩,data长度为%s", data.length)

return ;

}else {

var start = 0;

var end = 2;

var buffer = Buffer.from(receiveData.slice(start, end));

var filenamelength = buffer.readInt16BE();

console.log("文件名长度为:%s" , filenamelength);

}

if (receiveData.length < filenamelength + 10) {

console.error("奇葩,data长度为%s", data.length)

return;

}

var start = end;

var end = end + filenamelength;

var buffer = Buffer.from(receiveData.slice(start, end));

var filename = buffer.toString();

console.log("文件名为:%s" ,filename);

var start = end;

var end = end + 8;

var buffer = Buffer.from(receiveData.slice(start, end));

contentLength = buffer.readBigInt64BE();

console.log("文件长度为:%s" , contentLength);

var newfilename = "data/" + filename;

fd = fs.openSync(newfilename, "w+");

isFirst = false;

var var1 = receiveData.slice(end)

fs.writeFileSync(fd, var1);

dataTotalLength += receiveData.length - end;

}else {

fs.writeFileSync(fd, data);

dataTotalLength += data.length;

}

if(dataTotalLength == contentLength){

console.log("文件传输完毕");

}

});

client.on("end", function () {

console.log(dataTotalLength);

console.log(contentLength);

console.log("关闭socket!")

});

client.on("error",function (e) {

console.error(e);

})

});

server.listen(7251, "0.0.0.0");

 

虽然不是很喜欢这种弱类型的语言,但是nodejs与生俱来的的多线程特性还是让人震惊,以上实现中没有出现任何与Thread相关的关键词,但这却是一个支持多线程上传的服务。

 

java 客户端(多线程上传)

package test;

import java.io.DataOutputStream;

import java.io.File;

import java.io.FileInputStream;

import java.net.Socket;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

import java.util.concurrent.atomic.AtomicInteger;

public class FileTransferClient{

public static final String SERVER_IP = "127.0.0.1"; // 服务端IP

public static final int SERVER_PORT = 7251; // 服务端端口

public static void main(String[] args) throws Exception{

String datadir = "C:\Users\who\Desktop\testdata\data\face" ;

File directory = new File(datadir) ;

assert directory.isDirectory() ;

ExecutorService executor = Executors.newFixedThreadPool(10);

int count = 0 ;

for (File file : directory.listFiles()) {

if(file.isFile()) {

Task task = new Task(file.getAbsolutePath());

executor.submit(task);

count ++ ;

}

}

while (true) {

if (aCount.get() == count) {

System.out.println("end");

executor.shutdown();

break;

}

Thread.sleep(1000);

}

}

public static AtomicInteger aCount = new AtomicInteger(0);

}

class Task implements Runnable {

private String filename;

public Task(String filename){

this.filename = filename ;

}

@Override

public void run() {

try {

Socket socket = new Socket(FileTransferClient.SERVER_IP, FileTransferClient.SERVER_PORT);

FileInputStream fis = null;

DataOutputStream dos = null;

File file = new File(filename);

if (file.exists()) {

fis = new FileInputStream(file);

dos = new DataOutputStream(socket.getOutputStream());

// 文件名和长度

byte[] namebytes = file.getName().getBytes();

dos.writeShort(namebytes.length);

dos.write(namebytes);

dos.writeLong(file.length());

dos.flush();

byte[] bytes = new byte[1024];

int length;

while ((length = fis.read(bytes, 0, bytes.length)) != -1) {

dos.write(bytes, 0, length);

dos.flush();

}

}

if (fis != null)

fis.close();

if (dos != null)

dos.close();

if (!socket.isClosed()) {

socket.close();

}

} catch (Exception e) {

e.printStackTrace();

}

FileTransferClient.aCount.addAndGet(1);

}

}

 

nodejs 客户端

var net = require("net");

var fs = require("fs");

function sendfile(filename) {

console.log(filename);

var socket = new net.Socket();

socket.on("ready",function () {

var contentSize = 0 ;

fs.stat(filename,function(error,stats){

if(error){

console.error(error)

}else{

contentSize = stats.size ;

console.log(contentSize) ;

}

var length = 2 + filename.length + 8 ;

var buffer = Buffer.alloc(length) ;

buffer.writeInt16BE(filename.length,0);

buffer.write(filename,2);

var bigInt = BigInt(contentSize);

var start = Number(2 + filename.length);

buffer.writeBigInt64BE(bigInt,start);

socket.write(buffer.slice(0,length)) ;

// 大文件应该一次读取不了,不想写了

var data = fs.readFileSync(filename);

socket.write(data);

}) ;

}) ;

socket.on("error",function (e) {

console.error(e)

}) ;

socket.connect(7251, "localhost");

}

sendfile("app.js");

sendfile("client.js");

 

 

nodejs 的 socket在处理字节流时不能主动的去read, 只能靠data事件来触发回调函数,但是data并不是一次能接收到所有的字节流,因此在处理时需要自己合并多个data才行,以下是一个小小的使用建议。

var net = require("net");

var client = new net.Socket();

var receiveData = Buffer.alloc(0);

client.connect(8899, "localhost");

client.on("data", function (data) {

// 这里只是合并data

receiveData = Buffer.concat([receiveData, data]);

});

client.on("error", function (e) {

console.error(e)

});

client.on("end", function (e) {

// 接收完所有data再处理

console.log(receiveData.toString());

});

 

 

 

 

以上是 nodejs如何实现简单的文件服务器 的全部内容, 来源链接: utcz.com/z/514338.html

回到顶部