Java 套接字接收字节数组,其中每个字节为 0
Java socket receives byte array where each byte is 0
我正在制作一个程序,它获取一个文件,并通过套接字将其发送到客户端。客户端收到它并将其保存到文件中。这就是它应该做的。
但是不知何故,客户端接收到的字节数组只包含 0 个字节,所以我的输出文件是空的。这是代码:
服务器:
try {
serverSocket=new ServerSocket(7575);
serverSocket.setSoTimeout(1000000);
System.out.println("serverSocket created.");
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
System.out.println("Error in creating new serverSocket on port 7575");
}
for(int i=0;i<array.length;i++)
System.out.println(array[i]);
Socket socket=null;
try {
System.out.println("Waiting for client...");
socket=serverSocket.accept();
System.out.println("Client accepted.");
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
PrintWriter outWriter=null;
DataOutputStream outputStream=null;
OutputStream os=null;
BufferedOutputStream bos=null;
try {
os=socket.getOutputStream();
outputStream=new DataOutputStream(os);
outWriter=new PrintWriter(socket.getOutputStream());
bos=new BufferedOutputStream(socket.getOutputStream());
System.out.println("Server streams created.");
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("sending name "+name);
outWriter.println(name);
outWriter.flush();
outWriter.println(array.length);
outWriter.println("array.length"+array.length);
outWriter.flush();
try {
os.write(array);
os.flush();
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
System.out.println("couldnt send array of bytes");
}
try {
os.close();
outputStream.close();
socket.close();
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
客户:
public class Client implements Runnable {
private Socket socket;
private String folderPath;
public Client(String p)
{
folderPath=p;
}
@Override
public void run()
{
try {
System.out.println("Client connecting to localhost on 7575 port...");
socket=new Socket("localhost", 7575);
} catch (IOException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
BufferedReader reader=null;
BufferedInputStream bis=null;
InputStream input=null;
DataInputStream in=null;
try {
System.out.println("creating streams");
reader=new BufferedReader(new InputStreamReader(socket.getInputStream()));
input=socket.getInputStream();
in=new DataInputStream(input);
bis=new BufferedInputStream(socket.getInputStream());
System.out.println("streams created!");
} catch (IOException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
String name="";
int size=0;
String s="32";
try {
name=reader.readLine();
s=reader.readLine();
} catch (IOException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
if(s!=null)
size=Integer.parseInt(s);
System.out.println("name: "+name);
System.out.println("size: "+size);
byte [] arr=new byte[size];
try {
input.read(arr);
} catch (IOException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
System.out.println("couldnt read the byte array");
}
for(int i=0;i<arr.length;i++)
System.out.println(arr[i]);
FileOutputStream fos=null;
try {
fos=new FileOutputStream(folderPath+"/"+name);
} catch (FileNotFoundException ex) {
System.out.println("Could write the file");
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
try {
fos.write(arr);
fos.flush();
} catch (IOException ex) {
System.out.println("Could write the file2");
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
try {
fos.close();
} catch (IOException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
try {
in.close();
input.close();
reader.close();
socket.close();
} catch (IOException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
您可以使用 DataOutputStream 通过 writeUTF() 函数直接在输出流上写入一些字符串(消息)。然后你可以通过使用 readUTF() 方法使用 DataInputStream class 的对象接收你的消息。
您可以使用以下方式发送数据:-
String message="something";
DataOutputStream out=new DataOutputStream(socket.getOutputStream());
out.writeUTF(message);
并且您可以使用以下方式接收数据或消息:-
DataInputStream in=new DataInputStream(socket.getInputStream());
String message=in.readUTF();
我基本上使用这些方法多次从输入流读取数据并将数据写入输出流并且每次都有效,所以你也应该检查这种方式。
在同一个流中混合使用二进制和文本模式是很棘手的。建议您不要这样做。使用 DataInputStream
(名称、计数和文件内容)是一种可能的解决方案。 (这就是我会尝试的)。另一种方法是将文件内容编码为文本(例如使用 Base64 编码)。
当前“混合流”的问题:代码在客户端。当您从 BufferedReader 读取名称和大小时,将导致 reader 从中读取和缓冲最多 4096 个字节套接字。问题是这些字节中的一些是文件内容。因此当您尝试从底层 InputStream
此处读取内容时:
input.read(arr);
您可能会发现没有什么可读的了。结果:文件为空或损坏。
还有一个问题。您的代码假定 input.read(arr)
语句将读取流的其余部分,或者直到它填满字节数组。这个假设是不正确的。当您从套接字流中读取时,read
只负责 return 当前可用的字节(在客户端网络堆栈中)。
再一次,结果很可能是损坏的文件。 (在本例中被截断。)
读取的代码应如下所示:
int count = 0;
while (count < size) {
int bytesRead = is.read(bytes, count, bytes.length - count);
if (bytesRead == -1) {
throw EOFException("didn't get a complete file");
}
count += bytesRead;
}
最后:
在两端将文件内容读入字节数组会浪费内存,而且对于一个非常大的文件来说会有问题。
你真的应该使用 "try with resources" 来确保所有流都正确关闭。手工操作很麻烦,而且有资源泄漏的风险。
I am making a program which takes a file, and sends it via socket to client. Client receives it and saves it to a file. That is what it is supposed to do.
如果你不需要检查正在传递的内容,那么直接 InputStream
和 OutputStream
是我认为的方式。该代码直接且快速,因为它避免了检查内容以进行编码等的更高级别流类型强加的任何开销。这也减少了破坏信息的机会。
我同意 Stephen C 的回答,除了
Reading the file content into byte arrays at both ends wastes memory, and is going to be problematic for a really large file.
对于将一个文件简单地移动到另一个系统而无需查看值的特定要求,如果您知道如何处理内容,这不是问题。基本流程是
client: InputStream in = getFileInputStream();
OutputStream out = socket.getOutputStream();
byte[] bytes = new byte[BUFFER_SIZE]; // could be anything
int bytesRead;
while((bytesRead = in.read(bytes)) != -1){
out.write(bytes,0,bytesRead);
}
in.close();
out.close();
server: InputStream in = socket.getInputStream();
OutputStream out = getFileOutputStream();
// the rest is the exact same thing as the client
这将处理任意大小的文件,仅受服务器磁盘大小的限制。
这里是我举的一个例子。无可否认,它很老套(例如 FILE_COUNTER
和 STOP_KEY
的使用),但我只是想展示让用户输入文件然后在客户端和服务器之间发送文件的各个方面。
public class FileSenderDemo {
private static final int PORT = 7999;
private static final String STOP_KEY = "server.stop";
private static final int[] FILE_COUNTER = {0};
public static void main(String[] args) {
FileSenderDemo sender = new FileSenderDemo();
Thread client = new Thread(sender.getClient());
Thread server = new Thread(sender.getServer());
server.start();
client.start();
try {
server.join();
client.join();
} catch (InterruptedException e) {
FILE_COUNTER[0] = 999 ;
System.setProperty(STOP_KEY,"stop");
throw new IllegalStateException(e);
}
}
public void send(File f, OutputStream out) throws IOException{
try(BufferedInputStream in = new BufferedInputStream(new FileInputStream(f),1<<11)){
byte[] bytes = new byte[1<<11];
int bytesRead;
while((bytesRead = in.read(bytes)) != -1){
out.write(bytes,0,bytesRead);
}
}
}
public Runnable getClient() {
return () -> {
while(FILE_COUNTER[0] < 3 && System.getProperty(STOP_KEY) == null) {
Socket socket;
try {
socket = new Socket("localhost", PORT);
} catch (IOException e) {
throw new IllegalStateException("CLIENT: Can't create the client: " + e.getMessage(), e);
}
File f = getFile();
try (BufferedOutputStream out = new BufferedOutputStream(socket.getOutputStream())) {
send(f, out);
} catch (IOException e) {
System.out.println("CLIENT: Failed to send file " + f.getAbsolutePath()+" due to: " + e.getMessage());
e.printStackTrace(System.err);
} finally {
FILE_COUNTER[0]++;
}
}
System.setProperty(STOP_KEY,"stop");
};
}
public File getFile(){
Scanner scanner = new Scanner(System.in);
System.out.println("CLIENT: Enter a file Name: ");
return new File(scanner.next());
}
public Runnable getServer(){
return () -> {
OutputStream out = null;
try{
ServerSocket server = new ServerSocket(PORT);
server.setSoTimeout(20000);
while(System.getProperty(STOP_KEY) == null){
Socket socket = null;
try {
socket = server.accept();
}catch (SocketTimeoutException e){
System.out.println("SERVER: Waited 20 seconds for an accept. Now checking if we need to stop.");
continue;
}
String fileName = "receivedFile_"+System.currentTimeMillis()+".content";
File outFile = new File(fileName);
out = new BufferedOutputStream(new FileOutputStream(outFile));
InputStream in = socket.getInputStream();
int bytesRead;
byte[] bytes = new byte[1<<12];
while((bytesRead = in.read(bytes)) != -1){
out.write(bytes,0,bytesRead);
}
out.close();
socket.close();
System.out.println("SERVER: Just created a new file: " + outFile.getAbsolutePath());
}
System.out.println("SERVER: " + STOP_KEY + " was not null, so quit.");
}catch (IOException e){
throw new IllegalStateException("SERVER: failed to receive the file content",e);
}finally {
if(out != null){
try{out.close();}catch (IOException e){}
}
}
};
}
}
我正在制作一个程序,它获取一个文件,并通过套接字将其发送到客户端。客户端收到它并将其保存到文件中。这就是它应该做的。
但是不知何故,客户端接收到的字节数组只包含 0 个字节,所以我的输出文件是空的。这是代码:
服务器:
try {
serverSocket=new ServerSocket(7575);
serverSocket.setSoTimeout(1000000);
System.out.println("serverSocket created.");
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
System.out.println("Error in creating new serverSocket on port 7575");
}
for(int i=0;i<array.length;i++)
System.out.println(array[i]);
Socket socket=null;
try {
System.out.println("Waiting for client...");
socket=serverSocket.accept();
System.out.println("Client accepted.");
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
PrintWriter outWriter=null;
DataOutputStream outputStream=null;
OutputStream os=null;
BufferedOutputStream bos=null;
try {
os=socket.getOutputStream();
outputStream=new DataOutputStream(os);
outWriter=new PrintWriter(socket.getOutputStream());
bos=new BufferedOutputStream(socket.getOutputStream());
System.out.println("Server streams created.");
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("sending name "+name);
outWriter.println(name);
outWriter.flush();
outWriter.println(array.length);
outWriter.println("array.length"+array.length);
outWriter.flush();
try {
os.write(array);
os.flush();
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
System.out.println("couldnt send array of bytes");
}
try {
os.close();
outputStream.close();
socket.close();
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
客户:
public class Client implements Runnable {
private Socket socket;
private String folderPath;
public Client(String p)
{
folderPath=p;
}
@Override
public void run()
{
try {
System.out.println("Client connecting to localhost on 7575 port...");
socket=new Socket("localhost", 7575);
} catch (IOException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
BufferedReader reader=null;
BufferedInputStream bis=null;
InputStream input=null;
DataInputStream in=null;
try {
System.out.println("creating streams");
reader=new BufferedReader(new InputStreamReader(socket.getInputStream()));
input=socket.getInputStream();
in=new DataInputStream(input);
bis=new BufferedInputStream(socket.getInputStream());
System.out.println("streams created!");
} catch (IOException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
String name="";
int size=0;
String s="32";
try {
name=reader.readLine();
s=reader.readLine();
} catch (IOException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
if(s!=null)
size=Integer.parseInt(s);
System.out.println("name: "+name);
System.out.println("size: "+size);
byte [] arr=new byte[size];
try {
input.read(arr);
} catch (IOException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
System.out.println("couldnt read the byte array");
}
for(int i=0;i<arr.length;i++)
System.out.println(arr[i]);
FileOutputStream fos=null;
try {
fos=new FileOutputStream(folderPath+"/"+name);
} catch (FileNotFoundException ex) {
System.out.println("Could write the file");
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
try {
fos.write(arr);
fos.flush();
} catch (IOException ex) {
System.out.println("Could write the file2");
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
try {
fos.close();
} catch (IOException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
try {
in.close();
input.close();
reader.close();
socket.close();
} catch (IOException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
您可以使用 DataOutputStream 通过 writeUTF() 函数直接在输出流上写入一些字符串(消息)。然后你可以通过使用 readUTF() 方法使用 DataInputStream class 的对象接收你的消息。
您可以使用以下方式发送数据:-
String message="something";
DataOutputStream out=new DataOutputStream(socket.getOutputStream());
out.writeUTF(message);
并且您可以使用以下方式接收数据或消息:-
DataInputStream in=new DataInputStream(socket.getInputStream());
String message=in.readUTF();
我基本上使用这些方法多次从输入流读取数据并将数据写入输出流并且每次都有效,所以你也应该检查这种方式。
在同一个流中混合使用二进制和文本模式是很棘手的。建议您不要这样做。使用 DataInputStream
(名称、计数和文件内容)是一种可能的解决方案。 (这就是我会尝试的)。另一种方法是将文件内容编码为文本(例如使用 Base64 编码)。
当前“混合流”的问题:代码在客户端。当您从 BufferedReader 读取名称和大小时,将导致 reader 从中读取和缓冲最多 4096 个字节套接字。问题是这些字节中的一些是文件内容。因此当您尝试从底层 InputStream
此处读取内容时:
input.read(arr);
您可能会发现没有什么可读的了。结果:文件为空或损坏。
还有一个问题。您的代码假定 input.read(arr)
语句将读取流的其余部分,或者直到它填满字节数组。这个假设是不正确的。当您从套接字流中读取时,read
只负责 return 当前可用的字节(在客户端网络堆栈中)。
再一次,结果很可能是损坏的文件。 (在本例中被截断。)
读取的代码应如下所示:
int count = 0;
while (count < size) {
int bytesRead = is.read(bytes, count, bytes.length - count);
if (bytesRead == -1) {
throw EOFException("didn't get a complete file");
}
count += bytesRead;
}
最后:
在两端将文件内容读入字节数组会浪费内存,而且对于一个非常大的文件来说会有问题。
你真的应该使用 "try with resources" 来确保所有流都正确关闭。手工操作很麻烦,而且有资源泄漏的风险。
I am making a program which takes a file, and sends it via socket to client. Client receives it and saves it to a file. That is what it is supposed to do.
如果你不需要检查正在传递的内容,那么直接 InputStream
和 OutputStream
是我认为的方式。该代码直接且快速,因为它避免了检查内容以进行编码等的更高级别流类型强加的任何开销。这也减少了破坏信息的机会。
我同意 Stephen C 的回答,除了
Reading the file content into byte arrays at both ends wastes memory, and is going to be problematic for a really large file.
对于将一个文件简单地移动到另一个系统而无需查看值的特定要求,如果您知道如何处理内容,这不是问题。基本流程是
client: InputStream in = getFileInputStream();
OutputStream out = socket.getOutputStream();
byte[] bytes = new byte[BUFFER_SIZE]; // could be anything
int bytesRead;
while((bytesRead = in.read(bytes)) != -1){
out.write(bytes,0,bytesRead);
}
in.close();
out.close();
server: InputStream in = socket.getInputStream();
OutputStream out = getFileOutputStream();
// the rest is the exact same thing as the client
这将处理任意大小的文件,仅受服务器磁盘大小的限制。
这里是我举的一个例子。无可否认,它很老套(例如 FILE_COUNTER
和 STOP_KEY
的使用),但我只是想展示让用户输入文件然后在客户端和服务器之间发送文件的各个方面。
public class FileSenderDemo {
private static final int PORT = 7999;
private static final String STOP_KEY = "server.stop";
private static final int[] FILE_COUNTER = {0};
public static void main(String[] args) {
FileSenderDemo sender = new FileSenderDemo();
Thread client = new Thread(sender.getClient());
Thread server = new Thread(sender.getServer());
server.start();
client.start();
try {
server.join();
client.join();
} catch (InterruptedException e) {
FILE_COUNTER[0] = 999 ;
System.setProperty(STOP_KEY,"stop");
throw new IllegalStateException(e);
}
}
public void send(File f, OutputStream out) throws IOException{
try(BufferedInputStream in = new BufferedInputStream(new FileInputStream(f),1<<11)){
byte[] bytes = new byte[1<<11];
int bytesRead;
while((bytesRead = in.read(bytes)) != -1){
out.write(bytes,0,bytesRead);
}
}
}
public Runnable getClient() {
return () -> {
while(FILE_COUNTER[0] < 3 && System.getProperty(STOP_KEY) == null) {
Socket socket;
try {
socket = new Socket("localhost", PORT);
} catch (IOException e) {
throw new IllegalStateException("CLIENT: Can't create the client: " + e.getMessage(), e);
}
File f = getFile();
try (BufferedOutputStream out = new BufferedOutputStream(socket.getOutputStream())) {
send(f, out);
} catch (IOException e) {
System.out.println("CLIENT: Failed to send file " + f.getAbsolutePath()+" due to: " + e.getMessage());
e.printStackTrace(System.err);
} finally {
FILE_COUNTER[0]++;
}
}
System.setProperty(STOP_KEY,"stop");
};
}
public File getFile(){
Scanner scanner = new Scanner(System.in);
System.out.println("CLIENT: Enter a file Name: ");
return new File(scanner.next());
}
public Runnable getServer(){
return () -> {
OutputStream out = null;
try{
ServerSocket server = new ServerSocket(PORT);
server.setSoTimeout(20000);
while(System.getProperty(STOP_KEY) == null){
Socket socket = null;
try {
socket = server.accept();
}catch (SocketTimeoutException e){
System.out.println("SERVER: Waited 20 seconds for an accept. Now checking if we need to stop.");
continue;
}
String fileName = "receivedFile_"+System.currentTimeMillis()+".content";
File outFile = new File(fileName);
out = new BufferedOutputStream(new FileOutputStream(outFile));
InputStream in = socket.getInputStream();
int bytesRead;
byte[] bytes = new byte[1<<12];
while((bytesRead = in.read(bytes)) != -1){
out.write(bytes,0,bytesRead);
}
out.close();
socket.close();
System.out.println("SERVER: Just created a new file: " + outFile.getAbsolutePath());
}
System.out.println("SERVER: " + STOP_KEY + " was not null, so quit.");
}catch (IOException e){
throw new IllegalStateException("SERVER: failed to receive the file content",e);
}finally {
if(out != null){
try{out.close();}catch (IOException e){}
}
}
};
}
}