Я озадачен своим последним затруднительным положением с программированием Java Socket в течение трех дней подряд. Я использую NIO ByteBuffer и Channel для передачи байтов от клиента к серверу. Я тестирую свой код, заставляя клиента отправлять 2 файла последовательно - первые файлы всегда приходят, а второй всегда теряется, так что где. Я сделал tcpdump и увидел трафик по определенному адресу и порту, но не смог расшифровать файл pcap (понять, как читать весь синтаксис в файлах pcap).
каким-то образом socketchannel.read(bytebuffer) не читает ни одного байта для второго файла. первый файл будет в порядке. Он проходит через команду чтения, получает файл и отвечает. второй файл будет в порядке для команды чтения и ответа. он не получает никакого файла для socketchannel.read получает -1 --- ЭТО проблема.
Пожалуйста, помогите. Это действительно сумасшедшая проблема.
public class ServersThread implements Runnable
{
private Socket socket;
public ServersThread(Socket socket)
{
this();
this.socket = socket;
}
public void run()
{
try
{
InputStreamReader isr = new InputStreamReader(socket.getInputStream());
BufferedReader br = new BufferedReader(isr);
PrintStream ps = new PrintStream(socket.getOutputStream(), true);
String orderFromClient = br.readLine(); // first read command from client
String filename = orderFromClient.split(":")[0]
long fileSize = Long.parseLong(orderFromClient.split(":")[1]);
File destFile = new File(filename);
destFile.setReadable(true);
destFile.setWritable(true);
FileOutputStream inFile = new FileOutputStream(destFile);
FileChannel inChannel = inFile.getChannel();
SocketChannel sc = socket.getChannel();
ByteBuffer dst = ByteBuffer.allocate(65536);
dst.clear();
// this receiving binary file part that is questionable.
// it always run okay for the first file
// the second file is created but always has size 0
// The second file will enter into while-loop start and end but it won't enter sc.read(dst)
logger.debug(AUDIT,"while-loop start");
start = System.currentTimeMillis();
while (sc.read(dst) != -1)
{
dst.flip();
logger.debug(AUDIT,"dst flip and ask remaining: {} at position {}",dst.hasRemaining(),dst.position());
while (dst.hasRemaining())
{
temp = inChannel.write(dst);
curnset += temp;
logger.debug(AUDIT, "c {} | t {} | size {}", curnset, temp, fileSize);
}
dst.clear();
}
end = System.currentTimeMillis();
logger.debug(AUDIT,"while-loop end");
if (curnset == fileSize)
ps.println("SUCCESS");
else
ps.println("FAIL");
}
catch(Exception e)
{
e.printStackTrace(System.err);
logger.error("Exception ",e);
}
finally
{
try
{
inChannel.close();
inFile.close();
sc.close();
ps.close();
isr.close();
br.close();
socket.close();
}
catch(IOException e)
{ }
}
}
}
Этот ServerThread реализует runnable, который вызывается другим классом ServerMain, который передает только serversocket.accept() в ServersThread (сокет Socket)
Вот класс ServerMain:
public class ServerMain
{
public static void main(String[] args)
{
ServerSocketChannel listener = null;
ServerSocket serverMain = null;
try
{
listener = ServerSocketChannel.open();
serverMain = listener.socket();
serverMain.setReuseAddress(true);
serverMain.bind(new InetSocketAddress("192.168.1.12",9999));
while (true)
{
new ServersThread(serverMain.accept()).start();
}
}
catch (Exception e)
{
logger.error("Exception ", e);
e.printStackTrace(System.err);
}
finally
{
try
{
listener.close();
}
catch (IOException e)
{
logger.error("IOException ", e);
e.printStackTrace(System.err);
}
}
}
}
Вот клиентский класс
public class ClientCallable
{
public static void process(String serverAddr,int serverPort,File file,String command)
{
SocketChannel sc = null;
PrintStream ps = null;
BufferedReader br = null;
int timeout = 10 * 1000;
try
{
sc = SocketChannel.open();
sc.configureBlocking(true);
if (!sc.connect(new InetSocketAddress(serverAddr, serverPort)))
return ClientMain.ERROR_UNABLE_TO_CONNECT;
sc.socket().setSoTimeout(timeout);
}
catch (Exception e)
{
logger.error("Exception ", e);
e.printStackTrace(System.err);
return;
}
long maxCount = 8192 * 1024;
long curnset = 0l;
long temp = 0l;
long filesize = 0l;
long startTime = 0l;
long endTime = 0l;
String serverResp = null;
FileInputStream fis = null;
FileChannel fc = null;
try
{
ps = new PrintStream(sc.socket().getOutputStream());
br = new BufferedReader(new InputStreamReader(sc.socket()
.getInputStream()));
fis = new FileInputStream(file);
fc = fis.getChannel();
filesize = fc.size();
// send command to server
ps.print(command);
// send binary file
ByteBuffer dst = ByteBuffer.allocate(65536);
dst.clear();
startTime = System.currentTimeMillis();
while (fc.read(dst) != -1)
{
dst.flip();
while (dst.hasRemaining())
{
temp = sc.write(dst);
curnset += temp;
logger.debug(AUDIT, "c {} | t {} | size {}", curnset, temp,
filesize);
}
dst.clear();
}
sc.shutdownOutput();
endTime = System.currentTimeMillis();
// read server respond
serverResp = br.readLine();
logger.debug(AUDIT,"server responds {}",serverResp);
}
catch (Exception e)
{
logger.error("Exception ", e);
e.printStackTrace(System.err);
}
try
{
if (fis != null)
fis.close();
if (fc != null)
fc.close();
if (ps != null)
ps.close();
if (br != null)
br.close();
if (sc != null)
sc.close();
}
catch (Exception e)
{
logger.error("Exception ", e);
e.printStackTrace(System.err);
}
}
public static void main(String[] args)
{
String serverAddr = "192.168.1.12"
int serverPort = 9999;
File file1 = new File("file1.fpt");
File file2 = new File("file2.fpt");
String command = "somecommandtoserver";
process(serverAddr,serverPort,file1,command);
process(serverAddr,serverPort,file2,command);
}
}