I am using the following code to connect my client to the server. The problem is this doesn't terminate and I am unable to start a new activity after this one.
I think the problem is either I don't close the socket or the thread doesn't terminate.
I start the thread in onCreate()
cThread = new Thread(new ClientThread());
cThread.start();
And here is my Runnable
public class ClientThread implements Runnable {
public void run() {
try {
InetAddress serverAddr = InetAddress.getByName(serverIpAddress);
Log.d("ClientActivity", "C: Connecting...");
socket = new Socket(serverAddr, 8080);
connected = true;
while (connected) {
try {
Log.d("ClientActivity", "C: Sending command.");
PrintWriter out = new PrintWriter(new BufferedWriter(new
OutputStreamWriter(socket
.getOutputStream())), true);
// where you issue the commands
out.println(serverIpAddress);
Log.d("ClientActivity", "C: Sent.");
} catch (Exception e) {
Log.e("ClientActivity", "S: Error while sending", e);
}
connected = false;
}
//socket.close();
Log.d("ClientActivity", "C: Closed.");
} catch (Exception e) {
Log.e("ClientActivity", "C: Error while connecting", e);
connected = false;
}
}
}
Your program is quite useless. Assuming the socket is estabilished, the while loop is executed only once because, at the end of the first iteration, you set connected to false, thus disabling any further cycle. You don't flush your buffered output to ensure it's written, and you don't even read from the socket, so I wonder what your custom protocol looks like... At this moment, all your program does is simply writing a string to a server, then exiting. We can't even tell why you are not able to start a new activity, because in the supplied code there is nothing preventing you from doing so.
There are basically two kinds of TCP protocols
Request-response based (like HTTP, not suitable for a chat program). The client estabilishes a connection, makes a request, reads the response, makes another request, reads the new response and so on, till the client has finished its job. A graphical client will need 2 threads at least: one for the UI update and the other for network communication.
Client and server both send messages at random times. This leverages the full-duplex capability of socket communication, however you'll need at least three threads in a GUI program: one for the UI, one blocked on the socket's input stream, and one for writing. Things get quite messy because you'll likely share streams and have to synchronize by hand.
If this is yet another chat program, I'd suggest not to design your own TCP protocol, and start with a standard technology like WebSockets. There are Java clients available, and you may test your server simply with a bit of Javascript in your browser, and there are even more choices on the server side (Socket.IO - for a JS solution, Jetty, Glassfish, ...).
After you get some experience and become acquainted with the job, you may try to design your own custom TCP protocol. By the time, you'll have learned at least the basics of sockets, threads and Android programming.
BTW, you may want to take a look at the Service API for background tasks which don't require user interaction.
Related
I am writing an application that streams data that clients can then listen to and receive. However I am running into an issue with closing a socket when a client is no longer listening.
What I do is create a ServerSocket, when then waits for a connection and once it is connected, I start streaming the data. However, once the client is no longer connected, I am stuck in a loop of streaming and cannot tell if anyone is listening. Is there a way around this?
try {
serverSocket = new ServerSocket(STREAM_PORT);
Socket clientSocket = serverSocket.accept();
PrintWriter pw = new PrintWriter(clientSocket.getOutputStream(), true);
while (true) {
pw.println("some data");
}
} catch (SocketException e) {
// Never occurs when client disconnects
} catch (IOException e) {
// Never occurs when client disconnects
}
I have tried using socket.isClosed(), but it always returns false. Am I approaching this from the wrong angle, or is there a way to do it. I would ideally not want the client to have to send the server a "end" command.
EDIT: Edited to reflect what current code I am running after #Rod_Algonquin suggestion
As you are using PrintWriter, which swallows I/O exceptions, you need to call checkError() after each write to see if an error has occurred.
We are making an somewhat RTS networked game in java. i have this main server that accepts other players which has the serversocket. Then on our game when you created your own game room
i filtered all the players that has joined my room.then when the game starts the creator of the room should be the host. should i be still using my main server or should i establish a new serversocket for those who are connected to my room? and 1 more thing should a inputstream.readObject() what for an message to go for another loop?or it continuously looping? here is the sample code snippet for the inputstream.
public void run() {
while (running) {
try {
inStream = new ObjectInputStream(client.getInputStream());
command = (String) inStream.readObject();
Thread.sleep(10);
}//try
catch (Exception e) {
e.printStackTrace();
}//catch
}//while
}//run
////accepting new client
while (running) {
try {
clientConnecting = serverSocket.accept();
new TCPServerHandle(clientConnecting).start();
Thread.sleep(10);
}//try
catch (Exception e) {
e.printStackTrace();
}//catch
}//while
You could deffinitely create a second ServerSocket for the "party" to communicate with the host. Incoming packets are demultiplexed to the correct process, using port numbers. You can set multiple TCPServerSockets to listen and accept incoming connection requests on different ports.
ServerSocket welcomeSocket = new ServerSocket(portNumber);
Socket clientSocket = welcomeSocket.accept();
And yes, it is in many cases more efficient to use a combination of TCP and UDP, because as you mention some data is more critical than other. UDP only provides a best effort service, where packets can get lost. If you want to setup a UDP socket:
DatagramSocket UDPSocket = new DatagramSocket();
Using blocking I/O with Object I/O streams aren't optimal conditions for an RTS because you don't want other clients to wait during the login process of another client. You might be thinking that you could just multi-thread everything to avoid the wait but it wouldn't make much of a difference because there are still blocking read/write operations. Also, with Object I/O streams, all objects sent have to be serialized first (known as serialization), which could be a pretty lengthy process depending on your user-base. If there are a lot of players, literally every millisecond counts. You should use non-blocking I/O (such as NIO) along with ByteBuffers. I would suggest looking at an NIO tutorial instead, this is a very detailed tutorial on how to make a simple server-client application.
Good Day,
I was taking a look at this tutorial to do a TCP Threadpool server.
http://tutorials.jenkov.com/java-multithreaded-servers/thread-pooled-server.html
It works great for listening/RECEIVING to clients and processing, and returning a response. There is a class inside that I pass in WorkerRunnable into, and that basically prints out the remote socket address (who it was sent from)
public void run(){
synchronized(this){
this.runningThread = Thread.currentThread();
}
openServerSocket();
while(! isStopped()){
Socket clientSocket = null;
try {
clientSocket = this.serverSocket.accept();
} catch (IOException e) {
if(isStopped()) {
System.out.println("Server Stopped.") ;
return;
}
throw new RuntimeException(
"Error accepting client connection", e);
}
this.threadPool.execute(
new WorkerRunnable(clientSocket,
"Thread Pooled Server"));
}
this.threadPool.shutdown();
System.out.println("Server Stopped.") ;
}
The problem is. The remote address is supposed to stay fixed (I am working within my own home wifi router). However, the IP address of the sender stays the same, but the port keeps changing!!
This is a big problem for me..as I need to be able to return a response to the user for future tasks and I actually save this address to use again to send data. When I ran this in a single TCP thread..it stayed fixed (the port).
Why does the threadpool cause the TCP remote address port to keep changing?
With TCP, the client socket port is most of the time (almost 99%, except for specific protocols) randomly chosen. But to you don't have to know it, the only thing you have to do is to keep the clientSocket reference to write back data to the client. If you want to send data to the other host after that the connection is closed, you have to start a ServerSocket on both sides with a fixed port.
Even if you test from same machine the client port will be random by default. I am not sure if there is any way to set the client source port. However, if you use netstat or capture the packet you can be sure the source port is different for every connection.
Is there a way to have reliable communications (the sender get informed that the message it sent is already received by the receiver) using Java TCP/IP library in java.net.*? I understand that one of the advantages of TCP over UDP is its reliability. Yet, I couldn't get that assurance in the experiment below:
I created two classes:
1) echo server => always sending back the data it received.
2) client => periodically send "Hello world" message to the echo server.
They were run on different computers (and worked perfectly). During the middle of the execution, I disconnected the network (unplugged the LAN cable). After disconnected, the server still keep waiting for a data until a few seconds passed (it eventually raised an exception). Similarly, the client also keep sending a data until a few seconds passed (an exception is raised).
The problem is, objectOutputStream.writeObject(message) doesn't guarantee the delivery status of the message (I expect it to block the thread, keep resending the data until delivered). Or at least I get informed, which messages are missing.
Server Code:
import java.net.*;
import java.io.*;
import java.io.Serializable;
public class SimpleServer {
public static void main(String args[]) {
try {
ServerSocket serverSocket = new ServerSocket(2002);
Socket socket = new Socket();
socket = serverSocket.accept();
InputStream inputStream = socket.getInputStream();
ObjectInputStream objectInputStream = new ObjectInputStream(
inputStream);
while (true) {
try {
String message = (String) objectInputStream.readObject();
System.out.println(message);
Thread.sleep(1000);
} catch (Exception ex) {
ex.printStackTrace();
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
Client code:
import java.net.*;
import java.io.*;
public class SimpleClient {
public static void main(String args[]) {
try {
String serverIpAddress = "localhost"; //change this
Socket socket = new Socket(serverIpAddress, 2002);
OutputStream outputStream = socket.getOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(
outputStream);
while (true) {
String message = "Hello world!";
objectOutputStream.writeObject(message);
System.out.println(message);
Thread.sleep(1000);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
If you need to know which messages have arrived in the peer application, the peer application has to send acknowledgements.
If you want this level of guarantees it sounds like you really want JMS. This can ensure not only that messages have been delivered but also have been processed correctly. i.e. there is no point having very reliable delivery if it can be discarded due to a bug.
You can monitor which messages are waiting and which consumers are falling behind. Watch a producer to see what messages it is sending, and have messages saved when it is down and are available when it restarts. i.e. reliable delivery even if the consumer is restarted.
TCP is always reliable. You don't need confirmations. However, to check that a client is up, you might also want to use a UDP stream with confirmations. Like a PING? PONG! system. Might also be TCP settings you can adjust.
Your base assumption (and understanding of TCP) here is wrong. If you unplug and then re-plug, the message most likely will not be lost.
It boils down on how long to you want the sender to wait. One hour, one day? If you'd make the timeout one day, you would unplug for two days and still say "does not work".
So the guaranteed delivery is that "either data is delivered - or you get informed". In the second case you need to solve it on application level.
You could consider using the SO_KEEPALIVE socket option which will cause the connection to be closed if no data is transmitted over the socket for 2 hours. However, obviously in many cases this doesn't offer the level of control typically needed by applications.
A second problem is that some TCP/IP stack implementations are poor and can leave your server with dangling open connections in the event of a network outage.
Therefore, I'd advise adding application level heartbeating between your client and server to ensure that both parties are still alive. This also offers the advantage of severing the connection if, for example a 3rd party client remains alive but becomes unresponsive and hence stops sending heartbeats.
I'm writing a java package that will be called by another language (matlab). If my matlab process ends, I want the Java process to keep running. Whenever matlab starts again, it should be able to communicate with the existing running process. So I think I need to have the Java application communicating through sockets in a client/server model. I envision having a simple set of functions:
startServer(host, port)
runCommand(server, command...)
stopServer(host, port)
I have never done anything like this before. Am I thinking about it in the right way, or is there an easier way of building an application that can run independently of it's parent's process? What's the best modern way of doing this (e.g. are there any good Apache packages)? Can anyone provide a simple demo or point me to a tutorial on communicating with a process through sockets?
[Edit] For some clarification, matlab is able to instantiate a java object and run java code within itself. So the startServer() function in matlab would run java code that will check if a java process is already running on that port and if not, start the server process.
I'm not tied to using sockets by any means (in case it isn't obvious, I'm mostly a matlab developer), so if there's something easier, I'm all for it. I just need to be able to run things independently of matlab, but have matlab control those processes (through java).
The server listens for a connection. When a connection is established by a client. The client can send data. In the current example the client sends the message "Hi my server". To terminate the connection, the client sends the message "bye". Then the server sends the message "bye" too. Finally the connection is ended and the server waits for an other connection. The two programs should be running in the same machine. however if you want to run them in two different machines, you may simply change the address "localhost" by the IP address of the machine where you will run the server.
The server
import java.io.*;
import java.net.*;
public class Provider{
ServerSocket providerSocket;
Socket connection = null;
ObjectOutputStream out;
ObjectInputStream in;
String message;
Provider(){}
void run()
{
try{
//1. creating a server socket
providerSocket = new ServerSocket(2004, 10);
//2. Wait for connection
System.out.println("Waiting for connection");
connection = providerSocket.accept();
System.out.println("Connection received from " + connection.getInetAddress().getHostName());
//3. get Input and Output streams
out = new ObjectOutputStream(connection.getOutputStream());
out.flush();
in = new ObjectInputStream(connection.getInputStream());
sendMessage("Connection successful");
//4. The two parts communicate via the input and output streams
do{
try{
message = (String)in.readObject();
System.out.println("client>" + message);
if (message.equals("bye"))
sendMessage("bye");
}
catch(ClassNotFoundException classnot){
System.err.println("Data received in unknown format");
}
}while(!message.equals("bye"));
}
catch(IOException ioException){
ioException.printStackTrace();
}
finally{
//4: Closing connection
try{
in.close();
out.close();
providerSocket.close();
}
catch(IOException ioException){
ioException.printStackTrace();
}
}
}
void sendMessage(String msg)
{
try{
out.writeObject(msg);
out.flush();
System.out.println("server>" + msg);
}
catch(IOException ioException){
ioException.printStackTrace();
}
}
public static void main(String args[])
{
Provider server = new Provider();
while(true){
server.run();
}
}
}
The client
import java.io.*;
import java.net.*;
public class Requester{
Socket requestSocket;
ObjectOutputStream out;
ObjectInputStream in;
String message;
Requester(){}
void run()
{
try{
//1. creating a socket to connect to the server
requestSocket = new Socket("localhost", 2004);
System.out.println("Connected to localhost in port 2004");
//2. get Input and Output streams
out = new ObjectOutputStream(requestSocket.getOutputStream());
out.flush();
in = new ObjectInputStream(requestSocket.getInputStream());
//3: Communicating with the server
do{
try{
message = (String)in.readObject();
System.out.println("server>" + message);
sendMessage("Hi my server");
message = "bye";
sendMessage(message);
}
catch(ClassNotFoundException classNot){
System.err.println("data received in unknown format");
}
}while(!message.equals("bye"));
}
catch(UnknownHostException unknownHost){
System.err.println("You are trying to connect to an unknown host!");
}
catch(IOException ioException){
ioException.printStackTrace();
}
finally{
//4: Closing connection
try{
in.close();
out.close();
requestSocket.close();
}
catch(IOException ioException){
ioException.printStackTrace();
}
}
}
void sendMessage(String msg)
{
try{
out.writeObject(msg);
out.flush();
System.out.println("client>" + msg);
}
catch(IOException ioException){
ioException.printStackTrace();
}
}
public static void main(String args[])
{
Requester client = new Requester();
client.run();
}
}
If you decide to go with a custom socket-level protocol, then I can suggest that you use JBoss Netty at the java end:
In other words, Netty is a NIO client
server framework which enables quick
and easy development of network
applications such as protocol servers
and clients. It greatly simplifies and
streamlines network programming such
as TCP and UDP socket server.
It sounds like you need the Java server process to be independent of the Matlab process. So when the Matlab process starts/stops, the Java server continues. The Java server will sit and wait for incoming connections, and handle multiple connections, disconnects etc.
Here's a tutorial for writing a Java socket server (note it's part of a larger tutorial on Java client/server socket communication).
One challenge you will face (and I can't help you here being Matlab-unaware) is creating or using a platform-independent means of creating the actual message, whether that's using a binary representation, XML (looks like Matlab has some XML functionality) or other.
If, as you say, matlab can run java code from within itself, then there should be no reason that you can't use RMI to communicate between matlab and java server. RMI is vastly easier than raw socket programming.
The easy part is the tutorial: Sun's Sockets Tutorial taught me everything I needed to know about sockets programming, and will hopefully do for you too.
I think you need to clarify your thinking about the commands you want to support, in particular the first and 3rd:
If the Java process isn't running, who's going to respond to your startServer command? And if it is running, who needs it? :)
You can certainly implement a stopServer command. But that would be kind of like having your computer pulling its own power cord out of the wall. We return to the previous question: If the server's stopped, who'll hear the start command?
As I understand it, the only remote operation you need is the middle one.
However... socket programming is only moderately fun. You may consider looking at the RMI tutorial for an alternative.
Any reason that you can't just implement your java server as a collection of servlets in tomcat? Tomcat comes with all the tools to autostart and keep the server running, you can implement SOAP service or RESTful web services pretty easily which will help to decouple your matlab code from your java code.