Server端:
import java.net.*;
import java.io.*;
public class Server {
// 服务器监听端口
private int port;
// 文件保存路径
private String path;
// 判断server是否启动
private boolean started = false;
public static void main(String[] args) {
new Server(8888, "E:/").listen(8888);
}
// 初始化服务器端口及文件保存路径
private Server(int port, String path) {
this.port = port;
this.path = path;
}
// 二进制转换为十进制
public static int b2i(byte[] b) {
int value = 0;
for (int i = 0; i < 4; i++) {
int shift = (4 - 1 - i) * 8;
value += (b[i] & 0x000000FF) << shift;
}
return value;
}
public static long b2l(byte[] b) {
long s = 0;
long s0 = b[0] & 0xff;
long s1 = b[1] & 0xff;
long s2 = b[2] & 0xff;
long s3 = b[3] & 0xff;
long s4 = b[4] & 0xff;
long s5 = b[5] & 0xff;
long s6 = b[6] & 0xff;
long s7 = b[7] & 0xff;
s1 <<= 8;
s2 <<= 16;
s3 <<= 24;
s4 <<= 8 * 4;
s5 <<= 8 * 5;
s6 <<= 8 * 6;
s7 <<= 8 * 7;
s = s0 | s1 | s2 | s3 | s4 | s5 | s6 | s7;
return s;
}
// 主线程始终处于监听状态,等待客户端连接
private void listen(int port) {
Socket s = null;
ServerSocket ss = null;
try {
ss = new ServerSocket(port);
started = true;
System.out.println("监听端口:" + port);
while (started) {
s = ss.accept();
System.out.println("A client connected!");
new Thread(new HandleThread(s)).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
// 处理接收文件并做相关处理的线程类
private class HandleThread implements Runnable {
Socket s = null;
private HandleThread(Socket s) {
this.s = s;
}
public void run() {
String name = getName(s);
System.out.println(name);
String isOver = getFile(name, s);
System.out.println(isOver);
}
// 1、先获取文件名,并按照文件名创建相应文件壳,用于储存文件内容
private String getName(Socket s) {
try {
InputStream is = s.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
byte[] buffer1 = new byte[4];
bis.read(buffer1);
int name_len = b2i(buffer1);
System.out.println("s_name_len = " + name_len);
// 开始获取文件名
byte[] buffer2 = new byte[name_len];
bis.read(buffer2);
return new String(buffer2);
} catch (IOException e) {
return new String("接收过程出现故障!");
}
}
// 2、开始接收文件
private String getFile(String name, Socket s) {
InputStream is = null;
BufferedInputStream bis = null;
FileOutputStream fos = null;
BufferedOutputStream bos = null;
File file = null;
try {
file = new File(path + "/" + name);
if (!file.exists()) {
file.createNewFile();
}
is = s.getInputStream();
bis = new BufferedInputStream(is);
fos = new FileOutputStream(file);
bos = new BufferedOutputStream(fos);
byte[] bytes = new byte[8];
bis.read(bytes);
long size = b2l(bytes);
System.out.println("s_size = " + size);
byte[] buffer = new byte[1024];
long count = 0;
while (count < size) {
long num = bis.read(buffer);
bos.write(buffer);
count = count + num;
}
/*
int a = -1;
while ((a = bis.read()) != -1) {
bos.write(a);
}*/
bos.flush();
bos.close();
return "文件 " + file.getName() + " 大小 " + file.length()
+ "接收完成!";
} catch (IOException e) {
return "接收失败";
} finally {
try {
if (bos != null) {
bos.close();
bos = null;
}
if (fos != null) {
fos.close();
fos = null;
}
if (bis != null) {
bis.close();
bis = null;
}
if (is != null) {
is.close();
is = null;
}
if (s != null) {
s.close();
s = null;
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
Client
import java.net.*;
import java.io.*;
public class Client {
// 服务器ip地址
private String ipAdd;
// 服务器监听端口号
private int port;
// 发送文件路径
private String path;
public static void main(String[] args) {
new Client("127.0.0.1", 8888, "D:\\把悲伤留给自己.mp3").connect();
}
public Client(String ipAdd, int port, String path) {
this.ipAdd = ipAdd;
this.port = port;
this.path = path;
}
// 连接到服务器
private void connect() {
Socket s = null;
OutputStream os = null;
BufferedOutputStream bos = null;
try {
s = new Socket(ipAdd, port);
os = s.getOutputStream();
bos = new BufferedOutputStream(os);
File file = new File(path);
// 文件名
String name = file.getName();
// 文件大小
long size = file.length();
System.out.printf("%s%s%s%s%s", "Sending file ", name, " size ",
size, " bytes to server...");
// 先发送文件名到服务器
boolean completed1 = sendName(name, bos);
boolean completed2 = sendContent(file, bos);
if (completed1 && completed2) {
System.out.println("文件发送成功");
} else {
System.out.println("文件发送失败");
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
System.out.println("文件未检测到");
} finally {
try {
if (bos != null) {
bos.close();
bos = null;
}
if (os != null) {
os.close();
os = null;
}
} catch (IOException e) {
}
}
}
// 整型数据转换为byte数据方法
public static byte[] i2b(int i) {
return new byte[] { (byte) ((i >> 24) & 0xFF),
(byte) ((i >> 16) & 0xFF), (byte) ((i >> 8) & 0xFF),
(byte) (i & 0xFF) };
}
// long类型转成byte数组
public static byte[] l2b(long number) {
long temp = number;
byte[] b = new byte[8];
for (int i = 0; i < b.length; i++) {
b[i] = new Long(temp & 0xff).byteValue();
temp = temp >> 8; // 向右移8位
}
return b;
}
// 发送文件名长度以及文件名到服务器
private boolean sendName(String name, BufferedOutputStream bos) {
byte[] buffer = name.getBytes();
int name_len = buffer.length;
try {
// 这就要求文件名长度不能长于65535,当然,这显然不太可能!!!
bos.write(i2b(name_len));
bos.write(buffer);
bos.flush();
return true;
} catch (IOException e) {
return false;
}
}
// 发送文件内容到服务器
private boolean sendContent(File file, BufferedOutputStream bos) {
try {
long size = file.length();
// 先发送文件长度
bos.write(l2b(size));
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
byte[] buffer = new byte[1024];
long count = 0;
// 一边读入,一边写出
while (count < size) {
long d = bis.read(buffer);
count = count + d;
bos.write(buffer);
}
bos.flush();
return true;
} catch (FileNotFoundException e) {
System.out.println("未检测到发送文件!");
return false;
} catch (IOException e) {
return false;
}
}
}
问题补充:Server端发送的文件内容和Client端接收的文件内容大小不一致,服务器端接收到的数据比客户端发送的数据大
相关推荐
在IT领域,网络通信是不可或缺的一部分,而TCP(Transmission Control Protocol)作为一种面向连接的、可靠的传输协议,常用于文件传输。本示例将探讨如何利用Qt框架实现TCP文件传输功能。Qt是一个强大的C++库,提供...
2. 连接成功后,客户端可以打开本地文件,读取文件内容并分块发送。 3. 每发送一部分数据,客户端可以等待服务器的确认,确保数据正确到达。 **五、实现文件传输** 1. 在服务器端,接收到数据后,将其写入到临时...
此外,为了确保文件的完整性和一致性,可以采用CRC校验或MD5哈希值的方式验证传输的数据是否与原始文件一致。在QT中,可以使用QFile和QCryptographicHash类来计算文件的哈希值。 最后,文件传输完成后,别忘了关闭...
为了保证数据的完整性,TCP协议使用了校验和机制,每个数据段都会附带一个校验和,接收端接收到数据后会计算校验和,如果与发送端计算的结果不一致,则会要求重传该数据段。 在文件传输系统的设计中,我们需要考虑...
在传统的文件传输中,如果一次性发送整个大文件,可能会因为网络状况不稳定导致数据丢失,或者消耗过多的网络带宽,从而降低传输效率。为了解决这个问题,分包技术应运而生。分包就是将一个大文件拆分成多个小的...
SSH是一种网络协议,用于安全地远程登录、执行命令以及传输文件。通过SSH,用户可以在Windows电脑上与Linux服务器建立加密连接,安全地发送和接收文件,避免了传统FTP方式可能存在的数据泄露或篡改风险。此外,“并...
"TCP大文件批量传输"这个话题涉及到如何高效、稳定地通过TCP协议来发送大量大体积的文件。在描述中提到了已修复的部分bug,这暗示了在实现过程中可能存在一些技术挑战,比如文件读取错误、网络中断或数据丢失等问题...
在这个项目中,我们聚焦于构建一个包含加解密功能的文件传输系统,它由发送端和接收端两部分组成,旨在确保在传输过程中文件的机密性和完整性。 首先,我们要理解的是“本地文件传输”。本地文件传输指的是在同一台...
该项目是基于Qt库实现的文件网络传输应用,服务器部分运行在Linux操作系统上,而客户端则在Windows 10系统上运行。Qt是一个跨平台的C++应用程序开发框架,广泛用于创建图形用户界面和其他应用程序。其丰富的功能和多...
UDP(User Datagram Protocol)是一种无连接的、不可靠的传输层协议,它是互联网协议套件的一部分。...不过,对于大规模的文件传输,还是建议使用TCP或者更高级的文件传输协议,以确保数据的完整性和一致性。
为了实现断点续传,我们需要在服务器端和客户端维护文件的元信息,包括已传输的文件大小和当前位置。当客户端中断连接后,再次连接时,可以向服务器发送当前的文件状态,服务器根据这个信息找到上次传输的结束位置,...
这个过程可能需要多次读取和发送,因为文件可能较大,不能一次性发送完成。 客户端则通过`Receive()`方法接收来自服务器的数据,同样需要将接收到的数据写入到本地文件。为了确保数据的完整性和一致性,通常会使用...
2. **数据分块**:大文件会被分成多个小的数据段,每个数据段作为一个TCP报文在网络中传输。这样可以提高传输效率,也便于错误处理。 3. **错误检测与纠正**:TCP使用校验和来检测数据在传输过程中是否出错。如果...
在IT领域,多线程是一种常见且重要的编程技术,尤其在处理大文件传输时,能够显著提高效率。本文将深入探讨“多线程传输文件”的概念、原理以及实际应用。 多线程指的是在一个程序中同时运行多个独立的执行线程。在...
在IT领域,大型文件传输是一项重要的技术挑战,尤其是在网络带宽有限、文件尺寸庞大的情况下。本文将深入探讨大型文件传输的实现方式,以C语言为例,解析其背后的原理和技术细节。 首先,我们要理解大型文件传输的...
- 文件传输过程中可能出现各种错误,如网络中断、文件不存在、权限问题等。VB中的`On Error`语句可以用来捕获并处理错误。 - 对于网络通信,应处理`SocketException`,如超时、连接失败等。 - 文件操作中,要检查...
- 如果是二进制文件,确保数据的大小和顺序在发送和接收过程中保持一致,因为二进制文件通常对数据的精确性有较高要求。 在LabVIEW中,可以通过调试和日志记录来定位问题,查看是否所有数据都成功发送和接收,以及...
在互联网上,大文件通常被分割成小的数据包进行传输,这是因为TCP/IP协议栈的设计如此,每个数据包包含了部分文件内容和必要的头部信息,用于标识数据来源、目的地以及顺序等。这种方式可以提高传输效率,但同时也...
在信息技术日新月异的今天,文件传输成为了日常工作和生活中不可或缺的一部分。对于局域网内的设备来说,快速、高效的文件传输系统更是至关重要。本文将深入探讨一个利用Winsock库构建的局域网文件传输系统,该系统...