I am new to JAVA/Android TCP connection. I try to implement a TCP Server like the following code.
private class TCPServerThread implements Runnable
{
#Override
public void run() {
// TODO Auto-generated method stub
try {
ServerSocket serverSocket = new ServerSocket(PORT);
while (true) {
try {
socket = serverSocket.accept();
ClientAddress = socket.getInetAddress();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
I can send message to the client when I get the socket by socket = serverSocket.accept();
-----------------------------Question-----------------------------
Do I need to set different port for client ?
But How to get the multiple socket from the multiple client ?
Do I need to set different port for client
No.
But How to get the multiple socket from the multiple client?
Your code already does that.
Related
I have a TCP Server written in java. I am trying to connect to it via a TCP client socket written in dartlang but the client written in dartlang times out almost immediately after the initial connection (my five second timeout set in the java code). I was able to send a message to the dart client in a test immediately after it connected but it soon timed out. However the data in the dartlang '{"packet_id":1}' never gets received by the server.
I tried writing a test server in dartlang and it was able to connect and send/receive messages without any issues.
Dart Client:
import 'dart:io';
import 'dart:async';
main(List<String> arguments) {
Future<Socket> future = Socket.connect('localhost', 12345);
future.then((client) {
print('connected to server!');
client.handleError((data){
print(data);
});
client.listen(
(data) {
print(new String.fromCharCodes(data));
},
onDone:(){
print("Done");},
onError: (error) {
print(error);
}
);
String requestHalls = '{"packet_id":1}';
client.write(requestHalls);
}).catchError(() {print('Error connecting');});
print('Hello world: ${dart_test.calculate()}!');
}
My Java client connects to the Java Server socket just fine.
EDIT: adding java code
creating the serversocket.
#Override
public void run() {
// Create Server Socket for clients to connect to
try {
// load data from config manager
ConfigManager config = HDAServer.getConfigManager();
int port = config.getServerPort();
String ip = config.getServerURL();
Inet4Address inet4 = (Inet4Address) Inet4Address.getByName(ip); // this allows for binding to domain name or ipv4 address
HDAServer.getLogger().info(String.format("Opening Server Socket at address(%s)= %s:%s", ip, inet4.getHostAddress(), port));
// attempt to bind
serverSocket = new ServerSocket(config.getServerPort(), 50, inet4);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// wait for incoming client connections
waitForConnections();
}
/**
* Method that waits for incoming connections, adds the connection to a new pool, and creates a
* new thread for the connection to run on.
*/
private void waitForConnections() {
// loop through waiting for incoming connections until server shuts down
while (!shutdown) {
Socket socket = null;
try {
// blocks thread waiting for a connection
socket = serverSocket.accept();
} catch (IOException e) {
if (e.getMessage().equals("socket closed")) {
HDAServer.getLogger().info("Shutting Down Server Socket");
continue;// skip to while check
} else {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// create our connection class, start it in a new thread, and add it to our connection list
HDAServerConnection newConn = new HDAServerConnection(socket);
new Thread(newConn).start();
connections.add(newConn);
HDAServer.getLogger().info(String.format("Client connected from: %1s", newConn.getRemoteIP()));
// reap dead connections
this.reapDeadConnections();
}
}
Servers "Client" HDAConnection class:
protected Socket socket;
protected DataInputStream inputStream;
protected DataOutputStream outputStream;
private boolean shutdown = false;
public HDAConnection(Socket socket) {
this.socket = socket;
// configure socket
try {
socket.setKeepAlive(true);
socket.setSoTimeout(5000);
socket.setTcpNoDelay(true);
} catch (SocketException ex) {
AbstractHDALogger.get().severe("Error configuring Socket Connection.", ex);
}
// create input/output stream for handling data
try {
inputStream = new DataInputStream(socket.getInputStream());
outputStream = new DataOutputStream(socket.getOutputStream());
} catch (IOException ex) {
AbstractHDALogger.get().severe("Error creating input/output streams.", ex);
}
}
code that is listening for a message over the stream.
String response = null;
try {
response = new BufferedReader(new InputStreamReader(inputStream)).readLine();
} catch(SocketTimeoutException ste) {
shutdown();
AbstractHDALogger.get().severe(String.format("Socket Timed out(%s), closing Connection", this.getRemoteIP()), ste);
// TODO: handle exception
} catch (IOException e) {
// TODO Make this better?
// IO Exception probably means client disconnected, so we should terminate.
if (e.getMessage().equals("Connection reset")) {
shutdown();
AbstractHDALogger.get().info(String.format("Client Connection Disconnected(%s). Closing connection.", this.getRemoteIP()));
} else {
shutdown();
AbstractHDALogger.get().severe(String.format("Connection Error(%s), closing Connection", this.getRemoteIP()), e);
}
return null;
}
The socket is timing out on the Java Server because the dartlang client is never writing a newline at the end of its message and the Java Server is using the readline method to read. This function will only return when it reads a new line character. After reading the initial message from the dartlang client the Java server waits five seconds for more data to be sent but will time out as nothing more is ever sent.
The dartlang client should use the writeln function or appent a newline character to the end of its messages for the Java server BufferedReader to return.
I have java client server application. Server is running or may not be connected. but we need to connect with ip and port.
Socket s=new Socket(ip,port);
if it is connected, socket will be created, else it throws IOException. then i will set a status of that connection as not connected in an object.
if connected, i will send data as commands. It will respond to that command with data. We send commands with output stream and read responce with input-stream of the socket.
I need to automatically reconnect to the server when server is available (wired or wifi connection).
How to Use Multi threading here
ex:
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
public class ConnectionThread implements Runnable {
static class ConnectionStatus {
boolean connected = false;
public boolean isConnected() {
return connected;
}
public void setConnected(boolean connected) {
this.connected = connected;
}
}
ConnectionStatus status;
Socket socket;
String ip;
int port;
public ConnectionThread(ConnectionStatus status, String ip, int port) {
this.status = status;
this.ip = ip;
this.port = port;
}
public void connectAgain() throws IOException {
while (!status.isConnected()) {
socket = new Socket(ip, port);
status.setConnected(true);
}
}
public void run() {
try {
connectAgain();
} catch (IOException e) {
try {
Thread.sleep(1000);
connectAgain();
} catch (InterruptedException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
public static void main(String[] args) {
ConnectionStatus status = new ConnectionStatus();
status.setConnected(false);
ConnectionThread cthread = new ConnectionThread(status, "192.166.102.201", 1986);
Thread x = new Thread(cthread);
x.start();
System.out.println("Connected ..." + status.isConnected());
}
}
I need to send commands (data) only when connected to receive response.
I need to set the connected status to false when not connected
and to true when connected.
Based on connected status i will read from socket or write to socket steams.
I need to know when the connection is failed
and when the connection is available.
I think better to use propertychangelistener when connected property is changed.
is it right?
This loop really has no point.
while (!status.isConnected()) {
socket = new Socket(ip, port);
status.setConnected(true);
}
Whether it succeeds or fails it can never execute the loop more than once. It has exactly the same effect as just this:
socket = new Socket(ip, port);
status.setConnected(true);
The run will call this twice with a 1 second delay unless it doesn't throw an exception and succeeds. If you want it to keep trying until you connect, you need to catch the exception within the loop. eg
Socket s = new Socket();
SocketAddress sa = new InetSocketAddress("192.166.102.201", 1986);
while (!s.isConnected()) {
try {
s.connect(sa); // try the connection
} catch (IOException ex) {
// ignore we may have to try lots of times
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
// not sure how to handle this, maybe we should just give up.
}
}
}
Update: I had both the sleep and the connect in the same try block which meant it would never sleep but just keep the thread always busy. Moved the sleep to separate block.
I need to develop a Java server which listens on a port on my pc.
Multiple clients (on the same PC) will access that port and the server should invoke a common method (for all clients, like file copying) which I have written in another class.
My input would be a file path through command line from each client on to that port.
It should invoke a thread each time a client accesses the port.
You can use the server socket class from the java.net package for creating a socket which will listen to incoming client connections on that port. On accepting new connections, start a new thread specific to that client which will handle that client while the server can continue to listen for new connections . Put the common method which you want the server to invoke in the run() method of the new thread.
public class server {
public static void main (String[] args)
{
ServerSocket sock = new ServerSocket (6666); // Server Socket which will listen for connections
try{
while(true)
{
new clientThread(sock.accept()).start(); // start a new thread for that client whenever a new request comes in
}
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
finally {
sock.close();
}
}
// Client Thread for handling client requests
private static class clientThread extends Thread {
Socket socket ;
BufferedReader in ;
PrintWriter out;
clientThread(Socket socket) throws IOException
{
this.socket = socket ;
}
public void run()
{
try
{
// create streams to read and write data from the socket
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
// put your server logic code here like reading from and writing to the socket
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
finally {
try {
socket.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
}
}
You can refer to the documentation for further information about the java socket API
All About Sockets - Oracle
i am creating a multiple-client/server app whenever any client disconnects from
my server it just hangs.
how can i set any condition that will tell me print some message whenever
any client disconnects from the server
here is my server code
class ServerThread implements Runnable {
public void run() {
Socket socket = null;
try {
System.out.println("server starting.......");
serverSocket = new ServerSocket(SERVERPORT);
} catch (IOException e) {
e.printStackTrace();
}
while (!Thread.currentThread().isInterrupted()) {
try {
System.out.println("Ready to accept.......");
socket = serverSocket.accept();
System.out.println(" client Connected with ip address =" +socket.getRemoteSocketAddress().toString());
CommunicationThread commThread = new CommunicationThread(socket);
new Thread(commThread).start();
} catch (IOException e) {
e.printStackTrace();
System.out.println("catch block");
}
}
}
}
class CommunicationThread implements Runnable {
private Socket clientSocket;
private BufferedReader input;
public CommunicationThread(Socket clientSocket) {
this.clientSocket = clientSocket;
try {
this.input = new BufferedReader(new InputStreamReader(this.clientSocket.getInputStream()));
} catch (IOException e) {
e.printStackTrace();
}
}
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
String read = input.readLine();
updateConversationHandler.post(new updateUIThread(read));
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
any help will be appreciated
It's not clear whether you mean disconnect because the conversation was over (ie: everything completed successfully) or the disconnect is because of some network problems (or the client canceled the request).
If it's the first case, then it's easy: the protocol you are using (your own, or http, or whatever) is in charge of defining how to determine that a conversation was over. If that situation arises, then you just close the socket.
If it's the second case, then you'd have to have an algorithm in place to determine whether or not the connection must be closed. For instance, by implementing a timeout, or a slow-read threshold. Take a look at the Socket's javadoc for instructions on how to set a timeout.
It's also worth noting that it's fine to create your own servers when you want to practice or learn something, but you'd be better off using an existing solution, like vert.x or a slimmed down version of Wildfly, for instance. The overhead of such servers is very low, nowadays, while still providing very robust networking capabilities.
I have a program running on a server (Server A) which listens on one port for an external connection (from an external server, B), then listens on another port for an internal connection on the same server (Server A). It then passes data from the internal to external connection and back again.
I want to know if there is a way I can detect that the client external was disconnected. I just need one external connection at a time, but I would like to be able to accept a new one if the external client reboots or something like that.
This socket level stuff is all fairly new to me, so if there is a better way of going about this, I'm all ears. The one stipulation is that the client running on Server B must be the one to initiate the connection and the connection must live for as long as possible.
public void handleConnection() {
System.out.println("Waiting for client message...");
try {
SSLSocket extSocket = (SSLSocket) this.externalServerSocket.accept();
ObjectInputStream externalOis = new ObjectInputStream(extSocket.getInputStream());
ObjectOutputStream externalOos = new ObjectOutputStream(extSocket.getOutputStream());
System.out.println("Client connection establisthed");
// Loop here to accept all internal connections
while (true) {
SSLSocket internalSocket = (SSLSocket) this.internalServerSocket.accept();
new ConnectionHandler(externalOis, externalOos, internalSocket);
}
} catch (IOException e) {
System.err.println(e.getMessage());
return;
}
}
class ConnectionHandler implements Runnable {
private SSLSocket internalSocket;
private ObjectOutputStream internalOos;
private ObjectInputStream internalOis;
private ObjectInputStream externalOis;
private ObjectOutputStream externalOos;
public ConnectionHandler(ObjectInputStream externalOis,
ObjectOutputStream externalOos, SSLSocket internalSocket) {
this.internalSocket = internalSocket;
try {
this.internalOis = new ObjectInputStream(this.internalSocket.getInputStream());
this.internalOos = new ObjectOutputStream(this.internalSocket.getOutputStream());
this.externalOis = externalOis;
this.externalOos = externalOos;
} catch (IOException e) {
System.err.println(e.getMessage());
}
new Thread(this).start();
}
#Override
public void run() {
try
{
// process data
Object o = internalOis.readObject();
externalOos.writeObject(o);
Object o2 = externalOis.readObject();
internalOos.writeObject(02);
internalOos.close();
internalOis.close();
this.internalSocket.close();
} catch (IOException e) {
System.err.println(e.getMessage());
} catch (ClassNotFoundException e) {
System.err.println(e.getMessage());
}
}
}
If the client disconnects, readObject() will throw EOFException, and write() will throw an IOException: connection reset. That's all you need.