I'm running a TCP/IP Socket, that sends a SOAP message then gets a response then read it.
The problem is with that scenario: At first everything is fine, I send a message and I get the response using the swingworker. If I close the socket, and I try to connect again, I stop the swing worker by a boolean. When I connect again, I let the thread run, but then I don't get any output from the socket when I send a SOAP Message, but when I do debugging at that time, and I step down to codes, I get a response and an output!. How come that happens ?
Here is my code:
protected Object doInBackground() throws Exception {
Integer result = 1;
while (true) {
if (startReading && !this.server.isSocketClosed()) {
// send the SOAP Message based on which message is selected
SendSOAPRequestMessage();
//Thread.sleep(5);
String responseMessage = null;
try {
// get the response from the client/server
responseMessage = Utils.convertStreamToString(this.server);
System.out.println(responseMessage);
// give the message without the header + and check the content length and if the header is corrupted
fullMsg = decoder.DecodeSoapHeader(new String(responseMessage.getBytes("UTF-8")));
} catch (Exception ex) {
Logger.getLogger(MainWindow.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
As noted here, "SwingWorker is only designed to be executed once." Moreover, your worker does not synchronize access to this.server, so external changes may not be visible to the worker's background thread. Some alternatives:
Create a new instance of the worker for each request.
Let the worker manage the socket.
Addendum: For solution number one, should I create a new socket also?
No. As noted here, "A call to start on a thread happens-before any action in the started thread." It might be clearer to pass a reference to the socket as a constructor parameter, for example.
On the other hand, socket overhead may be irrelevant. Profile to be sure.
Related
I'm using Erlang with SSL,
My server socket listens to incoming client connections and spawns a new thread for every incoming connection (assume the looping function called clientroutine())
This thread is designed based on this tutorial I found on web: http://erlycoder.com/89/erlang-ssl-sockets-example-ssl-echo-server-ssl-client-
so basically clientroutine() waits in receive, gets data from client, does some action based on received data and recursively calls itself again
Now, the problem is that when I issue ssl:send(Socket, Data), the client (Java-based) does not get anything from inputstream
Interestingly, this happens only when I recursively call clientroutine() after ssl:send like this (I skip socket close and default cases for simplicity):
clientroutine(Socket) ->
ssl:setopts(Socket, [{active, once}]),
receive
{ssl, Sock , Data} ->
ok = ssl:send(Sock, "~100 bytes list goes to client"),
clientroutine(Socket)
end.
The following works correctly (i.e. no recursion takes places and thread finishes) and my Java-client receives the string from inputstream:
clientroutine(Socket) ->
ssl:setopts(Socket, [{active, once}]),
receive
{ssl, Sock , Data} ->
ok = ssl:send(Sock, "~100 bytes list goes to client")
end.
Java-client launches inputstream listener in a separate thread like this (BufferedReader in has been declared above, among class fields):
new Thread(new Runnable(){
#Override
public void run() {
String msg;
try {
while((msg=in.readLine())!=null)
System.out.println("user received: " + msg);
} catch (IOException e) {
System.out.println("user: exception occured - inputstream reader");
}
}}).start();
I haven't yet checked if this works with Erlang client or not, I will update my post when I check it as well, but anyhow I need it to work with Java client
Any ideas why this happens?
Probably I should use some other BufferedReader routine instead of readLine(), or maybe BufferedReader requires some special character to be pushed into outputstream after the transferred message?
UPDATE. Erlang client receives everything correctly, with and without recursive call. Seems that this is somewhat related to Java inputstream
I found out that the newline character required for readLine() to fetch a line from inputstream, was (strangely) not included when I was sending my message in "recursive" version of the program, so everything goes well after I append \n to the transferred message
I've been searching for an answer to my problem, but none of the solutions so far have helped me solve it. I'm working on an app that communicates with another device that works as a server. The app sends queries to the server and receives appropriate responses to dynamically create fragments.
In the first implementation the app sent the query and then waited to receive the answer in a single thread. But that solution wasn't satisfactory since the app did not receive any feedback from the server. The server admin said he was receiving the queries, however he hinted that the device was sending the answer back too fast and that the app probably wasn't already listening by the time the answer arrived.
So what I am trying to achieve is create seperate threads: one for listening and one for sending the query. The one that listens would start before we sent anything to the server, to ensure the app does not miss the server response.
Implementing this so far hasn't been succesful. I've tried writing and running seperate Runnable classes and AsyncTasks, but the listener never received an answer and at some points one of the threads didn't even execute. Here is the code for the asynctask listener:
#Override
protected String doInBackground(String... params) {
int bufferLength = 28;
String masterIP = "192.168.1.100";
try {
Log.i("TCPQuery", "Listening for ReActor answers ...");
Socket tcpSocket = new Socket();
SocketAddress socketAddress = new InetSocketAddress(masterIP, 50001);
try {
tcpSocket.connect(socketAddress);
Log.i("TCPQuery", "Is socket connected: " + tcpSocket.isConnected());
} catch (IOException e) {
e.printStackTrace();
}
while(true){
Log.i("TCPQuery", "Listening ...");
try{
Log.i("TCPQuery", "Waiting for ReActor response ...");
byte[] buffer = new byte[bufferLength];
tcpSocket.getInputStream().read(buffer);
Log.i("TCPQuery", "Received message " + Arrays.toString(buffer) + " from ReActor.");
}catch(Exception e){
e.printStackTrace();
Log.e("TCPQuery", "An error occured receiving the message.");
}
}
} catch (Exception e) {
Log.e("TCP", "Error", e);
}
return "";
}
And this is how the tasks are called:
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.HONEYCOMB) {
listener.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, "");
sender.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, "");
}
else {
listener.execute();
sender.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
How exactly would you approach this problem? If this code is not sufficient I would be glad to post more.
This is because Android's AsyncTask is actually only one thread, no matter how many you create, so if you really want 2 threads running at the same time, I suggest you use standard Java concurrent package tools, not AsyncTask. As explained in the documentation:
AsyncTask is designed to be a helper class around Thread and Handler
and does not constitute a generic threading framework. AsyncTasks
should ideally be used for short operations (a few seconds at the
most.) If you need to keep threads running for long periods of time,
it is highly recommended you use the various APIs provided by the
java.util.concurrent pacakge such as Executor, ThreadPoolExecutor and
FutureTask.
Look this is tcp connection. So you don't need to bother about data lose. This is port to port connection and it never sends end of stream (-1). Perhaps you have to care about read functionality. Because you can not conform all steams are received or not. Tcp read method is a blocking call. If your read buffer size is smaller than available stream size then it block until it can read fully. And you are using android device, perhaps available stream can vary depending upon your device network. So you have 2 options,
1) your buffer size should be dynamic. At first check your available input stream size by using is.available() and create your buf size by this size. If available size is zero then sleep for a certain time to check it is lost its stream availability or not.
2) set your input stream timeout. It really works, because it reads its available stream and wait for the timeout delay, if any stream is not available within the timeout period then it throws timeout exception.
Try to change your code.
For an example if I try to build a file transfer mechanism on the server program to whack one file bytes from sender A to user B by capitalizing on their own existing connecting socket, so how could avoid it interleaving with all the ongoing chat stream coming in, i.e to keep clear wait and notify between this two threads apart from creating an extra serversocket at server side …
Many thanks
Kev
create a message protocol for your app which distinguishes between various message types. then create a "file chunk" message and a "chat" message and whatever other messages you need.
pseudo code:
// sending method
public synchronized void send(Message msg) {
// write message to socket ...
}
// receiving method
while(true) {
Message msg = readMessage(); // read message from socket
handleMessage(msg); // may want to push this work to another thread
}
I saw plenty of similar questions on SO but hardly any of them have Socket in the picture. So please take time to read the question.
I have server app (using ServerSocket) which listens for requests, and when a client attempts to connect, new thread is created to serve the client (and server is back to listening mode for new requests). Now, I need to respond one client based on what other client sent to server.
Example:
ServerSocket listening for incoming connections.
Client A connects, new thread is created to serve A.
Client B connects, new thread is created to serve B.
A sends message "Hello from A" to the Server.
Send this message as a response to Client B.
I'm new to this whole "inter-thread communication" thing. Obviously, above mentioned situation sounds dead simple, but I'm describing this to get a hint, as I'll be exchanging huge amount data among clients keeping server as intermediate.
Also, what if I want to keep a shared object limited to, say 10, particular Clients? such that, when 11th client connects to the server, I create new shared object, which will be used to exchange data between 11th, 12th, 13th..... upto 20th client. And so on for every single set of 10 clients.
What I tried: (foolish I guess)
I have a public class with that object supposed to be shared as public static, so that I can use it as global without instantiating it, like MyGlobalClass.SharedMsg.
That doesn't work, I was unable to send data received in one thread to the other.
I'm aware that there is an obvious locking problem since if one thread is writing to an object, other can't be accessing it until the first thread is done writing.
So what would be an ideal approach to this problem?
Update
Since the way in which I create threads for serving incoming connection requests, I can't understand how I can share same object among the threads, since using Global object as mentioned above doesn't work.
Following is how I listen for incoming connections and create serving threads dynamically.
// Method of server class
public void startServer()
{
if (!isRunning)
{
try
{
isRunning = true;
while (isRunning)
{
try
{
new ClientHandler(mysocketserver.accept()).start();
}
catch (SocketTimeoutException ex)
{
//nothing to perform here, go back again to listening.
}
catch (SocketException ex)
{
//Not to handle, since I'll stop the server using SocketServer's close() method, and its going to throw SocketException anyway.
}
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
else
System.out.println("Server Already Started!");
}
And the ClientHandler class.
public class ClientHandler extends Thread
{
private Socket client = null;
private ObjectInputStream in = null;
private ObjectOutputStream out = null;
public ClientHandler(Socket client)
{
super("ClientHandler");
this.client = client;
}
//This run() is common for every Client that connects, and that's where the problem is.
public void run()
{
try
{
in = new ObjectInputStream(client.getInputStream());
out = new ObjectOutputStream(client.getOutputStream());
//Message received from this thread.
String msg = in.readObject().toString();
System.out.println("Client # "+ client.getInetAddress().getHostAddress() +" Says : "+msg);
//Response to this client.
out.writeObject("Message Received");
out.close();
in.close();
client.close();
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
I believe that the way I'm creating dynamic threads to serve each client that connects, sharing the same data source is not possible using Global object, since the body of run() above is exactly the same for every client that connects, hence this same method is both consumer and producer. What fixes should I make such that I could create dynamic threads for each connection and still share the same object.
You probably want a queue for communication between each client. Each Queue will be the 'pipeline' for data pushed from one client to the other.
You would use it like so (pseudo code):
Thread 1:
Receive request from Client A, with message for Client B
Put message on back of concurrent Queue A2B
Respond to Client A.
Thread 2:
Receive request from Client B.
Pop message from front of Queue A2B
Respond to Client B with message.
You might also want it generic, so you have a AllToB Queue that many clients (and thus many threads) can write to.
Classes of note: ConcurrentLinkedQueue, ArrayBlockingQueue.
If you want to limit the number of messages, then ArrayBlockingQueue with its capacity constructor allows you to do this. If you don't need the blocking functionality, you can use the methods offer and poll rather than put and take.
I wouldn't worry about sharing the queues, it makes the problem significantly more complicated. Only do this if you know there is a memory usage problem you need to address.
EDIT: Based on your update:
If you need to share a single instance between all dynamically created instances you can either:
Make a static instance.
Pass it into the constructor.
Example of 1:
public class ClientHandler extends Thread
{
public static final Map<ClientHandler, BlockingQueue<String>> messageQueues
= new ConcurrentHashMap<>();
<snip>
public ClientHandler(Socket client)
{
super("ClientHandler");
this.client = client;
// Note: Bad practice to reference 'this' in a constructor.
// This can throw an error based on what the put method does.
// As such, if you are to do this, put it at the end of the method.
messageQueues.put(this, new ArrayBlockingQueue<>());
}
// You can now access this in the run() method like so:
// Get messages for the current client.
// messageQueues.get(this).poll();
// Send messages to the thread for another client.
// messageQueues.get(someClient).offer(message);
A couple of notes:
The messageQueues object should really contain some sort of identifier for the client rather than an object reference that is short lived.
A more testable design would pass the messageQueues object into the constructor to allow mocking.
I would probably recommend using a wrapper class for the map, so you can just call offer with 2 parameters rather than having to worry about the map semantics.
I'm in the process of writing a Java client and server, and they're both talking to each other correctly. At the moment, however, the client must always send a message to the server before it can receive one - but I want the server to be able to send a message without the client asking for it.
In AS3, my primary language, I'd have added an event listener to the socket and handled the data that way - but I can't seem to find out how I would do that in Java.
Currently my client has this code in it:
public String send(String message) {
out.println(message);
try {
return in.readLine();
} catch (IOException ex) {
return "";
}
}
Basically I call it, passing my message, and it returns giving me the server's response.
Instead of doing this I want to send a message there, like below, and have the response picked up somewhere different (by an event listener).
public void send(String message) {
out.println(message);
}
As I couldn't figure out how an event listener would work, I did contemplate using a separate thread to run while(true){in.readLine;} but I want to avoid this if at all possible; I'm not too comfy with threads, and I want to keep it as simple as possible.
The simplest way to do this is to use threads. I would have at least one thread reading the socket which allows the server to send a message to the client any time.
The problem with mixed responses and events is that your first block won't work because the "response" could be an event.
If you don't want to use threads, you could have something like
// simple but probably not a good idea.
public String send(String message) {
out.println(message);
try {
while(true) {
String line = in.readLine();
if (isEvent(line))
processEvent(line);
else
return line;
} catch (IOException ex) {
return "";
}
}
However, it will only read events when a request is sent and if this is not done regularly it can cause the stream to bank up all the way to the server causing it to block as well.