i want to connect morethan one client at a time to the server and also communicate server to all the clients.
how server recognize each client. and how to send data to a particular client?
consider , there are 3 clients A,B,C. all the clients are connected to the server. the server wants to send message to B. how its done ?
If i understand you right - all you need is not bind socket for one connection.
Your client code will looks like that:
Client class:
public class TCPClient {
public TCPClient(String host, int port) {
try {
clientSocket = new Socket(host, port);
} catch (IOException e) {
System.out.println(" Could not connect on port: " + port + " to " + host);
}
}
Server(host) class:
public class TCPListener {
public TCPListener(int portNumber) {
try {
serverSocket = new ServerSocket(portNumber);
} catch (IOException e) {
System.out.println("Could not listen on port: " + portNumber);
}
System.out.println("TCPListener created!");
System.out.println("Connection accepted");
try {
while (true) {
Socket clientConnection = serverSocket.accept();
//every time client's class constructor called - line above will be executed and new connection saved into Socket class.
}
} catch (Exception e) {
e.printStackTrace();
}
}
That is simplest example. More can be found here:
http://www.oracle.com/technetwork/java/socket-140484.html
Related
I have written a client to run on an android device (android 6) and when the server is up and running it connects, however when the server is down the socket() call should throw an exception however it doesn't.
I originally tried it using the NDK and ran into a very similar issue (Android NDK socket connect() returning 0 when it should fail whilst on 3g).
I am assuming this is a bug with android at this point but any insight into a solution or work around would be much appreciated.
The code in question:
public class Client implements Runnable{
private Socket socket;
private InetAddress IP;
private int port;
public Client(int port){
try {
this.IP = InetAddress.getByName(server ip);
}
catch(UnknownHostException e){
Log.d("App1", "Unknown Host, connection failed");
System.exit(1);
}
this.port = port;
Log.d("App1", "initialised");
}
#Override
public void run(){
try {
this.socket = new Socket(this.IP, this.port);
Log.d("FiX1", "Connected");
listen();
}
catch(IOException e){
Log.d("FiX1,","connection failed");
System.exit(1);
}
finally
{
try{
socket.close(); // dispose
}
catch(IOException e){
System.exit(1);
}
}
}
public void listen() {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while (true) {
String cominginText = "";
try {
cominginText = in.readLine();
Log.d("FiX1",cominginText);
} catch (IOException e) {
//error ("System: " + "Connection to server lost!");
System.exit(1);
break;
}
}
} catch (IOException e) {
System.exit(1);
}
}
}
The best solution I could find was to manually send an acknowledgement from the server that a connection had been made, the client would retry the connection if it did not receive this message within a certain time after it claimed to have connected.
There is a difference between a TCP connection "close" vs "disconnect".
If you close the socket connection from server using socket.close() then you will get exception in client side, if you try to read from that connection or vice versa.
However, if one side just disappears(shut down the program) then the other side has no way of knowing that. So the other side will wait for response for read call.
The TCP protocol was designed to be reliable in hostile communication environments and it will not normally decide a connection is closed just because it has not heard from the other side for a while.
I'm trying to write simple server-client chat solution. For test purposes, I'm creating an array of 2 serverThreads, which are responsible for sending and receiving messages from the clients connected.
I'd like a server to reject a connections after the number of connected clients reach a maximum value. However, even though the server do not accept the connection, the socket on client side is created. Methods socket.isBound and isConnected both return true value.
So back to the main question. Do you have any ideas how could I reject the client from connecting when the ServerSocket will not be able to .accept() additional connection?
Here's the code of the Server class.
public class Server {
private ServerSocket serverSocket = null;
private ServerThread serverThread[] = new ServerThread[2];
protected volatile int clientCount = 0;
public Server (int port){
try {
System.out.println("Binding to port " + port + " ...");
serverSocket = new ServerSocket (port);
System.out.println("Binded to port " + port + ".");
} catch (IOException e) {
System.out.println("Failed binding to the port: " + e.getMessage());
}
}
public void addThread (Socket socket){
System.out.println ("Client connected at socket: " + socket);
serverThread[clientCount] = new ServerThread (this, socket);
try {
serverThread[clientCount].open();
serverThread[clientCount].start();
} catch (IOException e) {e.getMessage();}
}
public void waitForClient () {
boolean isLogPrinted = false;
while (true){
try {
if (clientCount < serverThread.length){
System.out.println ("Waiting for connection...");
isLogPrinted = false;
addThread (serverSocket.accept());
clientCount++;
System.out.println("Client count: " + clientCount);
}
else {
if (!isLogPrinted){
System.out.println("MAXIMUM NUMBER OF CLIENTS REACHED! (" + clientCount + ").");
isLogPrinted = true;
}
}
} catch (IOException e) {
System.out.println("Error while waiting for new clients to connect: " + e.getMessage());
}
}
}
public synchronized void broadcastMessages (String msg){
for (int i = 0; i < clientCount; i++)
serverThread[i].sendMessage(msg);
}
public static void main (String args[]){
Server server = new Server (4200);
server.waitForClient();
}
}
I'd like a server to reject a connections after the number of connected clients reach a maximum value.
Close the server socket.
However, even though the server do not accept the connection, the socket on client side is created. Methods socket.isBound and isConnected both return true value.
Correct. That's because TCP maintains a 'backlog queue' of incoming connections which have been completed but not yet accepted by the server application.
So back to the main question. Do you have any ideas how could I reject the client from connecting when the ServerSocket will not be able to .accept() additional connection?
Close the server socket while the number of connections is at its maximum.
However due to the backlog this technique can never be perfect. There is no perfect solution. You could have the server immediately close excess connections, but the excess clients won't detect that until they try to send something. If you need perfection you will probably have to introduce an application protocol whereby the server sends something like 'ACCEPTED' or 'REJECTED' accordingly.
Instead of while true in you waitForClient method try this
private final int allowedClients = 10;
private int connectedClients = 0;
public void waitForClient () {
boolean isLogPrinted = false;
while (connectedClients <= allowedClients){
try {
if (clientCount < serverThread.length){
System.out.println ("Waiting for connection...");
isLogPrinted = false;
addThread (serverSocket.accept());
connectedClients++;
System.out.println("Client count: " + clientCount);
}
else {
if (!isLogPrinted){
System.out.println("MAXIMUM NUMBER OF CLIENTS REACHED! (" + clientCount + ").");
isLogPrinted = true;
}
}
} catch (IOException e) {
System.out.println("Error while waiting for new clients to connect: " + e.getMessage());
}
}
}
I know this is very late to answer, but I think it will help many.
You can check for the existing socket if any by below code.
SocketAddress socketAddress = new InetSocketAddress("localhost", 8091);
Socket socket = new Socket();
ServerSocket serverSocket = null;
try {
socket.connect(socketAddress);
} catch (IOException e) {
e.printStackTrace();
}
if(socket == null) {
try {
serverSocket = new ServerSocket(8091);
} catch (IOException e) {
e.printStackTrace();
}
}
if not found a active socket on the same port and IP then it will start a new server socket or you can change it start socket only else you can connect to the existing socket.
I will post my code below, a little background.
I am trying to connect to a gameserver on port 9339. my local port changes each time. The aim is to pass the packets through the proxy and display the info in the command line.
The client connects to the remote host using bluestacks which is running the game.
Code:
import java.io.*;
import java.net.*;
public class proxy {
public static void main(String[] args) throws IOException {
try {
String host = "gamea.clashofclans.com";
int remoteport = 9339;
ServerSocket ss = new ServerSocket(0);
int localport = ss.getLocalPort();
ss.setReuseAddress(true);
// Print a start-up message
System.out.println("Starting proxy for " + host + ":" + remoteport
+ " on port " + localport);
// And start running the server
runServer(host, remoteport, localport,ss); // never returns
System.out.println("Started proxy!");
} catch (Exception e) {
System.err.println(e);
}
}
/**
* runs a single-threaded proxy server on
* the specified local port. It never returns.
*/
public static void runServer(String host, int remoteport, int localport, ServerSocket ss)
throws IOException {
final byte[] request = new byte[2048];
byte[] reply = new byte[4096];
while (true) {
Socket client = null, server = null;
try {
// Wait for a connection on the local port
client = ss.accept();
System.out.println("Client Accepted!");
final InputStream streamFromClient = client.getInputStream();
final OutputStream streamToClient = client.getOutputStream();
// Make a connection to the real server.
// If we cannot connect to the server, send an error to the
// client, disconnect, and continue waiting for connections.
try {
server = new Socket(host, remoteport);
System.out.println("Client connected to server.");
} catch (IOException e) {
PrintWriter out = new PrintWriter(streamToClient);
out.print("Proxy server cannot connect to " + host + ":"
+ remoteport + ":\n" + e + "\n");
out.flush();
client.close();
System.out.println("Client disconnected");
continue;
}
// Get server streams.
final InputStream streamFromServer = server.getInputStream();
final OutputStream streamToServer = server.getOutputStream();
// a thread to read the client's requests and pass them
// to the server. A separate thread for asynchronous.
Thread t = new Thread() {
public void run() {
int bytesRead;
try {
while ((bytesRead = streamFromClient.read(request)) != -1) {
streamToServer.write(request, 0, bytesRead);
streamToServer.flush();
}
} catch (IOException e) {
}
// the client closed the connection to us, so close our
// connection to the server.
try {
streamToServer.close();
} catch (IOException e) {
}
}
};
// Start the client-to-server request thread running
t.start();
// Read the server's responses
// and pass them back to the client.
int bytesRead;
try {
while ((bytesRead = streamFromServer.read(reply)) != -1) {
streamToClient.write(reply, 0, bytesRead);
streamToClient.flush();
}
} catch (IOException e) {
}
// The server closed its connection to us, so we close our
// connection to our client.
streamToClient.close();
} catch (IOException e) {
System.err.println(e);
} finally {
try {
if (server != null)
server.close();
if (client != null)
client.close();
} catch (IOException e) {
}
}
}
}
}
Basically the last thing that is printed out is "Starting proxy for gamea.clashofclans.com:9339 on port (whatever it chose).
Hopefully someone can help me.
I have this problem too, I don`t have enough time to correct this but i think using thread is that is why all mistake.
check your proxy for working on browser setting( May be proxy had problem)
If not,
I suggest to don`t use thread. maybe mutual exclusion occurs.
Your code is correct.It is working fine so you don't need any fix. What is happening is , your serverSocket in your proxy class is waiting for client to connect. that's why it is not going forward. What you need to do is, create a client and connect to it.
follow the step :
run your proxy.
then run your client
for the client, you can use this code,
public static void main(String[] args) throws IOException {
try {
int remoteport = 9339;
String host="127.0.0.1";
makeConnection(host, remoteport);
System.out.println("connection successful!");
} catch (Exception e) {
System.err.println(e);
}
}
public static void makeConnection(String host, int remoteport) throws IOException {
while (true) {
Socket client = null;
try {
client = new Socket(host, remoteport);
System.out.println("Client connected to server.");
break;
} catch (IOException e) {
System.err.println(e);
} finally {
if (client != null)
client.close();
if (client != null)
client.close();
}
}
}
i am developing web application and i host it in tomcat server. my requirement is client system wants to know the ip address of the system where the tomcat server located in a network.Before make any request to the server using java.or any possible to set default ip address for the tomcat server.and how can i use the default ip address to make a request if system ip and tomcat ip are different.
I don't know if I understood your question right. So the server is running in a local area network and your client software does not know which address/ip to connect to? You could add a multicast server to your servers app and a multicast receiver to your clients. The server will send a boardcast packet frequently to a specified boardcast address/channel, i.e. 203.0.113.0.
Once your client starts, it will receive the boardcast packet send by the server, as long as he is connected to the same channel. The packet is containing the servers address. You can than use that address to connect to the server.
Update
This is a very simplyfied example of a sender, receiver and a constants class to share the settings. It sends a String (Server is here) as packet data, but in a real world application, you should create an object serialize it at the server and deserialize it at the client. That object could hold more information about the server an could be verified at client side.
Server/Client side shared code:
public final class MulticastConstants {
public static final String MULTICAST_PACKET_DATA = "Server is here!";
public static final String MULTICAST_CHANNEL = "230.0.0.1";
public static final int MULTICAST_PORT = 8881;
public static final int MULTICAST_PACKET_SIZE = MULTICAST_PACKET_DATA.getBytes().length;
}
Server Side code:
The sender is a WebListener and will start and stop with your application.
#WebListener
public class MulticastSender implements ServletContextListener {
private MulticastSocket socket;
private boolean running = true;
private Thread mcss;
public MulticastSender() {
System.out.println("New " + this.getClass().getSimpleName());
try {
socket = new MulticastSocket(MulticastConstants.MULTICAST_PORT);
mcss = new MulticastServerThread();
} catch (IOException e) {
System.out.println("Error creating MulticastSender: " + e.getMessage());
}
}
#Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("Starting " + this.getClass().getSimpleName());
mcss.start();
}
#Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("Stopping " + this.getClass().getSimpleName());
this.running = false;
socket.disconnect();
socket.close();
}
private class MulticastServerThread extends Thread {
public MulticastServerThread() {
super("MulticastServer");
}
public void run() {
System.out.println("Start sending multicast packets ...");
while (running) {
System.out.println("Sending multicast packet ...");
try {
byte[] dataBuffer = MulticastConstants.MULTICAST_PACKET_DATA.getBytes();
InetAddress group = InetAddress.getByName(MulticastConstants.MULTICAST_CHANNEL);
DatagramPacket packet = new DatagramPacket(dataBuffer, dataBuffer.length, group, MulticastConstants.MULTICAST_PORT);
socket.send(packet);
System.out.println("Packet send ...");
try {
sleep(2000);
} catch (InterruptedException e) {
}
} catch (IOException e) {
System.out.println("Error sending multicast packet: " + e.getMessage());
running = false;
break;
}
}
socket.close();
}
}
}
Client side code:
The client only receives a single packet for simplicity. You might create a thread to not to freeze your clients gui.
public class MulticastReceiver {
private MulticastSocket socket;
private InetAddress address;
public static void main(String[] args) throws InterruptedException {
new MulticastReceiver();
}
public MulticastReceiver() {
System.out.println("Starting MulticastReceiver ...");
try {
address = InetAddress.getByName(MulticastConstants.MULTICAST_CHANNEL);
socket = new MulticastSocket(MulticastConstants.MULTICAST_PORT);
socket.joinGroup(address);
DatagramPacket packet;
try {
byte[] buf = new byte[MulticastConstants.MULTICAST_PACKET_SIZE];
packet = new DatagramPacket(buf, buf.length);
System.out.println("Waiting for packets ...");
socket.receive(packet);
System.out.println("Received a packet (" + packet.getLength() + " bytes) ...");
// deserialize packet.getData() to your own object (for simplicity a String is used) ...
// check if type and serialVersionId are ok, otherwise dispose packet ...
System.out.println("Server is located at: " + packet.getAddress());
socket.close();
// connect to server ...
} catch (IOException ex) {
ex.printStackTrace();
} catch (Exception ex) {
ex.printStackTrace();
}
} catch (UnknownHostException e) {
System.out.println("Could not connect to host \"" + address + "\": " + e.getMessage());
} catch (Exception e) {
System.out.println("Error initializing: " + e.getMessage());
}
}
}
Tested on Glassfish 4, hope that helps.
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.