I am fairly new to java and I am currently experimenting with sockets and buffers.
What I wanted to try was just to instantiate a connection from one local java app and another. I am using ServerSocket and Socket.
The server app has a thread that listens for connections:
public void run() {
try{
ServerSocket serverSock = new ServerSocket(62666);
while(doRun){
Socket sock = serverSock.accept();
BufferedReader reader = new BufferedReader(new InputStreamReader(sock.getInputStream()));
InfoReader.gui.writeToTextArea(reader.readLine() + "\n");
reader.close();
}
}catch(IOException e){
e.printStackTrace();
}
}
The "client" simply sends a string to the server (well it should, but I can't make it work):
try{
Socket sock = new Socket("127.0.0.1",62666);
PrintWriter writer = new PrintWriter(sock.getOutputStream());
writer.print("Connection works!");
}catch(IOException e){
e.printStackTrace();
}
I am sure that the port is open and forwarded to the local machine already. I've checked on http://canyouseeme.org/.
I've also tried using my external IP address as the IP of the socket in the client. It did not work either.
Any help appreciated :).
Mike.
Ok, then as an answer so you can close the question ;-)
Add a flush() and a close() to the Writer.
Hope that helps. :-)
Related
I'm trying to code a TCP client in android java. Most works fine. But i have one issue. If the socket is connected and the remeote host shuts down or the network goes down or something else, the socket.getinputstream keeps blocking.
I don't know if the socket is still connected. I code in objective-c too and in objective-c i get an event that the socket forcefully shuts down and i can try to reconnect. So on objective c the socket tracks the state.
In java the socket and the inputstream is still connected or blocked even the socket is down. How can i check if the socket is still connected?
#Override
protected Void doInBackground(String... params) {
try {
String host = params[0];
int port = Integer.parseInt(params[1]);
SocketAddress sockaddr = new InetSocketAddress(host, port);
Socket socket = new Socket();
socket.connect(sockaddr,5000);
socket.setSoTimeout(7000);
out = new PrintWriter(socket.getOutputStream(), true);
mBufferIn = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while (mRun) {
try {
-----> mServerMessage = mBufferIn.readLine();
}catch (Exception e){
Log.d("my","hier3" + e.getMessage());
}
if (mServerMessage.trim() != null) {
sender.messageReceived(s2);
}else{
}
}
}
} catch (UnknownHostException e
) {
The question of how to detect if the remote peer/socket has closed the connection has been answered here as well as here.
Basically, the answers suggest that you attempt to read from the socket, and then observe what happens (read() returns -1, or readLine() returns null or your read methods raise EOFException.
I have two problems with an app that i have built for socket communication, first I'll try to explain what the app does and then I'll go into the details of those two problems.
First I click on a button, which starts a thread, which sends a multicast massage "group address" through a UDP socket. Once any of the devices receive the massage, they will send a response through TCP socket and my device will act as a server to the one that sent the response. So after debugging I found out the first problem which is clientSocket = serverSocket.accept(); sometimes gets stuck and the app will block everything and keep executing it, which might happen because the udp massage might never arrive at the destination which means there is no client for the tcp server that I've created.
First question: Is there any way to make the serverSocket.accept(); non-blocking or set a time out? I've tried serverSocket.setTimeSoOut() method, but that didn't work. Maybe this problem comes from something other than the UDP message?
The second problem is that if I press the button that calls the thread twice it will throw a BindException address already in use: Which will happen because of the re execution of serverSocket.bind(new InetSocketAddress(4125));. Is there any way to fix/avoid that?
Here are the threads that I'm using:
This one is called after I press the button:
private class ChatClientThread extends Thread {
DatagramSocket socket;
String sentence;
String modifiedSentence;
BufferedReader inFromUser;
DataOutputStream outToServer;
BufferedReader inFromServer;
Socket clientSocket;
ServerSocket serverSocket;
#Override
public void run() {
/*Socket socket = null;
DataOutputStream dataOutputStream = null;
DataInputStream dataInputStream=null;*/
clientSocket=null;
try {
String data="NewTask_"+EmpPhoneNumber;
serverSocket=new ServerSocket();
serverSocket.setReuseAddress(true);
serverSocket.bind(new InetSocketAddress(4125));
socket = new DatagramSocket(52276);
socket.setBroadcast(true);
InetAddress group = InetAddress.getByName(
"224.0.1.2");
DatagramPacket packet = new DatagramPacket(data.getBytes(), data.length(),
group, 52276);
socket.send(packet);
while(true){
clientSocket = serverSocket.accept();
ConnectThread ct=new ConnectThread(clientSocket);
ct.start();
}
} catch (UnknownHostException e) {
e.printStackTrace();
final String eString = e.toString();
TicketDetails.this.runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(TicketDetails.this, eString, Toast.LENGTH_LONG).show();
}
});
} catch (IOException e) {
e.printStackTrace();
final String eString = e.toString();
TicketDetails.this.runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(TicketDetails.this, eString, Toast.LENGTH_LONG).show();
}
});
} finally {
TicketDetails.this.runOnUiThread(new Runnable() {
#Override
public void run() {
}
});
}
}
}
this one is called from the above thread as you can see:
private class ConnectThread extends Thread {
Socket socket;
String sentence;
String modifiedSentence;
BufferedReader inFromUser;
DataOutputStream outToServer;
BufferedReader inFromServer;
ConnectThread(Socket socket){
this.socket= socket;
}
#Override
public void run() {
DataInputStream dataInputStream = null;
DataOutputStream dataOutputStream = null;
Socket socket2 = null;
DataOutputStream dataOutputStream2= null;
DataInputStream dataInputStream2=null;
try {
while(true){
inFromUser = new BufferedReader( new InputStreamReader(System.in));
outToServer = new DataOutputStream(socket.getOutputStream());
inFromServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
sentence = inFromUser.readLine();
modifiedSentence = inFromServer.readLine();
socket2 = new Socket(socket.getInetAddress().getHostAddress(), 4125);
dataOutputStream2 = new DataOutputStream(
socket2.getOutputStream());
String[] parts = modifiedSentence.split("_");
String partGive = parts[0].substring(4); // 004
String partEmpId = parts[1];
if(partGive.equals("GiveMeATask")&&Integer.parseInt(partEmpId)==empId){
dataOutputStream2.writeUTF(" "+"SolveProblemOrder_2");
dataOutputStream2.flush();
}
System.out.println("FROM SERVER: " + modifiedSentence);
if(modifiedSentence!=null) break;}
outToServer.close();
inFromServer.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (dataInputStream != null) {
try {
dataInputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (dataOutputStream != null) {
try {
dataOutputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
Those are two very commmon problems. I'll answer the two in reverse order.
The button you are talking about is creating a ServerSocket and binding it to a specific port. In your case, the port is 4125. From looking at your code, you don't seem to be closing that serversocket anywhere. When you click the button a second time, a second instance of ServerSocket tries to bind to the same port - but that port is still in use by the first ServerSocket. In that case, you get a bind exception. One port cannot be used by more than one ServerSocket. The solution would be to close the existing ServerSocket before creating a new one using serverSocket.close();
If you read the documentation, it clearly states what ServerSocket.accept() does: "[...] The method blocks until a connection is made." This is the "getting stuck" that you described. The thread that executes that code is put into a waiting position and continues only when a connection is made, then returns that new connection. The classic approach is to start a new thread that waits for incoming connections so that your main thread continues to execute and your whole application does not "freeze". Another approach would be a non-blocking framework that encapsulates all that overhead away from you, one of those is Apache MINA.
I would highly suggest to look into small example projects that deal with basic client/server behaviour as you will most likely deal with threads here.
First problem: It is very likely that your application is not receiving the UDP packages. If serverSocket.accept() doesn't get any clients it'll wait indefinitely for someone to connect. You could avoid this by using yet another thread that just accepts connections to avoid freezing your application. Another way would be to use Java's NIO classes that provide non-blocking IO for pretty much anything. That would require you to use ServerSocketChannel and related classes. (Quick googling also gave me this guide which seems fairly easy to follow).
Second problem: You need to close your ServerSocket once you're done using it. Otherwise the port will never be free again to be used by another ServerSocket.
Alternatively you could just leave the Socket open and remember that you already openend it (e.g. with a boolean field in your class).
I am trying to send an object over a connection using Java. This is my client side code. The server receives the data the first time, but the second time is stuck at socket.accept(). Am i doing something wrong here? Thank you!
public class Client
{
public static void main(String args[])
{
try
{
Socket socket = new Socket("localhost", 40003);
ClientObject c = new ClientObject(socket);
c.init();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
class ClientObject
{
Socket socket;
public ClientObject(Socket socket)
{
this.socket = socket;
}
public void init()
{
try
{
// computation
SendObject so = new SendObject(toSend1, toSend2, rand, username.length());
// send all of this
OutputStream o = socket.getOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(o);
oos.writeObject(so);
o.flush();
InputStream i = socket.getInputStream();
ObjectInputStream ois = new ObjectInputStream(i);
// works, data received from the server
so = (SendObject)ois.readObject();
// further computation
so = new SendObject(null, digest, rand + 1, -1);
oos.reset();
oos.writeObject(so);
// doesn't work :(
o.flush();
}
}
Two things:
Flush the ObjectOutputStream instead of the underlying OutputStream.
The client it's using the same stream and thus the same connection to write to the server, hence the server should not expect a second accept but rather keep reading the stream of the same connection. You can of course also set up a new connect (Socket) and send the second object over that socket. Then the server should accept another socket.
Looks for me, that the server has successfully accepted the connection, otherwise you would not be able to send and receive. Look at your server code the problem may be that you close() the socket connection after the server has received from the client. Pleas provide your server code to have a look at.
I am developing a server/client application .The application works fine on an emulator but when I test it on a Nokia 5200 or a Nokia 6303i, although the connection establishes successfully, the server blocks on first read method. In other words, the client(j2me) application can't send data to server.
My client part:
Thread occ=new Thread(new Runnable() {
public void run() {
try {
SocketConnection sc = (SocketConnection)Connector.open("socket://213.233.169.142:2000");
sc.setSocketOption(SocketConnection.DELAY, 0);
OutputStream os=sc.openDataOutputStream();
DataOutputStream dos=new DataOutputStream(os);
InputStream is=sc.openDataInputStream();
DataInputStream dis=new DataInputStream(is);
//dos.writeUTF(receiverT.getString());
os.write("saalam".getBytes());
os.flush();
dos.writeUTF(Midlet.userPhoneNumber);
dos.flush();
dos.writeUTF(messT.getString());
dos.flush();
while((!dis.readUTF().equals("system-use:code=2")) && false)
{
}
dos.close();
os.close();
sc.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
});
occ.start();
My server part:
serverSocket = new ServerSocket(2000);
Socket socket=serverSocket.accept();
System.out.println("connection stablished");
inp=new DataInputStream(mySocket.getInputStream());
outp=new DataOutputStream(mySocket.getOutputStream());
receiverTemp=inp.read();//the server code blocks on this line
senderTemp=inp.readUTF();
.
.
.
.
Did you set socket permissions in the JAD file? This fact is very important to solve this kind of issues in devices
The problem finally solved.the problem was that some mobile operators don't allow send/receive information with raw sockets so we used HTTP sockets on port 80 and it worked.
I am learning currently about client server communication using Java through sockets.
First of all I retrieve my own machine's IP Address using following code.
InetAddress ownIP=InetAddress.getLocalHost();
//the result being 192.168.56.1
Now I write the simple client server application using the above mentioned address as follow
public class SimpleClientServer {
public static void main(String[] args)
{
//sending "Hello World" to the server
Socket clientSocket = null;
PrintWriter out = null;
BufferedReader in = null;
try
{
clientSocket = new Socket("192.168.56.1", 16000);
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(
clientSocket.getInputStream()));
out.println("Hello World");
out.close();
in.close();
clientSocket.close();
}
catch(IOException e)
{
System.err.println("Error occured " + e);
}
}
}
The result hower reads a follow.
Error occured java.net.ConnectException: Connection refused: connect
What is the reason for this. Is it just the wrong host address?
From the code you have given you seem to suggest that there is currently nothing listening on port 16000 for the socket to connect to.
If this is the case you need to implement something like
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(16000);
}
catch (IOException e) {
System.err.println("Could not listen on port: 16000.");
System.exit(1);
}
More information can be found in the Java online documentation and a full example is included.
With sockets, no matter what language you're using, you either initiate a connection with socket_connect or you listen and accept with socket_listen and socket_accept. Your socket_connect call is trying to connect to an ip address that doesn't seem to be listening to anything.