java 客户端-服务器通信中的问题
Problem in java client-server communication
我在 java 中实现了客户端-服务器通信。以下是传输一组文件的代码:
服务器代码:
public class TransferServer {
static List<String> filesListInDir = new ArrayList<String>();
static String zipName = "tmp.tar.gz";
public static void main(String[] args) throws IOException, InterruptedException {
// TODO Auto-generated method stub
ServerSocket s1 = new ServerSocket(7104);
System.out.println("Transfer server started");
while (true) {
Socket sckt = s1.accept();
System.out.println("Request received. Please wait..");
zipData();
transferData(sckt);
System.out.println("Data transferred");
}
}
private static void transferData(Socket ts) throws IOException {
FileInputStream fi=new FileInputStream(zipName);
byte b[] = new byte[8000];
fi.read(b, 0, b.length);
OutputStream os = ts.getOutputStream();
os.write(b, 0, b.length);
fi.close();
}
客户代码:
public class Fetchmyfile {
static String addr_list="/home/pi/addresslist.txt";
static String zipName = "tmp.tar.gz";
public static void main(String[] args) throws InterruptedException, IOException {
// TODO Auto-generated method stub
trigger();
}
private static void trigger() throws InterruptedException, IOException {
// TODO Auto-generated method stub
String[] hostList = readAddressList(addr_list);
//remove tmp.zip
for (int i = 0; i < hostList.length; i++) {
Runtime r = Runtime.getRuntime();
Process p = null;
try {
p = r.exec("rm /home/pi/combined_data/"+hostList[i]+"/"+zipName);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
p.waitFor();
}
//remove complete
for (int i = 0; i < hostList.length; i++) {
String addr = hostList[i];
TransferClient clientInstance = new TransferClient();
clientInstance.fileCopy(addr, "/home/pi/combined_data/"+addr.trim()+"/tmp.tar.gz");
}
System.out.println("All data has been transferred");
}
private static String[] readAddressList(String addr_list) throws IOException {
FileReader fileReader = new FileReader(addr_list);
BufferedReader bufferedReader = new BufferedReader(fileReader);
List<String> lines = new ArrayList<String>();
String line = null;
while ((line = bufferedReader.readLine()) != null)
{
lines.add(line);
}
bufferedReader.close();
System.out.println("Loaded the host list");
return lines.toArray(new String[lines.size()]);
}
}
public class TransferClient {
public boolean fileCopy(String sensor_node_ip, String filename) throws InterruptedException{
//public static void main(String args[]) throws IOException
{
try {
//String filename = "‎�‎�localfile.zip";
byte b[] = new byte[8000];
Socket s = null;
try {
s = new Socket(sensor_node_ip, 7104);
System.out.println("connection done");
} catch (IOException e) {
System.out.println("Couldn't connect to the server");
return false;
}
InputStream iss = s.getInputStream();
FileOutputStream fr = new FileOutputStream(filename);
iss.read(b, 0, b.length);
fr.write(b, 0, b.length);
fr.close();
s.close();
//unZip(filename);
System.out.println("Tar file recieved from " + sensor_node_ip);
return true;
}
catch (IOException e){
return false;
}
}
}
我面临的问题是,对于一个相对较大的文件,客户端创建了一个具有预期名称的声明缓冲区大小的文件。但是该文件不可读并且是存档文件,无法提取。然而,服务器实际上拥有无论如何都是正确的文件。这可能是什么原因。非常感谢任何 suggestions/pointers。
在我看来,问题是您正在写入 8000 个字节,而不管输出的实际大小如何。您甚至没有尝试检查文件的大小,因此如果文件小于 8000 字节,您可能会写入垃圾,或者如果文件超过 8000 字节,则 t运行cating 它。
相反,您应该读取文件直到没有更多的字节要读取,并确保您只写入实际读取的字节数(因为读取可能读取的缓冲区长度少于字节)。
这真的很基础I/O。
因此,以下示例将概念剥离到最基本的框架,仅关注客户端和服务器之间的文件传输。为了对比,我在每一端都加了MD5校验,这样就很容易对比文件结果了。
编程的一个重要方面是,永远不要假设任何事情。总是看看你得到了什么,并在 运行 时间做出决定(例外情况是如果它被记录在案并事先达成一致,但即使那样,我也会仔细检查,因为我不相信任何人)
服务器
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.NoSuchAlgorithmException;
public class Server {
public static void main(String[] args) {
try (ServerSocket server = new ServerSocket(7104)) {
Socket socket = server.accept();
read(socket);
} catch (IOException ex) {
ex.printStackTrace();
}
}
protected static void read(Socket socket) {
File target = new File("Target.file");
try (InputStream is = socket.getInputStream(); OutputStream os = new FileOutputStream(target)) {
byte bytes[] = new byte[1024];
int bytesRead = -1;
while ((bytesRead = is.read(bytes)) != -1) {
os.write(bytes, 0, bytesRead);
}
System.out.println("Server MD5 = " + Util.getMD5Checksum(target));
} catch (IOException | NoSuchAlgorithmException ex) {
ex.printStackTrace();
}
}
}
客户
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.security.NoSuchAlgorithmException;
public class Client {
public static void main(String[] args) {
try {
File source = new File(<BYO own file>);
System.out.println("Client MD5 = " + Util.getMD5Checksum(source));
try (Socket socket = new Socket("127.0.0.1", 7104); OutputStream os = socket.getOutputStream(); FileInputStream fis = new FileInputStream(source)) {
byte bytes[] = new byte[1024];
int bytesRead = -1;
while ((bytesRead = fis.read(bytes)) != -1) {
os.write(bytes, 0, bytesRead);
}
} catch (IOException exp) {
}
} catch (IOException | NoSuchAlgorithmException ex) {
ex.printStackTrace();
}
}
}
MD5
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class Util {
protected static byte[] createChecksum(File filename) throws IOException, NoSuchAlgorithmException {
try (InputStream fis = new FileInputStream(filename)) {
byte[] buffer = new byte[1024];
MessageDigest complete = MessageDigest.getInstance("MD5");
int numRead;
do {
numRead = fis.read(buffer);
if (numRead > 0) {
complete.update(buffer, 0, numRead);
}
} while (numRead != -1);
return complete.digest();
}
}
// see this How-to for a faster way to convert
// a byte array to a HEX string
public static String getMD5Checksum(File filename) throws IOException, NoSuchAlgorithmException {
byte[] b = createChecksum(filename);
String result = "";
for (int i = 0; i < b.length; i++) {
result += Integer.toString((b[i] & 0xff) + 0x100, 16).substring(1);
}
return result;
}
}
我强烈建议您花时间阅读 Basic I/O,这些概念您将一直重复使用。
我在 java 中实现了客户端-服务器通信。以下是传输一组文件的代码:
服务器代码:
public class TransferServer {
static List<String> filesListInDir = new ArrayList<String>();
static String zipName = "tmp.tar.gz";
public static void main(String[] args) throws IOException, InterruptedException {
// TODO Auto-generated method stub
ServerSocket s1 = new ServerSocket(7104);
System.out.println("Transfer server started");
while (true) {
Socket sckt = s1.accept();
System.out.println("Request received. Please wait..");
zipData();
transferData(sckt);
System.out.println("Data transferred");
}
}
private static void transferData(Socket ts) throws IOException {
FileInputStream fi=new FileInputStream(zipName);
byte b[] = new byte[8000];
fi.read(b, 0, b.length);
OutputStream os = ts.getOutputStream();
os.write(b, 0, b.length);
fi.close();
}
客户代码:
public class Fetchmyfile {
static String addr_list="/home/pi/addresslist.txt";
static String zipName = "tmp.tar.gz";
public static void main(String[] args) throws InterruptedException, IOException {
// TODO Auto-generated method stub
trigger();
}
private static void trigger() throws InterruptedException, IOException {
// TODO Auto-generated method stub
String[] hostList = readAddressList(addr_list);
//remove tmp.zip
for (int i = 0; i < hostList.length; i++) {
Runtime r = Runtime.getRuntime();
Process p = null;
try {
p = r.exec("rm /home/pi/combined_data/"+hostList[i]+"/"+zipName);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
p.waitFor();
}
//remove complete
for (int i = 0; i < hostList.length; i++) {
String addr = hostList[i];
TransferClient clientInstance = new TransferClient();
clientInstance.fileCopy(addr, "/home/pi/combined_data/"+addr.trim()+"/tmp.tar.gz");
}
System.out.println("All data has been transferred");
}
private static String[] readAddressList(String addr_list) throws IOException {
FileReader fileReader = new FileReader(addr_list);
BufferedReader bufferedReader = new BufferedReader(fileReader);
List<String> lines = new ArrayList<String>();
String line = null;
while ((line = bufferedReader.readLine()) != null)
{
lines.add(line);
}
bufferedReader.close();
System.out.println("Loaded the host list");
return lines.toArray(new String[lines.size()]);
}
}
public class TransferClient {
public boolean fileCopy(String sensor_node_ip, String filename) throws InterruptedException{
//public static void main(String args[]) throws IOException
{
try {
//String filename = "‎�‎�localfile.zip";
byte b[] = new byte[8000];
Socket s = null;
try {
s = new Socket(sensor_node_ip, 7104);
System.out.println("connection done");
} catch (IOException e) {
System.out.println("Couldn't connect to the server");
return false;
}
InputStream iss = s.getInputStream();
FileOutputStream fr = new FileOutputStream(filename);
iss.read(b, 0, b.length);
fr.write(b, 0, b.length);
fr.close();
s.close();
//unZip(filename);
System.out.println("Tar file recieved from " + sensor_node_ip);
return true;
}
catch (IOException e){
return false;
}
}
}
我面临的问题是,对于一个相对较大的文件,客户端创建了一个具有预期名称的声明缓冲区大小的文件。但是该文件不可读并且是存档文件,无法提取。然而,服务器实际上拥有无论如何都是正确的文件。这可能是什么原因。非常感谢任何 suggestions/pointers。
在我看来,问题是您正在写入 8000 个字节,而不管输出的实际大小如何。您甚至没有尝试检查文件的大小,因此如果文件小于 8000 字节,您可能会写入垃圾,或者如果文件超过 8000 字节,则 t运行cating 它。
相反,您应该读取文件直到没有更多的字节要读取,并确保您只写入实际读取的字节数(因为读取可能读取的缓冲区长度少于字节)。
这真的很基础I/O。
因此,以下示例将概念剥离到最基本的框架,仅关注客户端和服务器之间的文件传输。为了对比,我在每一端都加了MD5校验,这样就很容易对比文件结果了。
编程的一个重要方面是,永远不要假设任何事情。总是看看你得到了什么,并在 运行 时间做出决定(例外情况是如果它被记录在案并事先达成一致,但即使那样,我也会仔细检查,因为我不相信任何人)
服务器
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.NoSuchAlgorithmException;
public class Server {
public static void main(String[] args) {
try (ServerSocket server = new ServerSocket(7104)) {
Socket socket = server.accept();
read(socket);
} catch (IOException ex) {
ex.printStackTrace();
}
}
protected static void read(Socket socket) {
File target = new File("Target.file");
try (InputStream is = socket.getInputStream(); OutputStream os = new FileOutputStream(target)) {
byte bytes[] = new byte[1024];
int bytesRead = -1;
while ((bytesRead = is.read(bytes)) != -1) {
os.write(bytes, 0, bytesRead);
}
System.out.println("Server MD5 = " + Util.getMD5Checksum(target));
} catch (IOException | NoSuchAlgorithmException ex) {
ex.printStackTrace();
}
}
}
客户
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.security.NoSuchAlgorithmException;
public class Client {
public static void main(String[] args) {
try {
File source = new File(<BYO own file>);
System.out.println("Client MD5 = " + Util.getMD5Checksum(source));
try (Socket socket = new Socket("127.0.0.1", 7104); OutputStream os = socket.getOutputStream(); FileInputStream fis = new FileInputStream(source)) {
byte bytes[] = new byte[1024];
int bytesRead = -1;
while ((bytesRead = fis.read(bytes)) != -1) {
os.write(bytes, 0, bytesRead);
}
} catch (IOException exp) {
}
} catch (IOException | NoSuchAlgorithmException ex) {
ex.printStackTrace();
}
}
}
MD5
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class Util {
protected static byte[] createChecksum(File filename) throws IOException, NoSuchAlgorithmException {
try (InputStream fis = new FileInputStream(filename)) {
byte[] buffer = new byte[1024];
MessageDigest complete = MessageDigest.getInstance("MD5");
int numRead;
do {
numRead = fis.read(buffer);
if (numRead > 0) {
complete.update(buffer, 0, numRead);
}
} while (numRead != -1);
return complete.digest();
}
}
// see this How-to for a faster way to convert
// a byte array to a HEX string
public static String getMD5Checksum(File filename) throws IOException, NoSuchAlgorithmException {
byte[] b = createChecksum(filename);
String result = "";
for (int i = 0; i < b.length; i++) {
result += Integer.toString((b[i] & 0xff) + 0x100, 16).substring(1);
}
return result;
}
}
我强烈建议您花时间阅读 Basic I/O,这些概念您将一直重复使用。