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
}
Related
I am writing two types of packets to a PLC which responds by sending different packets for each type of input packets. I am using socket class with two different threads to achieve this i.e. one thread to handle one type of message. Since received messages/packets at sockets can come at any thread it is getting difficult to synchronize and achieve the necessary task.
There are two types of byte data that needs to be send to the PLC socket i.e. ByteFrame1 and ByteFrame2. After sending the packets different responses are received.
Following code snippet shows Thread 1.
Thread workerThread1 = new Thread() {
#Override
public void run() {
try {
dos = new DataOutputStream(socket.getOutputStream());
while (socket.isConnected()) {
dos.write(ByteFrame1);
try {
DataInputStream dis = new DataInputStream(socket.getInputStream());
readLength = dis.read(OutputBytes1, 0, receiveBufferSize1);
//Interpret OutputBytes1 code follows
Similarly code snippet for second thread is as follows:
Thread workerThread2 = new Thread() {
#Override
public void run() {
try {
dos = new DataOutputStream(socket.getOutputStream());
while (socket.isConnected()) {
dos.write(ByteFrame2);
try {
DataInputStream dis = new DataInputStream(socket.getInputStream());
readLength = dis.read(OutputBytes2, 0, receiveBufferSize2);
//Interpret OutputBytes2 code follows
I found that both threads are receiving some garbled data that is difficult to interpret. Probable reason can be socket receive getting out of synch due to threads out of order execution. How to achieve synchronization at each thread so that the response received at each thread don't gets mixed up?
Okay a couple of things here.
You should only ever have 1 thread sending messages through a socket. If you have more, you risk gabling one message by adding another message inside it. You can use a queue to send messages sequentially.
Do NOT use Data streams! This is Java-only and now many years beyond its reason d'etre (it was created as a solution to the big/small endian issue - which is no longer an issue)
You should put together a message standard for your communications ala how an HTTP header has information about what is being sent. I recommend using XML or JSON to structure your messages (it's how I do it over Sockets and WebSockets).
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'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.
I've written a java intake program that send an PDF-formatted intake to a shared folder so that other people in the network can read it. However, there is not a way for the other people to know that an intake was sent unless someone tells them, so I want the program to send an alert message to the other computers telling them that an intake has been sent.
Now I've done some research into this and figured that TCP is the way to go since it's reliable. I also know that this is a one-to-many sending going on, so I assume that my Intake program will act as the server an the other computers will be the client, or should it be the other way around?
Now I assume that I have to create a client program that listens to the server and waits for it to send a message.
With that in mind, how do I:
Create a client program that listens for the message continuously until the program is closed. I assume that I'll be using "while (true)" and sleep. If so, how long do I put the program to sleep?
Make it as part of Windows service so that can load up when Windows start.
On the server end, how do I:
Send messages to more than one computer, since TCP is not capable of multicasting or broadcasting. I assume an array/vector will play a part here.
Oh, this is a one-way communication. The client doesn't have to respond back to the server.
First of all, UDP is quite reliable (in fact, as reliable as the IP protocol itself). TCP simply ensures that the data was received which involved quite a lot of magic in the back end. Unless you absolutely need to be sure that other machines got the message, you could do it with UDP. Mind that I'm not saying “Don't use TCP”, I just want to make it straight that you should take UDP into consideration as well.
Anyway, yes, you can create a simple listening program. Here is an example of a client in Java that reads messages from the server. It overrides the run method of a Thread class:
public void run() {
try {
String messageFromServer = reader.readLine();
while (messageFromServer != null) {
// Do things with messageFromServer here
// processor.processFromServer(messageFromServer);
messageFromServer = reader.readLine(); // Blocks the loop, waits for message
}
}
catch (IOException e) {
// Handle your exception
}
}
Amongst other things, my thread was set up as such:
public CommunicationThread(String hostname, int port, int timeout) throws IOException, SocketTimeoutException {
InetSocketAddress address = new InetSocketAddress(hostname, port);
socket = new Socket();
socket.connect(address, 2000); // 2000ms time out
// You can use the writer to write messages back out to the server
writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
}
Now, regards to server-side you can do something as follows:
Write a program to allow clients to contact, given that they know your address.
Accept the connections, and store the sockets in a list.
When you need to send out a message, traverse the list and send the data to everyone on it.
You can start listening on your server with
this.socket = new ServerSocket(port);
You could (or even should(?)) make it threaded so that you can accept clients while serving others. You can accept new clients with:
socket.accept(); // Blocks, waiting for someone to connect, returns open socket
Feel free to pass that to a whole new class which can deal with BufferedWriter (and maybe even BufferedReader if you want to read from clients as well). That class is where you would implement things such as writeToClient(message)
Consider the situation where you have a ClientConnection class that has writeToClient(String s) method and (Server server, Socket socket) and initialized ArrayList conList.
Here is how you would follow:
In a separate thread in Server, accept connections with
ClientConnection con = new ClientConnection(this, socket.accept());
conList.add(con);
Then, when you want to write to clients:
for (ClientConnection c : conList) {
c.writeToClient("I'm sending you a message!");
}
I hope you get a vague idea of what you need to do. Read the Socket documentation, it's very useful. Also, as always with threaded applications, make sure you aren't doing things such as modifying a list while traversing it and avoid race conditions.
Good luck!
I am writing a java based chat server and currently my design is based on following :-
when a person in a chat room sends a message, the chatroom class at the server side, sends the same message to every participant in the room in a loop. Obviously , this is a poor design because networks calls are being made to individual participants in a loop. Hence, for example, consider there are 10 people in a chat room. When one user sends a message, the chatroom class will send the same message in a loop to all 10 people. if lets say, the 5th person in a loop has a crappy connection, the time when the sixth .. 10th person will see the message will be affected.
if i move from unicast to multicast per room, then how do i get a private multicast group ip per chat room? Also, it seems overkill to have individual groups per chat room.
One of the main problem is that when i replied to users in a room via a loop, the method that sent data over socket connection was blocking. Hence, i am thinking if i use non blocking NIO sockets, and then send the message to recipients in a loop, would that solve the problem ?
Are there other clever tricks that can be done to optimize sending of data to recipients in the room?
The simple implementation is to use two threads per client. One thread to read from the socket the other to write to the socket. If you have few clients this will be fine. You will have to get to know NIO to handle many of clients. ('many' meaning when the threaded model does not work well.)
The Client's reading thread reads an entire message from the socket and puts it on a queue in the ChatRoom object. The chat room has a thread that takes messages off the queue and puts them on the Client's queue. The clients writing thread polls its queue and writes the message to the socket.
The ChatRoom has a thread to accept connections and create Client objects and puts them in a Collection. It has another thread to poll its message queue and distribute the messages to the Client queues.
Apache Mina has an example using NIO
I agree that serially looping over your recipients would be a bad idea. For this, you could consider using a ThreadPool to help. However, I would think that Multicast would be your best bet. It is well suited to the chatroom model. You would only need to send once and your iterative approach will be solved. You can get a unique group id by specifying a different port in your address.
The simple approach is to use two threads per client connection. One thread handles reading messages from the client the other for sending messages, thereby can send/receive messages from the client simultaneously.
To avoid network calls when looping over the client connections to broadcast a message, the server thread should add the messages into a queue to send to the client. LinkedBlockingQueue in java.util.concurrent is perfect for this. Below is an example:
/**
* Handles outgoing communication with client
*/
public class ClientConnection extends Thread {
private Queue<String> outgoingMessages = new LinkedBlockingQueue<String>(MAX_OUTGOING);
// ...
public void queueOutgoing(String message) {
if (!outgoingMessages.offer(message)) {
// Kick slow clients
kick();
}
}
public void run() {
// ...
while (isConnected) {
List<String> messages = new LinkedList<String>();
outgoingMessages.drainTo(messages);
for (String message : messages) {
send(message);
}
// ...
}
}
}
public class Server {
// ...
public void broadcast(String message) {
for (ClientConnection client : clients) {
client.queueOutgoing(message);
}
}
}