我的客户端/服务器程序出现问题。服务器应该从客户端获取文件,然后将其转换为xml,然后将xml文件流回客户端。
到目前为止,一切工作都达到了将xml文件流回客户端的程度。我可以成功将文件发送到服务器并将其转换为XML。
服务器不向客户端发送任何内容。客户端停留在从InputStream读取字节的区域。在Client类的第57行。
public class Server {
private ServerSocket serverSocket;
private Socket clientSocket;
private PrintWriter out;
private BufferedReader in;
public static void main(String[] args) {
int port = 8081;
Server srv = new Server(port);
}
public Server(int portNumber) {
try {
serverSocket = new ServerSocket(portNumber);
clientSocket = serverSocket.accept();
out = new PrintWriter(clientSocket.getOutputStream(), true);
//in = new BufferedReader(
//new InputStreamReader(clientSocket.getInputStream()));
byte[] myArray = new byte[22000]; // should be file size
InputStream is = clientSocket.getInputStream();
FileOutputStream fos = new FileOutputStream("file.csv");
BufferedOutputStream bos = new BufferedOutputStream(fos);
int bytesRead;
int current = 0;
bytesRead = is.read(myArray, 0, myArray.length);
current = bytesRead;
do {
bytesRead = is.read(myArray, current, (myArray.length - current) );
if (bytesRead >= 0)
current += bytesRead;
} while (bytesRead > -1);
bos.write(myArray, 0, myArray.length);
bos.flush();
boolean flag = false;
System.out.println("Server: finished receiving file");
XMLWriter xmlWrite = new XMLWriter();
xmlWrite.createXmlDocument("file_copy.csv");
sendXML("server_file.XML");
clientSocket.close();
System.out.println("Server: disconnected with client");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void sendXML(String fileName) {
System.out.println("Sending file");
File file = new File(fileName);
BufferedInputStream bis;
try {
FileInputStream fis = new FileInputStream(file);
bis = new BufferedInputStream(fis);
DataInputStream dataIn = new DataInputStream( bis );
OutputStream outStream = clientSocket.getOutputStream();
int length;
try {
length = dataIn.readInt();
System.out.println("S: " + dataIn.readInt());
byte[] data = new byte[ length ];
dataIn.readFully(data, 0, data.length);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
public class Client {
private Socket mainSocket;
public static void main(String[] args) {
int port = 8081;
Client cli = new Client(port);
}
public Client(int portNumber) {
try {
mainSocket = new Socket("localhost", portNumber);
// send file to server
File file = new File("Passengers.csv");
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
OutputStream outStream = mainSocket.getOutputStream();
byte[] myBytes = new byte[(int) file.length()];
bis.read(myBytes, 0, myBytes.length);
outStream.write(myBytes, 0, myBytes.length);
outStream.flush();
System.out.println("Client: Done sending file");
byte[] fileData = new byte[30000];
InputStream is = mainSocket.getInputStream();
FileOutputStream fos = new FileOutputStream("client_file.XML");
BufferedOutputStream bos = new BufferedOutputStream(fos);
DataOutputStream dataOut = new DataOutputStream( bos );
dataOut.writeInt( fileData.length );
dataOut.write( fileData );
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
答案 0 :(得分:0)
此循环将一直运行,直到流关闭,直到客户端完成发送数据。
do {
bytesRead = is.read(myArray, current, (myArray.length - current) );
if (bytesRead >= 0)
current += bytesRead;
} while (bytesRead > -1);
这是因为InputStream.read将阻塞,直到至少有一个字节的数据可用或流已关闭,导致返回-1。由于客户端已完成发送数据但流仍处于打开状态,因此将永久阻止。
解决方案是首先使用类似DataOutputStream / DataInputStream之类的内容发送前4个字节中的文件长度,然后让客户端发送完全相同的字节数,然后服务器准确读取继续前进的许多字节。
客户端:
// Connect to the server and read in file data
byte[] fileData = ...;
DataOutputStream dataOut = new DataOutputStream( outStream );
dataOut.writeInt( fileData.length );
dataOut.write( fileData );
// Get reply from server
服务器:
// Create ServerSocket and get Client connection
DataInputStream dataIn = new DataInputStream( is );
int length = dataIn.readInt();
byte[] data = new byte[ length ];
dataIn.readFully( data );
// Continue to process client connection
这种网络通信背后的一般思想是每个数据块或数据包在发送之前都以其长度为前缀。这意味着数据的接收者可以读取该数字并确切地知道剩余多少字节以形成完整的块或数据包。对于连接的两端,通信都是这样的。唯一的区别在于您处理数据的方式。
public byte[] readPacket( DataInputStream dataIn ) throws IOException {
int length = dataIn.readInt();
byte[] packet = new byte[ length ];
dataIn.readFully( packet );
return packet;
}
public void writePacket( DataOutputStream dataOut, byte[] packet ) throws IOException {
dataOut.writeInt( packet.length );
dataOut.write( packet );
}
只有您可以从某种循环中调用这些循环,最好是在后台线程上,但这并不是您想要做的事情所必需的。对于您的情况,您希望将客户端的文件读入byte [],然后使用writePacket将其发送到服务器。在服务器端,您将使用readPacket从客户端读取文件。将数据发送回客户端但切换角色时会发生同样的事情。