Java reading message from socket is not sending full message - java

hello I am using this method to read a message:
public String readMessage() {
int read = -1;
byte[] buffer = new byte[5*1024];
byte[] redData;
try {
while ((read = this.session.getInputStream().read(buffer)) > -1) {
redData = new byte[read];
System.arraycopy(buffer, 0, redData, 0, read);
return new String(redData,"UTF-8");
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
And when I write something like "hello how are you today?"
Response (Exact format, including these new lines):
[/127.0.0.1:54930]:
[/127.0.0.1:54930]: are
[/127.0.0.1:54930]: you
[/127.0.0.1:54930]: today?
Thats how I read chat messages, first I check which packet was requested, if the packet type was 0, then I get instance of packethandler, and pass the client object to the Chat handling packet which will read the message here, like this:
public void startClientService() throws IOException {
while(true) {
int packetType = this.in.read();
packets.getPacket(packetType);
}
}
public void getPacket(int packetType) {
switch (packetType) {
case 0:
chat.processPacket(this.client);
break;
}
}
And the chat packet:
#Override
public void processPacket(Session c) {
String clientMessage = c.readMessage();
System.out.println("[" + c.getStream().getRemoteSocketAddress() + "]: " + clientMessage.toString());
}
And there the print message happens.
Why does it print parts of the messages, in new lines? not even the full message.
This is my client:
public static void main(String[] args) throws UnknownHostException, IOException {
Socket socket = new Socket("127.0.0.1", 43594);
Scanner r = new Scanner(System.in);
PrintWriter out = new PrintWriter(socket.getOutputStream());
String input;
while(true) {
input = r.next();
if (input != null) {
sendMessage(input, out);
}
}
}
public static void sendMessage(String message, PrintWriter out) {
out.write(0);
out.flush();
out.write(message + "\n");
out.flush();
}
Thanks.
Session:
public class Session extends Thread implements Runnable {
private Socket session;
private Client client;
private PrintWriter out;
private BufferedReader in;
private PacketHandler packets;
public Session(Socket session) {
this.session = session;
this.client = new Client(this);
try {
this.setStream();
} catch (IOException e) {
e.printStackTrace();
}
this.packets = new PacketHandler(this);
System.out.println("[New session created]: " + session.getRemoteSocketAddress());
}
public void run() {
try {
this.startClientService();
} catch (IOException e) {
e.printStackTrace();
}
}
public Socket getStream() {
return this.session;
}
public void setStream() throws IOException {
this.out = new PrintWriter(this.session.getOutputStream());
this.in = new BufferedReader(new InputStreamReader(this.session.getInputStream()));
}
public Client getClient() {
return this.client;
}
public String readMessage() {
int read = -1;
byte[] buffer = new byte[5*1024];
byte[] redData;
try {
while ((read = this.session.getInputStream().read(buffer)) > -1) {
redData = new byte[read];
System.arraycopy(buffer, 0, redData, 0, read);
return new String(redData,"UTF-8");
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public void startClientService() throws IOException {
while(true) {
int packetType = this.in.read();
packets.getPacket(packetType);
}
}
public void destruct() throws IOException {
this.session.close();
System.out.println("Session killed");
}
}

looks like you are returning as soon as you get some data from stream.
while ((read = this.session.getInputStream().read(buffer)) > -1) {
redData = new byte[read];
System.arraycopy(buffer, 0, redData, 0, read);
return new String(redData,"UTF-8");
}
Read the data completely and make a string object out of it and return it
BufferedReader br = new BufferedReader(new InputStreamReader(this.session.getInputStream()));
String msg = br.readLine();
br.close();
return msg;
try this way. This will give you entire data to a buffer and can return as line of string.No need of loop

The the amount of data returned from one call to read has no relationship to how the
data divided when sent. One send can result in any number of reads, and multiple sends
may be combined into one read.

Related

IndexOutOfBoundsException when transferring a file through sockets. urgent data transfer control

How can I resolve this error when transferring a file through sockets:
java.lang.IndexOutOfBoundsException
at java.io.FileOutputStream.writeBytes(Native Method)
at java.io.FileOutputStream.write(FileOutputStream.java:326)
at Client.getFile(Client.java:18)
I implemented a client server application for transferring a file using the TCP protocol. Server is parallel. It is also necessary to implement transmission control using urgent data. I did not find a solution on Java on the Internet.
Class Server:
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
private ServerSocket serverSocket;
public void start(int port) throws IOException {
serverSocket = new ServerSocket(port);
while (true)
new ClientHandler(serverSocket.accept()).start();
}
public void stop() throws IOException{
serverSocket.close();
}
private static class ClientHandler extends Thread {
private Socket clientSocket;
private DataOutputStream out;
private FileInputStream in;
public ClientHandler(Socket socket) {
this.clientSocket = socket;
}
public void run() {
try {
out = new DataOutputStream(clientSocket.getOutputStream());
out.writeInt((int) Prop.FILE_1.length());
} catch (IOException e) {
e.printStackTrace();
}
try {
in = new FileInputStream(Prop.FILE_1);
} catch (IOException e) {
e.printStackTrace();
}
while (true) {
byte buf[] = new byte[512];
int len = 0;
try {
len = in.read(buf);
} catch (IOException e) {
e.printStackTrace();
}
if(len == -1) {
break;
}
try {
out.write(buf, 0, len);
} catch (IOException e) {
e.printStackTrace();
}
try {
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
/*try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}*/
}
}
}
Class Client:
import java.io.*;
import java.net.Socket;
public class Client {
private Socket clientSocket;
private FileOutputStream out;
private DataInputStream in;
public String getFile() throws IOException {
int i = 0;
int len;
byte buf[] = new byte[512];
Integer fileSize;
fileSize = in.readInt();
while (i < fileSize) {
len = in.read(buf);
if (len == -1) {
break;
}
i += len;
out.write(buf, 0, len);
out.flush();
}
out.close();
return in.readUTF();
}
public void startConnection(String ip, int port) throws IOException {
clientSocket = new Socket(ip, port);
out = new FileOutputStream(Prop.FILE_2);
in = new DataInputStream(clientSocket.getInputStream());
}
public void stopConnection() throws IOException {
in.close();
out.close();
clientSocket.close();
}
}
Test
public class TestCS {
#Test
// (threadPoolSize = 3, invocationCount = 6, timeOut = 1000)
public void givenClient1__whenServerResponds__thenCorrect() throws IOException {
SoftAssert softAssert = new SoftAssert();
Client client1 = new Client();
client1.startConnection("127.0.0.1", 555);
String file = client1.getFile();
System.out.println(file);
client1.stopConnection();
softAssert.assertEquals(file, "First file!!!");
softAssert.assertAll();
}
}
You are reading InputStream wrongly. The logic you are trying to put there is already available in DataInputStream.read(..) method. All you have to do is to check how many bytes it read from the stream.
Change your while loop in Client like this
while (i < fileSize) {
// javadoc for below : - https://docs.oracle.com/javase/7/docs/api/java/io/DataInputStream.html#read(byte[])
len = in.read(buf);
if(len<0) {
break;
}
i += len;
out.write(buf, 0, len);
out.flush();
}
Note : I have not checked your logic. All I checked and corrected is the Exception you got.
Also, typically we do not read fileSize upfront. You generally keep on reading stream till you get EOF (-1) from the stream. Please check that logic as well.

Send files with java socket

i am sending files from two java applications here the source code of the server and the client
public class FileClient {
private Socket s;
public FileClient(String host, int port, String file) {
try {
s = new Socket(host, port);
sendFile(file);
} catch (Exception e) {
e.printStackTrace();
}
}
public void sendFile(String file) throws IOException {
DataOutputStream dos = new DataOutputStream(s.getOutputStream());
FileInputStream fis = new FileInputStream(file);
byte[] buffer = new byte[4096];
while ((fis.read(buffer) > 0)) {
dos.write(buffer);
}
fis.close();
dos.close();
}
public static void main(String[] args) {
FileClient fc = new FileClient("192.168.0.167", 1988, "C:/Users/mhattabi/Desktop/fileData.txt");
}
}
and here the source code of the server
public class FileServer extends Thread {
private ServerSocket ss;
public FileServer(int port) {
try {
ss = new ServerSocket(port);
} catch (IOException e) {
e.printStackTrace();
}
}
public void run() {
while (true) {
try {
Socket clientSock = ss.accept();
saveFile(clientSock);
// ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void saveFile(Socket clientSock) throws IOException {
DataInputStream dis = new DataInputStream(clientSock.getInputStream());
FileOutputStream fos = new FileOutputStream("fileData.txt");
byte[] buffer = new byte[4096];
int filesize = 15123; // Send file size in separate msg
int read = 0;
int totalRead = 0;
int remaining = filesize;
while((read = dis.read(buffer)) > 0) {
totalRead += read;
System.out.println("read " + totalRead + " bytes.");
fos.write(buffer, 0, read);
}
fos.close();
dis.close();
}
public static void main(String[] args) {
FileServer fs = new FileServer(1988);
fs.start();
}
}
the problem that in the server i received the file but there is extra character in it look like this.Any help will be appreciated thanks
Usual problem.
while ((fis.read(buffer) > 0)) {
dos.write(buffer);
}
You're ignoring the count returned by the read, and assuming that it filled the buffer. It should be:
while ((count = fis.read(buffer) > 0)) {
dos.write(buffer, 0, count);
}
Curiously enough you have this right in the server. NB You don't need a DataOutputStream here.
byte[] buffer = new byte[4096];
I think the" extra character" come from this place;every time you write 4096 byte
,at last time it happened less than 4096 byte.and then you get extra character

SocketException recv failed, but why?

I've got a Client and a Server. The client simply sends 1 line of input to the server and then prints the response.
I'm getting a
SocketException (Software caused connection abort: recv failed)
[...]
at java.io.InputStreamReader.read(InputStreamReader.java:168)
at hw3.Client.readLine(Client.java:37)
at hw3.Client.main(Client.java:28)
The debugger tells me that the socket is not closed at the time of the read, what else can cause this exception?
I think I'm running into issues because of the threading, does anything stick out as "doing it wrong"?
public class Client
{
public static final int PORT = ReversingEchoServerDispatcher.PORT;
private static final String host = "localhost";
private static Socket sock;
public static void main(String[] args)
throws IOException
{
try(Socket sock = new Socket(host, PORT);
InputStreamReader clin = new InputStreamReader(sock.getInputStream());
OutputStream clout = sock.getOutputStream();
Scanner sc = new Scanner(System.in))
{
Client.sock = sock;
byte[] cl = sc.nextLine().getBytes("UTF-8");
clout.write(cl);
System.out.println(readLine(clin));
}
}
private static String readLine(InputStreamReader in)
throws IOException
{
StringBuilder sb = new StringBuilder();
for(int i = in.read(); i != -1; i = in.read())
{
char c = (char) i;
if(c != '\n') sb.append(c);
else break;
}
return sb.toString();
}
}
public class ServerDispatcher
{
public static final int PORT = 8034;
public static void main(String[] args)
{
try (ServerSocket serversock = new ServerSocket(PORT))
{
while(true)
{
Socket socket = serversock.accept();
ServerLogic sv = new ServerLogic(socket);
new Thread(() -> {
try {
sv.run();
} catch (IOException ex) {
ex.printStackTrace(System.err);
}
}).start();
}
}
catch(IOException e)
{
e.printStackTrace(System.err);
}
}
}
For the record, the ServerLogic class looks something like the following. My exit code is 1, not -999, so it's not that socket.close() is failing
class ServerLogic
{
Socket socket;
public
ServerLogic(Socket s)
{
this.socket = s;
}
public void run()
throws IOException
{
try(InputStreamReader in = new InputStreamReader(socket.getInputStream());
OutputStreamWriter out = new OutputStreamWriter(socket.getOutputStream()))
{
StringBuilder sb = new StringBuilder();
while(in.ready()) {
char c = (char) in.read();
if(c == '\n') {
String str = process(sb);
if(str != null) out.write(str);
else return;
} else {
sb.append(in.read());
}
}
} finally {
try {
socket.close();
} catch(IOException ex) {
ex.printStackTrace(System.err);
System.exit(-999);
}
}
}
private static String process(StringBuilder sb)
{ /* ... */ }
The server is expecting a newline \n to terminate the input but you never send one from the client. sc.nextLine() returns the input line but does not include the terminating newline. The while(in.ready()) loop eventually ends and the server closes the socket without ever sending a response.

Why is this exception thrown and how to recover from it?

I am creating a remote-desktop screenshot application. I have two methods on the server 1) To read the Image from client 2) to read the list of task running on the client). But everytime I try to read the client's input stream an EOF excetion is thrown. The stakctrace of the exception is
java.io.EOFException at
java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2323)
at
java.io.ObjectInputStream$BlockDataInputStream.readShort(ObjectInputStream.java:2792)
at
java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:799)
at java.io.ObjectInputStream.(ObjectInputStream.java:299) at
remoteserverclient.original.ScreenServer$ServerThread.run(ScreenServer.java:254)
Here is the code on the server where the exception is thrown
ObjectInputStream in = new ObjectInputStream(client.getInputStream());
Object obj = in.readObject();
if (obj instanceof Rectangle) {
CaptureScreen(obj, in);
} else if (obj instanceof String) {
CaptureList(in);
}
Here is the complete code for the client
public class ScreenClient {
static Socket server;
public static void main(String[] args) throws Exception {
try {
while (true) {
server = new Socket("localhost", 5494);
BufferedReader bf = new BufferedReader(new InputStreamReader(server.getInputStream()));
String s;
s = bf.readLine();
System.out.println(s);
if (s.contains("execute")) {
new ClientMessageThread().start();
}
if (s.contains("getProcessList")) {
new ClientFetchProcessThread().start();
}
}
} catch (Exception e) {
System.err.println("Disconnected From server ->" + e.getMessage());
}
}
public static class ClientMessageThread extends Thread {
Socket server;
public ClientMessageThread() {
try {
server=new Socket("localhost",5494);
} catch (Exception ex) {
ex.printStackTrace();
}
}
#Override
public void run() {
try {
BufferedImage screen;
Robot robot = new Robot();
Rectangle size = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
screen = robot.createScreenCapture(size);
int[] rgbData = new int[(int) (size.getWidth() * size.getHeight())];
screen.getRGB(0, 0, (int) size.getWidth(), (int) size.getHeight(), rgbData, 0, (int) size.getWidth());
OutputStream baseOut = server.getOutputStream();
ObjectOutputStream out = new ObjectOutputStream(baseOut);
out.writeObject(size);
for (int x = 0; x < rgbData.length; x++) {
out.writeInt(rgbData[x]);
}
out.flush();
server.close();
//added new
} catch (Exception e) {
System.err.println("Disconnected From server ->" + e.getMessage());
}
}
}
public static class ClientFetchProcessThread extends Thread {
Socket server;
public ClientFetchProcessThread() {
try {
server=new Socket("localhost",5494);
} catch (Exception ex) {
ex.printStackTrace();
}
}
public void run() {
try {
PrintWriter ps;
System.out.println("\n\n********");
StringBuilder builder = new StringBuilder("");
String query = "tasklist";
Runtime runtime = Runtime.getRuntime();
InputStream input = runtime.exec(query).getInputStream();
BufferedInputStream buffer = new BufferedInputStream(input);
BufferedReader commandResult = new BufferedReader(new InputStreamReader(buffer));
String line = "";
ps = new PrintWriter(server.getOutputStream(), true);
while ((line = commandResult.readLine()) != null) {
builder.append(line + "\n");
//byte[] responseClient=s.getBytes();
ps.write(builder.toString());
System.out.println(builder.toString());
}
server.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
You're both printing and writing objects to port 5494 from the client. The server only reads objects.
Sort it out.
The exception being thrown is EOFException (End of file exception).
ObjectInputStream throws EOFException when it reaches the end of the input. That's standard behaviour. Are you catching all exceptions thrown by in.readObject()?
Documentation:
http://docs.oracle.com/javase/7/docs/api/java/io/ObjectInputStream.html

print BufferedReader while Socket remains open

What I want are just the responses from wunderground printed to the console:
public class Weather {
public static void main(String[] args) {
String host = "rainmaker.wunderground.com";
int port = 3000;
int c;
{
try (Socket socket = new Socket(host, port);
PrintWriter printWriter = new PrintWriter(socket.getOutputStream(), true);
final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in))) {
while (true) {
System.out.println(socket.toString());
c = bufferedReader.read();
System.out.print((char) c);
}
} catch (IOException ex) {
System.out.println(ex + host + port);
System.exit(1);
} finally {
System.exit(1);
}
}
}
}
However, there's not much output to go on:
thufir#dur:~/NetBeansProjects/MudSocketClient$
thufir#dur:~/NetBeansProjects/MudSocketClient$ java -jar dist/MudSocketClient.jar
Socket[addr=rainmaker.wunderground.com/38.102.137.140,port=3000,localport=53550]
^Cthufir#dur:~/NetBeansProjects/MudSocketClient$
thufir#dur:~/NetBeansProjects/MudSocketClient$
Running telnet from the CLI, the connection works fine.
I found some old code:
public class InputOutput extends Observable {
private static final Logger log = Logger.getLogger(InputOutput.class.getName());
private Alias alias = new Alias();
public InputOutput() {
}
private void readFromConsole(final OutputStream outputStream) {
Thread read = new Thread() {
#Override
public void run() {
String line;
byte[] bytes;
Scanner scanner;
while (true) {
GameDataBean gameData = null;
scanner = new Scanner(System.in);
line = scanner.nextLine();
try {
gameData = alias.parseUserInput(line);
} catch (StringIndexOutOfBoundsException e) {
log.fine(e.toString());
}
if (gameData != null) {
setChanged();
notifyObservers(gameData);
} else {
bytes = line.getBytes();
try {
outputStream.write(bytes);
outputStream.write(10);
outputStream.flush();
} catch (IOException ex) {
log.fine(ex.toString());
}
}
}
}
};
read.start();
}
private void readInput(final InputStream inputStream) throws FileNotFoundException, IOException {
Thread readInput = new Thread() {
#Override
public void run() {
char ch = 0;
int intVal = 0;
StringBuilder sb = new StringBuilder();
try {
while ((intVal = inputStream.read()) != -1) {
ch = (char) intVal;
printToConsole(ch);
//logToFile(ch);
sb.append(ch);
if (intVal == 13) {
setChanged();
notifyObservers(sb.toString());
sb = new StringBuilder();
}
}
} catch (IOException ex) {
Logger.getLogger(InputOutput.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void logToFile(char c) throws IOException {
String fname = "weather.log";
File f = new File(fname);
f.createNewFile();
try (PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(fname, true)))) {
out.print(c);
out.flush();
}
}
private void printToConsole(char c) {
System.out.print(c);
}
};
readInput.start();
}
public void readWriteParse(final InputStream inputStream, final OutputStream outputStream) throws FileNotFoundException, IOException {
readFromConsole(outputStream);
readInput(inputStream);
}
}
I think it's that, when the socket is still open, it has to be multi-threaded, as I recall.

Categories