Connection reset by peer or socket closed out of nothing - java

So far I've used this site whenever I encountered a problem and I've found solutions too, but this time I have no idea what's even happening.
I am working on a game that is based on a 1-vs-1-multiplayer-mode. So far i have created a server and my program with the client.
My server creates a new thread with a socket for every client that connects with the server and when the "New Game"-Button is pressed in the game, the thread searches for another thread that is looking for a new game right now and once it found him, creates a separate thread that sends a message to both threads to signal them that a game has started, which is then sent through their socket to the program which reacts accordingly.
Here is my code:
Thread:
public void run() {
try {
out = new ObjectOutputStream(socket.getOutputStream());
in = new ObjectInputStream(socket.getInputStream());
ServerNachricht inputLine, outputLine;
LabyrinthProtocol prot = new LabyrinthProtocol();
while (socket.isConnected()) {
ServerNachricht is a class that consists of a type(int), a sender(player) and a message(String).
When the thread gets a new game message, the protocol changes the players status-value to "searching", then looks if another "searching" player exists and then changes both players values to "playing" and returns a new ServerNachricht of type Kampfbeginn with the found player as sender.
After the protocol returns the outputLine, this is what the thread does:
if (outputLine.getArt() == ServerNachricht.KAMPFBEGINN) {
System.out.println(outputLine.getSender().getSname()+" ist da");
server.kampfbeginn(this, outputLine.getSender());
}
The sysout just verifies that the protocol has actually found another player and is printing that players name to be sure. So far, this has always worked.
Here are the parts that call for a new game in the server:
public void kampfbeginn(LabyrinthThread t, Spieler gegner) {
KampfThread kampf = null;
System.out.println(gegner.getSname()+" anerkannt");
for(int i = 0;i<threads.size();i++){
if(threads.get(i)!=null){
System.out.println(threads.get(i).getSpieler().getSname());
if(threads.get(i).getSpieler().getSname().equals(gegner.getSname())){
LabyrinthThread gegnert = threads.get(i);
kampf = new KampfThread(t,gegnert);
t.setKampf(kampf);
gegnert.setKampf(kampf);
break;
}
}
}
This code searches through every existing thread (the server stores them in a vector) and checks if that threads connected player is the player returned by the protocol. When the thread was found, both threads are then given to a newly created thread that stores both of them while also storing that new thread in both threads.
The new thread even verifies the connection with two sysouts:
public KampfThread(LabyrinthThread spieler1, LabyrinthThread spieler2) {
super();
this.spieler1 = spieler1;
this.spieler2 = spieler2;
System.out.println(spieler1.getSpieler().getSname() + "ist drin");
System.out.println(spieler2.getSpieler().getSname() + "ist drin");
}
which I also get every time.
After both connections are established, that thread sends a message to both threads so that they will notify their programs to start:
case(ServerNachricht.KAMPFBEGINN):
spieler1.ThreadNachricht(new ServerNachricht(ServerNachricht.KAMPFBEGINN,spieler2.getSpieler(),""));
spieler2.ThreadNachricht(new ServerNachricht(ServerNachricht.KAMPFBEGINN,spieler1.getSpieler(),""));
break;
which calls this method in the threads:
public void ThreadNachricht(ServerNachricht s) {
if(socket.isConnected()) {
try {
out.writeObject(s);
} catch (IOException e) {
e.printStackTrace();
}
}
The strange thing is that this works absolutely perfect about 80% of the time (so both programs go into the "game started" mode) but sometimes it just works for one or even neither program and the server gets either a
Connection reset by peer
or a
Socket closed
error in
public void ThreadNachricht(ServerNachricht s) {
if(socket.isConnected()) {
try {
out.writeObject(s);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
in the out.writeObject(s); line. There is no line anywhere that closes anything (I've even taken out every single close() out of anywhere to make sure that nothing can interfere) and there seems to be no pattern at all to when it works and when it doesn't (and not working closes the servers and the programs clientsocket so the program is unable to work when that happens). Is there any way I can guarantee that my program works or is there any error I made? I am rather desperate because I couldn't even do major tests to find out a pattern since starting the program twice with exactly the same setup still causes it to work most of the time.
Edit: I literally just had a situation in which one player went into the new game mode while the other one stayed in the main menu (resulting in a Connection reset by peer: socket write error for the server) twice in a row before it worked the third time without any problems in the same run. So I searched with both players but only one went into the game screen (and the other one got the error). I then pressed back to go into the main menu and did the same again with the same result. When I tried for the third time, it worked and both players got into the game screen and started interacting with each other.

It was actually a rather funny error I made: My server kept the threads stored in his vector even after their sockets disconnected. So logging in with an account that was already connected to the server before since its last restart (I use to keep the server running when I'm just testing cosmetic things) causes its
for(int i = 0;i<threads.size();i++){
if(threads.get(i)!=null){
System.out.println(threads.get(i).getSpieler().getSname());
if(threads.get(i).getSpieler().getSname().equals(gegner.getSname())){
loop to determine the thread for the other player to find an older and already closed thread and not the one the other player is connected to at the moment.

'connection reset' usually means that your wrote to a connection that had already been closed by the peer: in other words, an application protocol error.
'socket closed' means that you closed the socket and then continued to use it.
Neither of these comes 'out of nowhere'. Both indicate application bugs.
isConnected() is not an appropriate test. It doesn't magically become false when the peer disconnects. I'm not sure it becomes false even when you disconnect.
All this indicates nothing more than coding bugs. Post more of your code and I'll show you some more of them.

Related

Socket connection half dropped - IOException not thrown

i read some of the answers here about this problem, but i wasn't satisfied with them, so i decided to ask it my self. So I know that there are similar questions, but since the answers don't really work for me, i asked myself.
I have an app that lets 2 users connect to each other (one works as a server, the other one as client). They will send files through that socket connection. I am using a Service with 2 threads inside, one to read, another one to send the file that the user chose.
Here is the problem : If a client closes the app by swiping it on the android menu (of the apps that are running), and then the server (the other guy) tries to send him something, in my opinion it should throw an IOException, since the other end of the socket streams is over. But it is not doing that and i don't know why. If i try to send something to someone that left, i want to show a Toast.
Edit: just noticed it always stops at the instruction out.reset();
Do any of you know why that exception is not being thrown?
What could be a possible solution.
PS: It is a lite app, so to send Keep Alive messages wouldn't be a good solution. Also, it already showed the toast that i have one or two times, but then i couldn't replicate that behaviour again.
Here is my code where i wan't that to happen :
ClientHandler tmp = connectedClients.get(key);
ObjectOutputStream out = tmp.getOut();
Socket s = tmp.getSocket();
if(s.isClosed()){
System.out.println("The socket of this client "+key + " is closed!");
}
if(s.isOutputShutdown()){
System.out.println("The output of this client is shutdown !");//only checks this side, the other one is the one that is shutdown
}
System.out.println("changed the culpado to : "+1);
createSendNotification();
File apkToSend;
for(int i=0;i<listOfApps.size();i++){
System.out.println("Item do be sent is : "+i);
HighwayGridViewAppItem tmpItem=listOfApps.get(i);
filePath=tmpItem.getFilePath();
appName=tmpItem.getAppName();
System.out.println("his filepath to send is : "+filePath);
System.out.println("his appname to send is : "+appName);
couldSend=false;
apkToSend=new File(filePath);
if(apkToSend.exists()){//do i reallly need this if?
apkToSendSize=apkToSend.length();
System.out.println("File size: " +apkToSendSize);
try{
out.writeObject(appName +": "+ apkToSendSize);//appName to send to have the name of the file
byte[] buffer = new byte [8192];
BufferedInputStream bis=new BufferedInputStream(new FileInputStream(apkToSend));
int count;
totalToSend =0;
showSendProgress();
while((count=bis.read(buffer))!=-1){
out.write(buffer,0,count);
totalToSend +=count;
out.reset();
System.out.println("ServerComm send thread - already sent this ammount : "+ totalToSend);
}
out.flush();
bis.close();
}
catch ( IOException e){
System.out.println("It is throwing the input output exception");
e.printStackTrace();
connectedClients.remove(key);
if(clients.size()<=1){
h.post(new Runnable() {
#Override
public void run() {
Toast.makeText(context, "No one is in your group.", Toast.LENGTH_SHORT).show();
}
});
i=listOfApps.size()+1;
}else{
System.out.println("Has more than one");
}
}
PS: When i try to send to a "closed" client, it prints a few "ServerComm send thread - already sent this ammount : "+ totalToSend" but then just stops, which is when i think it should throw the exception, but it just stops, and doesn't give any error, the app continues its life, but i NEED to give some input to the user that some problem went down.
Also, I create that Handler in the onCreate method of this service, it is being correctly created (since it is in a Service, it needs different creation) with the main looper.
Thank you guys in advance.
EDIT: Eventually, after almost 4 minutes, it throws a SocketException, but i can't wait that long.
Just because Android disposes of an app does not mean that internally all of your open connections are closed, it is mostly likely you need to detect the Android event and then execute the code that explicitly closes the open socket rather than waiting for Android to take care of it eventually. Otherwise, you will have to wait for the socket to be closed by garbage collection calling the finalizer.
This post here has some details about Android events and the onDestroy method in particular: How to close Android application?
If you require an immediate disconnection detection then you would have to implement your own ping/keep alive mechanism which would normally mean sending packets and acknowledging them continuously to be able to catch an exception more reliably.

Stuck at socket.accept()

Hello I just started a Java Enterprise Edition class. This is my first exposure to this side of java programming so this is all pretty new to me. I was reading my textbook and decided to type it one of the codes given to me to try it out. This code is not mine. The program should output "hello, enter BYE to exit" and then echo back anything that is typed into the prompt. For some reason the code hangs at the try block containing s.accept (it outputs 1 then 2 then hangs). I was just wondering if anyone would have any insight as to why this isnt working for me when i copied it exactly from my textbook. Here is the code:
import java.io.*;
import java.net.*;
import java.util.*;
public class EchoServer
{
public static void main (String[] args) throws IOException
{
System.out.println("1");
try (ServerSocket s = new ServerSocket(8189))
{
System.out.println("2");
try(Socket incoming = s.accept())
{
System.out.println("3");
InputStream inStream = incoming.getInputStream();
OutputStream outStream = incoming.getOutputStream();
try(Scanner in = new Scanner(inStream))
{
PrintWriter out = new PrintWriter(outStream,true);
out.println("Hello! Enter BYE to exit.");
boolean done = false;
while(!done && in.hasNextLine())
{
String line = in.nextLine();
out.println("Echo: " + line);
if(line.trim().equals("BYE"))
done = true;
}
}
}
}
}
}
Im sure this is something relatively simple to explain, im just new to this and was wondering why this isnt working when i try to run it.
Is there a corresponding EchoClient demo in the textbook?
Socket.accept() hangs by design until a client connects to the port that is being waited on, in this case, port 8189. Your program is working fine
If you read the documentation you will see that Socket.accept() actually hangs the thread until a client connect , so after the connection is established it will continue also your using an echo protocol , so you need to make sure that the client in this case is ANOTHER server that supports echo protocol
You're dealing with networking. Great. Let's distinguish between terms a bit.
socket.accept() is an example of a blocking function call. I can't find any link to provide a quick interpretation but, to oversimplify, your code stops at that point until some event it is waiting for finally happens, in this case, a connection from a corresponding client. Hence, its behaving normally, as expected, as documented. You'll encounter lots of other blocking function calls waiting for all sorts of events like an item is inserted to a queue, threads finish processing, etc.
In contrast, the word "hang" as normally used, refers to a deadlock or (less commonly), kernel panic. This is usually a mistake on the programmer's part.

Android - multithread TCP connection

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.

Java threaded socket connection timeouts

I have to make simultaneous tcp socket connections every x seconds to multiple machines, in order to get something like a status update packet.
I use a Callable thread class, which creates a future task that connects to each machine, sends a query packet, and receives a reply which is returned to the main thread that creates all the callable objects.
My socket connection class is :
public class ClientConnect implements Callable<String> {
Connection con = null;
Statement st = null;
ResultSet rs = null;
String hostipp, hostnamee;
ClientConnect(String hostname, String hostip) {
hostnamee=hostname;
hostipp = hostip;
}
#Override
public String call() throws Exception {
return GetData();
}
private String GetData() {
Socket so = new Socket();
SocketAddress sa = null;
PrintWriter out = null;
BufferedReader in = null;
try {
sa = new InetSocketAddress(InetAddress.getByName(hostipp), 2223);
} catch (UnknownHostException e1) {
e1.printStackTrace();
}
try {
so.connect(sa, 10000);
out = new PrintWriter(so.getOutputStream(), true);
out.println("\1IDC_UPDATE\1");
in = new BufferedReader(new InputStreamReader(so.getInputStream()));
String [] response = in.readLine().split("\1");
out.close();in.close();so.close(); so = null;
try{
Integer.parseInt(response[2]);
} catch(NumberFormatException e) {
System.out.println("Number format exception");
return hostnamee + "|-1" ;
}
return hostnamee + "|" + response[2];
} catch (IOException e) {
try {
if(out!=null)out.close();
if(in!=null)in.close();
so.close();so = null;
return hostnamee + "|-1" ;
} catch (IOException e1) {
// TODO Auto-generated catch block
return hostnamee + "|-1" ;
}
}
}
}
And this is the way i create a pool of threads in my main class :
private void StartThreadPool()
{
ExecutorService pool = Executors.newFixedThreadPool(30);
List<Future<String>> list = new ArrayList<Future<String>>();
for (Map.Entry<String, String> entry : pc_nameip.entrySet())
{
Callable<String> worker = new ClientConnect(entry.getKey(),entry.getValue());
Future<String> submit = pool.submit(worker);
list.add(submit);
}
for (Future<String> future : list) {
try {
String threadresult;
threadresult = future.get();
//........ PROCESS DATA HERE!..........//
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
The pc_nameip map contains (hostname, hostip) values and for every entry i create a ClientConnect thread object.
My problem is that when my list of machines contains lets say 10 pcs (which most of them are not alive), i get a lot of timeout exceptions (in alive pcs) even though my timeout limit is set to 10 seconds.
If i force the list to contain a single working pc, I have no problem.
The timeouts are pretty random, no clue what's causing them.
All machines are in a local network, the remote servers are written by my also (in C/C++) and been working in another setup for more than 2 years without any problems.
Am i missing something or could it be an os network restriction problem?
I am testing this code on windows xp sp3. Thanks in advance!
UPDATE:
After creating two new server machines, and keeping one that was getting a lot of timeouts, i have the following results :
For 100 thread runs over 20 minutes :
NEW_SERVER1 : 99 successful connections/ 1 timeouts
NEW_SERVER2 : 94 successful connections/ 6 timeouts
OLD_SERVER : 57 successful connections/ 43 timeouts
Other info :
- I experienced a JRE crash (EXCEPTION_ACCESS_VIOLATION (0xc0000005)) once and had to restart the application.
- I noticed that while the app was running my network connection was struggling as i was browsing the internet. I have no idea if this is expected but i think my having at MAX 15 threads is not that much.
So, fisrt of all my old servers had some kind of problem. No idea what that was, since my new servers were created from the same OS image.
Secondly, although the timeout percentage has dropped dramatically, i still think it is uncommon to get even one timeout in a small LAN like ours. But this could be a server's application part problem.
Finally my point of view is that, apart from the old server's problem (i still cannot beleive i lost so much time with that!), there must be either a server app bug, or a JDK related bug (since i experienced that JRE crash).
p.s. I use Eclipse as IDE and my JRE is the latest.
If any of the above ring any bells to you, please comment.
Thank you.
-----EDIT-----
Could it be that PrintWriter and/or BufferedReader are not actually thread safe????!!!?
----NEW EDIT 09 Sep 2013----
After re-reading all the comments and thanks to #Gray and his comment :
When you run multiple servers does the first couple work and the rest of them timeout? Might be interesting to put a small sleep in your fork loop (like 10 or 100ms) to see if it works that way.
I rearanged the tree list of the hosts/ip's and got some really strange results.
It seems that if an alive host is placed on top of the tree list, thus being first to start a socket connection, has no problem connecting and receiving packets without any delay or timeout.
On the contrary, if an alive host is placed at the bottom of the list, with several dead hosts before it, it just takes too long to connect and with my previous timeout of 10 secs it failed to connect. But after changing the timeout to 60 seconds (thanks to #EJP) i realised that no timeouts are occuring!
It just takes too long to connect (more than 20 seconds in some occasions).
Something is blobking new socket connections, and it isn't that the hosts or network is to busy to respond.
I have some debug data here, if you would like to take a look :
http://pastebin.com/2m8jDwKL
You could simply check for availability before you connect to the socket. There is an answer who provides some kind of hackish workaround https://stackoverflow.com/a/10145643/1809463
Process p1 = java.lang.Runtime.getRuntime().exec("ping -c 1 " + ip);
int returnVal = p1.waitFor();
boolean reachable = (returnVal==0);
by jayunit100
It should work on unix and windows, since ping is a common program.
My problem is that when my list of machines contains lets say 10 pcs (which most of them are not alive), i get a lot of timeout exceptions (in alive pcs) even though my timeout limit is set to 10 seconds.
So as I understand the problem, if you have (for example) 10 PCs in your map and 1 is alive and the other 9 are not online, all 10 connections time out. If you just put the 1 alive PC in the map, it shows up as fine.
This points to some sort of concurrency problem but I can't see it. I would have thought that there was some sort of shared data that was not being locked or something. I see your test code is using Statement and ResultSet. Maybe there is a database connection that is being shared without locking or something? Can you try just returning the result string and printing it out?
Less likely is some sort of network or firewall configuration but the idea that one failed connection would cause another to fail is just strange. Maybe try running your program on one of the servers or from another computer?
If I try your test code, it seems to work fine. Here's the source code for my test class. It has no problems contacting a combination of online and offline hosts.
Lastly some quick comments about your code:
You should close the streams, readers, and sockets in a finally block. Check my test class for a better pattern there.
You should return a small Result class instead of passing back a String that they has to be parsed.
Hope this helps.
After a lot of reading and experimentation i will have to answer my own question (if i am allowed to do of course).
Java just can't handle concurrent multiple socket connections without adding a big performance overhead. At least in a Core2Duo/4GB RAM/ Windows XP machine.
Creating multiple concurrent socket connections to remote hosts (using of course the code i posted) creates some kind of resource bottleneck, or blocking situation, wich i am still not aware of.
If you try to connect to 20 hosts simultaneously, and a lot of them are disconnected, then you cannot guarantee a "fast" connection to the alive ones.
You will get connected but could be after 20-25 seconds. Meaning that you'll have to set socket timeout to something like 60 seconds. (not acceptable for my application)
If an alive host is lucky to start its connection try first (having in mind that concurrency is not absolute. the for loop still has sequentiality), then he will probably get connected very fast and get a response.
If it is unlucky, the socket.connect() method will block for some time, depending on how many are the hosts before it that will timeout eventually.
After adding a small sleep between the pool.submit(worker) method calls (100 ms) i realised that it makes some difference. I get to connect faster to the "unlucky" hosts. But still if the list of dead hosts is increased, the results are almost the same.
If i edit my host list and place a previously "unlucky" host at the top (before dead hosts), all problems dissapear...
So, for some reason the socket.connect() method creates a form of bottleneck when the hosts to connect to are many, and not alive. Be it a JVM problem, a OS limitation or bad coding from my side, i have no clue...
I will try a different coding approach and hopefully tommorow i will post some feedback.
p.s. This answer made me think of my problem :
https://stackoverflow.com/a/4351360/2025271

Expanding my Java program to send a alert message to other computers

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!

Categories