I need to send and receive alternately byte [] using Socket. How to do this ?
What wrappers to use ?
Is this ok or I can do this on quicker way
public boolean SendMessage(byte[] data){
try{
socket = new Socket(ipAddress, port);
OutputStream socketOutputStream = (OutputStream) socket.getOutputStream();
socketOutputStream.write(data);
socket.close();
return true;
}
catch(Exception exc){
System.err.println(exc.getStackTrace());
}
return false;
}
After call of this function I call function for receiving bytes, and again send =>receive and so on. Is there quicker way to do this ?
Use the same socket for reading and writing, just synchronize the two apps so that one read while the other writes, and vice-versa.
Instead of creating a new socket each time for sending/receiving and then closing it, you should use the same socket.
Say, create two threads. One as the SenderThread and the other as ReceiverThread.
The SenderThread creates a socket and then gets the outputstream and you can have a while loop with a flag to indicate whether it should run or not.
Eg: while (running){
The same thing should be done in the ReceiverThread. Create socket and inputstream. Then run the while loop.
In the while loop, you can provide your logic of writing/reading the data to/from the stream.
Use wait and notify so that the threads run in harmony..
Related
I have been trying to send a byte[] array across my client / server application using Sockets, DataInputStream and DataOutputStream, but on the server side, the program just gets stuck when I try to initialise the DataInputStream.
Here is the code on the client side (it works fine):
DataOutputStream datas = new DataOutputStream(connection.getOutputStream());
datas.flush();
byte[] send = identityKeyPair.serialize();
datas.write(send);
datas.flush();
Here is the code on the server side:
reader = new BufferedReader(new InputStreamReader(connection.getInputStream()) );
sender = new PrintWriter(connection.getOutputStream());
newUser = new BasicUserData();
System.out.println("New registration from: " + connection.getInetAddress());
System.out.println("Data:");
String un = reader.readLine();
newUser.USERNAME = un;
System.out.println(newUser.USERNAME);
String pw = reader.readLine();
newUser.PASSWORD = pw;
System.out.println(newUser.PASSWORD);
DataOutputStream dataout = new DataOutputStream(connection.getOutputStream());
System.out.println("Opened data output stream");
DataInputStream receiver = new DataInputStream(connection.getInputStream());
//It gets stuck here, and the program doesn't read anything further
receiver.read();
byte[] id = receiver.readAllBytes();
System.out.println("Opened data input stream");
You are using both connection.getInputStream() and connection.getOutputStream() in two different ways. You should use one and only one way of reading from and writing to streams, don't mix multiple ways.
When you execute reader.readLine(), the BufferedReader called reader will read up-to 8192 characters from the input stream into its buffer, likely consuming all bytes your client has written. This means that when you construct your DataInputStream around that same input stream and try to read it, there is no data available to read, causing the receiver.read() to block waiting for data. That data is never received as your client has sent all its data, which is now buffered in reader.
In addition, unless your client has closed its output stream, InputStream.readAllBytes() will block indefinitely anyway, because it is only finished when the end-of-stream has been reached. And for socket communication, that only happens when the other side closed its output stream.
Change your code so there is only one way of writing data (though not relevant here), and one way of reading data. In addition, you should establish clearly how you need to read and write data in a protocol, so to avoid consuming too much data at the wrong point, and to know how much data you need to read when.
Of course it does nothing but wait as specified in the javadoc a call to DataInputStream#read() blocks the current thread until data can be read from the input stream.
Your reader = BufferedReader(...) uses the same underlying InputStream which means the all the data the client sent is most likely already consumed by the 'login' logic.
Since neither the client nor the server close their respective streams no EOF is emitted either which leads to the stream 'just dangling' around waiting for more data.
Unless your client sends more data the server will wait eternally.
There are two solutions for your issue.
Either thread you application so that the 'await input' logic is in it's own thread or take a look at javas NIO package (more precisely Channels and Selectors)
How to close java client socket correctly?
is it necessary to close the socket.getOutputStream?
is it necessary to close the socket.getInputStream?
is it necessary to call socket.shutdownInput () ?
is it necessary to call socket.shutdownOutput () ?
What should be the sequence of calls (before|after) socket.close()?
The Socket documentation states:
Closing this socket will also close the socket's InputStream and OutputStream.
You don't have to shutdown the input/output. However that does allow you to "half" close the socket. Say if you wanted to continue to send data, but want to indicate you will no longer receive it.
So in short; It's completely fine to do the following:
...
finally {
if (socket != null)
socket.close();
}
I have to implement sending data with specific source port and in the same time listen to that port. Full duplex. Does anybody know how to implement it on java. I tried to create separate thread for listening on socket input stream but it doesnt work. I cannot bind ServerSocket and client socket to the same source port and the the same with netty.
It there any solution for dull duplex?
init(){
socket = new Socket(InetAddress.getByName(Target.getHost()), Target.getPort(), InetAddress.getByName("localhost"), 250);
in = new DataInputStream(socket.getInputStream());
out = new DataOutputStream(socket.getOutputStream());
}
private static void writeAndFlush(OutputStream out, byte[] b) throws IOException {
out.write(b);
out.flush();
}
public class MessageReader implements Runnable {
#Override
public void run() {
//this method throw exception EOF
read(in);
}
private void read(DataInputStream in){
while (isConnectionAlive()) {
StringBuffer strBuf = new StringBuffer();
byte[] b = new byte[1000];
while ((b[0] = bufferedInputStream.read(b)) != 3) {
strBuf.append(new String(b));
}
log.debug(strBuf.toString());
}
}
}
What you're trying to do is quite strange: A ServerSocket is a fully implemented socket that accepts connections, it handles its own messages and you definitely cannot piggy-back another socket on top of it.
Full duplex is fairly simple to do with NIO:
Create a Channel for your Socket in non-blocking mode
Add read to the interest OPs
Sleep with a Selector's select() method
Read any readable bytes, write any writable bytes
If writing is done, remove write from interest OPs
GOTO 3.
If you need to write, add bytes to a buffer, add write to interest OPs and wake up selector. (slightly simplified, but I'm sure you can find your way around the Javadoc)
This way you will be completely loading the outgoing buffer every time there is space and reading from the incoming one at the same time (well, single thread, but you don't have to finish writing to start reading etc).
I had run into the same question and decided to answer it myself. I would like to share with you guys the code repo. It is really simple, you can get the idea to make your stuff work. It is an elaborate example. The steps accidentally look like Ordous's solution.
https://github.com/khanhhua/full-duplex-chat
Feel free to clone! It's my weekend homework.
Main thread:
Create background thread(s) that will connect to any target machines(s).
These threads will connect to target machines and transmit data and die
Create an infinite loop
Listen for incoming connections.
Thread off any connection to handle I/O
Classes:
Server
Listens for incoming connections and threads off a Client object
Client
This class is created upon the server accepting the incoming connection, the TcpClient or NetClient (i forget what java calls it) is used to send data. Upon completion it dies.
Target
Is created during the start up and connects to a specific target and send data.
once complete it dies.
I have a problem with a BufferedOutputStream. I want to send a kml file from an Android device to a java server through a socket connection.
(The connection is ok, i am already able to exchange data with a PrintWriter in an other part of my program)
To send my kml file, I fill the buffer. But when i flush() it, nothing happen.
int lu = inFile.read();
while(lu != -1){
out.write(lu);
lu = inFile.read();
}
out.flush();
inFile.close();
inFile is my stream used to read the kml file
out is my BufferedOutputStream using the OutputStream of my socket
I don't close my out object but i don't want to, i don't use it just once. And this is the problem...
The close() method send the buffer's data but close the socket too.
The flush() method does not send the buffer's data.
I want to flush the buffer without closing my socket.
I also tried to use mySocket.shutdownOutput();
int lu = inFile.read();
while(lu != -1){
out.write(lu);
lu = inFile.read();
}
out.flush();
mySocket.shutdownOutput();
inFile.close();
This method close my stream and keep my socket open, that's what i want.
But when i try to open a new output stream, the Exception java.net.SocketException: Socket output is shutdown
So, how to flush my buffer without closing my sokcet are being unable to open a new output stream ?
Socket.close() and Socket.shutdownOutput() both send an EOS to the peer, on which he should close the socket, and after which you can no longer write to the socket, because you've closed it in that direction.
So if you need to continue writing to the socket you cannot use either of these methods.
Probably what you are searching for is a way to delimit application protocol messages. There are at least three techniques:
Send a length word prior to each message.
Send an out-of-band delimiter after each message, i.e. a byte or byte sequence that cannot occur in a message. The STX/ETX protocol, with escapes, is an example of this.
Use a self-describing message format such as Object Serialization or XML. STX/ETX is also an example of this.
Before I post this I looked at some past questions on this exceptions but couldn't find an exact answar.
I have a client server app which is basically a socket program connects with TCP.
I got this Exceptions from client side after it runs fine for some time. But still, the client is sending data to the server even though it throws Exceptions.( may be as Event objects are passed continuously). But the server works fine as it receives the data. The Exception I get from the client side while sending data is
java.io.IOException: stream active .. This occurs from the "LINE 01" as mentioned in the code below.
Here is the client code I used.
// And "Event" objects are passed continuously to this method one by one.
SocketChannel socketChannel = null;
try {
socketChannel = SocketChannel.open(new InetSocketAddress(host, port));
oos = new ObjectOutputStream(socketChannel.socket().getOutputStream());
oos.reset(); -----------> LINE 01
oos.writeObject(event);
} catch (IOException e) {
throw new RuntimeException(e);
}
Here is the server code
ServerSocketChannel serverSocketChannel = null;
try {
serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.socket().bind(new InetSocketAddress(port));
SocketChannel socket = serverSocketChannel.accept();
ObjectInputStream ois = new ObjectInputStream(socket.socket().getInputStream());
do {
Object object = ois.readObject();
if(object instanceof Event) {
Event event = (Event)object ;
viewDetailsInUI(event);
}
} while (true);
Here is the stack trace I got from the client side.
java.io.IOException: stream active
at java.io.ObjectOutputStream.reset(ObjectOutputStream.java:478)
at org.demo.siddhi.server.EventSenderClient.sendEventToSubscriber(EventSenderClient.java:42)
at org.demo.siddhi.server.query.types.SimpleStockQuoteVWAPQueryProvider$3.callBack(SimpleStockQuoteVWAPQueryProvider.java:344)
at org.siddhi.core.OutputStreamHandler.run(OutputStreamHandler.java:61)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
Can anyone please explain why is this ?
There are several problems here.
As Peter Lawrey has pointed out, calling reset() immediately you have constructed the ObjectOutputStream is completely pointless, and probably illegal. Remove it.
You are using SocketChannels in blocking mode via streams, i.e. you are just using the underlying Sockets in both cases. You would be much better off using a Socket and a ServerSocket. It's a lot simpler and clearer.
Your server loops reading an ObjectInputStream for multiple objects, but your client creates a new connection, sends one object, and then (I hope) closes it. These do not add up. Either your client should conserve the TCP connection and the ObjectOutputStream and use it to write multiple objects, in which case you may need to call reset() after writeObject(), and the server needs to break out of the loop when it gets EOFException, or your server can close its connection after reading one object, and the while (true) loop is unnecessary.
It appears to believe it is serializing an object already.
IOException if reset() is invoked while serializing an object.
You don't need to call reset() at the start as there is nothing to reset(). I would drop it and it may work fine.
If you want to call reset regularly, you can call it after writeObject().
You should also call flush() somewhere as the stream is buffered.
Look to OOS code:
493 if (depth != 0) {
494 throw new IOException("stream active");
495 }