Given the following code:
Client c1 = new Client();
c1.connect("127.0.0.1",1300);
Connect function:
public void connect(String serverName, int port)
{
try {
Socket socket = new Socket(serverName,port);
connection = new ConnectionProxy(socket);
connection.start();
}
catch(IOException e)
{
e.printStackTrace();
}
}
(ConnectionProxy class extends Thread) :
public class ConnectionProxy extends Thread {
private Socket socket;
private InputStream is;
private OutputStream os;
private StringConsumer client;
public ConnectionProxy(Socket socket)
{
this.socket = socket;
try {
is = socket.getInputStream();
os = socket.getOutputStream();
}
catch(IOException e)
{
e.printStackTrace();
}
}
public void run () {
DataInputStream dis = new DataInputStream(is);
DataOutputStream dos = new DataOutputStream(os);
while (socket != null)
{
try {
String msg = dis.readUTF();
System.out.println(msg);
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
I'm trying to implement a chat and I'm finding it difficult to send a message written by a client to all of the currently connected clients.
How could I do that? Should I hold the reference for each object (like c1) on the server side, or should I hold that ConnectionProxy thread on the server side?
If not, how do I implement that correctly and efficiently?
Would love to get some help!
Thanks!
Without being given much code, I'll outline what you'd want to do to achieve your goal.
On your server:
Keep an array or something similar of all connected client objects
Implement a send() function in your client class
Implement a broadcast() function that loops through the client list and sends each of them the message (using the aforementioned send() function
Make sure to keep track of (and remove) any dead/disconnected clients from your list, otherwise you'll run into trouble trying to send to them.
On your client:
Make sure you send a "connection terminated" message when you close/disconnect to tell the server you're leaving (makes it easier for the server to remove you)
The server should create a new client handler thread for each incoming connection.
For example, on the server side try something like:
ServerSocket server = new ServerSocket(port);
while (true) {
Socket client = server.accept();
//add incoming client to connected clients vector.
HandleClient c = new HandleClient(client);
clients.add(c);
}
After creating and storing clients in your vector of clients, you can the implement on the HandleClient class run() method a bufferReader (again not a must) to get your client text
Related
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 trying to improve the speed at which the sockets transfer information but i am unsure how to do so. the pourpose of the code is to transfer a number, the date, and a short xml which is being sent in the form of a string.
this is the server code
import java.net.*;
import java.io.*;
public class SSocket extends Thread
{
private ServerSocket serverSocket;
public SSocket(int port) throws IOException
{
serverSocket = new ServerSocket(port);
serverSocket.setSoTimeout(100000);
}
public void run()
{
System.out.println("Waiting for client on port " + serverSocket.getLocalPort() + "...");
while(true)
{
try
{
Socket server = serverSocket.accept();
DataInputStream in = new DataInputStream(server.getInputStream());
int cor=in.readInt();
int i=0;
String transaccion = in.readUTF();
String fecha = in.readUTF();
System.out.println(cor);
System.out.println(transaccion);
System.out.println(fecha);
DataOutputStream out =
new DataOutputStream(server.getOutputStream());
if(transaccion!=null && fecha != null && cor>0){
out.writeInt(cor);
}
else {
out.writeInt(-1);
}
if (i==100){
out.flush();
i=0;
}
i++;
server.close();
}catch(SocketTimeoutException s)
{
System.out.println("Socket timed out!");
break;
}catch(IOException e)
{
e.printStackTrace();
break;
}
}
}
public static void main(String [] args)
{
int port = 1337;
try
{
Thread t = new SSocket(port);
t.start();
}catch(IOException e)
{
e.printStackTrace();
}
}
}
the code for the client is
import java.net.*;
import java.io.*;
public class ClientSocket
{
public static void send(int correl, String transaccion, String fecha)
{
String serverName = "localhost";
int port = 1337;
try
{
Socket client = new Socket(serverName, port);
int i=0;
OutputStream outToServer = client.getOutputStream();
DataOutputStream out =
new DataOutputStream(outToServer);
out.writeInt(correl);
out.writeUTF(transaccion);
out.writeUTF(fecha);
InputStream inFromServer = client.getInputStream();
DataInputStream in =
new DataInputStream(inFromServer);
int corin=in.readInt();
if(corin>0){
Envio.updater(corin);
}
else {
}
if (i==100){
out.flush();
i=0;
}
i++;
client.close();
}catch(IOException e)
{
e.printStackTrace();
}
}
}
i have done some reading on the mater and it seems that posible solutions are to use either a buffer or swich to a datagram. however my experience on working with sockets is rather limited and i am unsure which would be best to use for this situation or if there is another option i havent yet considered. this code will be moving many transactions and i wish to do it in as short time as posible.
thanks in advance
ps. sorry for my bad english it is not my first language
Datagrams imply UDP, which is an unreliable delivery protocol so you're not guaranteed to get all content. That's probably not what you want; I'd stay with plain Sockets (which use TCP, which has reliable delivery).
Will the same client be calling send() repeatedly and connecting to the same server each time? That is, will there be many messages going across a single connection, or will each message be to a different server, with only a single message (or only a few) going to each of the many servers? If there's just one server that a client is going to connect to and if a given client is going to send lots of messages, you should keep the Socket open between send() calls; setting up and tearing down Sockets is expensive, so you're paying a high price for making a new connection each time.
Also, your server appears to only be able to handle a single connection at a time: you accept a connection, read from it, and then close it and accept a new one. So to make this work for more than one client, you'll need to separate the logic for accepting connections onto a different thread from the logic that reads data. If you'll only have a few clients at a time, you can just start a new thread to read from each socket as you create it for a new client; if you'll have lots of clients (thousands), you'll probably need to look at NIO for its ability to service multiple sockets from a single thread. But I suspect you're a long way from having that problem, if you ever do, so I'd just spawn a new thread for each socket.
i'm trying create "multi-client -- single server" connection.
My client(s) opens connection and in the server side I've create
Client clt = new Client("127.0.0.1", 9000);
clt.openConn();
...
public Client(String serverAddress, int serverPort) {
this.serverAddress = serverAddress;
this.serverPort = serverPort;
}
try {
this.clientSocket = new Socket(this.serverAddress, this.serverPort);
this.clientSocket.setKeepAlive(true);
this.clientSocket.setSoTimeout(0);
oos = new DataOutputStream(this.clientSocket.getOutputStream());
ois = new DataInputStream(this.clientSocket.getInputStream());...}
...
on the server side i've created ListArray of ServerSocket's each onf them I wrapped on the Thread.
ServerSocket serverSocket = null ;
Socket clientSocket;
boolean listening = true;
ArrayList threadList = new ArrayList();
Iterator itSrvThr;
try {
serverSocket = new ServerSocket(port);
} catch (IOException e) {
System.err.println("Could not listen on port: " + port + ".");
System.exit(-1);
}
while (listening) {
clientSocket = serverSocket.accept();
ServerThread srvThread = new ServerThread(clientSocket);
srvThread.start();
`...`
}
where
ServerThread extends Thread
{...
public void run() {
this.ois = new DataInputStream(socket.getInputStream());
this.oos = new DataOutputStream(socket.getOutputStream());
}
}
my program send and receive objects(i've called them "Datagramm") which are some kind of wrappers for file and strings (let us say it is some language for client-server)
And now about problem which I have. I must to make verification every time when need to test for "alive" socket from server side...
i'm trying to make this verification when appears new element in the ArrayList in that moment but it brings me problem with "Datagramm's" sending
itSrvThr = threadList.iterator();
while (itSrvThr.hasNext()) {
ServerThread st = (ServerThread) itSrvThr.next();
boolean stoppedSocket = st.getStopped();
if (stoppedSocket) {
st.stop();
itSrvThr.remove();
}else {??? resolution???}
stoppedSocket - it's a value which significate programly turned off socket from client site.
Honestly, i'm working with sockets and threads only a couple weeks, that is why every help and critics will be acceptable.
...
Thank for answer but I have problems with codding of heartbeats. First of them where exactly the place of heartbeat must be placed on the server side.
I suggest you send a heartbeat message from the client and/or the server whenever you haven't sent a message for a while (seconds) The other end can timeout when you haven't recieved anything for some multiple of this time.
If you have a protocol like {message length} {message} I use a message-length=0 as a heartbeat.
I have a server that wait in a loop for clients to connect. Once a client connect a new thread is created to handle that client requests. The server and the client connect with each other easily, but the problem I have with that thread is that it doesn't seem to read the object that the client send to the pipe. I've checked everywhere but can't seem to find the problem.
The server code:
public class Server
{
private ServerSocket server;
public Server(int port) throws IOException
{
//Port 9367
this.server = new ServerSocket(port);
this.server.setReuseAddress(true);
}
public void start() throws IOException
{
System.out.println("Waiting for client...");
while(true)
{
new Thread(new ClientRequestManager(server.accept())).start();
System.out.println("client found !");
}
}
}
ClientRequestManager code:
public void run()
{
try {
ObjectInputStream objectInput = new ObjectInputStream(clientSocket.getInputStream());
System.out.println("Waiting for request...");
while(true)
{
DataRequest request = (DataRequest)objectInput.readObject();
if(request instanceof TestDataRequest)
{
new Thread(new TestEntityManager((TestDataRequest)request, this.clientSocket)).start();
System.out.println("Client dispatched to the test entity manager !");
}
System.out.println("Can't find the right entity manager !");
}
} catch (Exception e) { }
}
The server seem to get stuck here: DataRequest request = (DataRequest)objectInput.readObject();
Here's the basic code I've written for the client to test the server:
//TestDataRequest inherit DataRequest
TestDataRequest request = new TestDataRequest();
request.setID(30);
request.setDescription("test");
Socket serverSocket = new Socket("localhost",9367);
ObjectOutputStream clientOutputStream = new ObjectOutputStream(serverSocket.getOutputStream());
System.out.println("Sending data...");
clientOutputStream.writeObject(request);
clientOutputStream.flush();
System.out.println("Data send !");
I don't get any error, the thread just block. I suppose it's waiting for object to be written to the pipe, like it should be, but it's still blocking when a client write an object to the pipe. I don't understand why. The object implements serializable... The server and the client seem to be connected to each other and writing/reading to the same pipe...
The server: addr=/127.0.0.1,port=49654,localport=9367
The client: addr=localhost/127.0.0.1,port=9367,localport=49654
Can somebody please explain to me what I'm doing wrong ?
I have a chat program. Now the code works for communicate between client and server via command line. But it gives an exception (java.net.SocketException: Socket is closed) while running. Please help me to fix that problem.
In a java chat program,how will the communication be implemented between client and server?
ie.
client<-->server (between server and client)
or
client A<-->server<-->client B (server act as a bridge between two clients)
Is the 2 way communication can be implemented through a single socket?
Are there any other methods ?
How to communicate more than one client simultaneously?
server code
class Server
{
ServerSocket server;
Socket client;
public Server()
{
try
{
server = new ServerSocket(2000);
System.out.println("\tServer Started..........");
while (true)
{
client = server.accept();
Send objsend = new Send(client);
Recive objrecive = new Recive(client);
//client.close();
}
}
catch (Exception e)
{
System.out.println("Exception4 " + e);
}
}
public static void main(String arg[])
{
new Server();
}
}
class Recive implements Runnable
{
Socket client;
public Recive(Socket client1)
{
client=client1;
Thread trsend=new Thread(this);
trsend.start();
}
public void run()
{
ObjectInputStream ois;
Message M=new Message();
try
{
ois = new ObjectInputStream(client.getInputStream());
M = (Message)ois.readObject();
M.display();
ois.close();
}
catch (Exception e)
{
System.out.println("Exception1 " + e);
}
}
}
class Send implements Runnable
{
Socket client;
public Send(Socket client1)
{
client=client1;
Thread trrecive=new Thread(this);
trrecive.start();
}
public void run()
{
Message M=new Message();
InputStreamReader isr=new InputStreamReader(System.in);
BufferedReader br=new BufferedReader(isr);
try
{
System.out.println("Me(server)");
M.strmessage=br.readLine();
ObjectOutputStream oos=new ObjectOutputStream(cli ent.getOutputStream());
oos.writeObject((Message)M);
oos.flush();
oos.close();
}
catch (Exception e)
{
System.out.println("Exception " + e);
}
}
}
client code
class Client
{
public static void main(String arg[])
{
try
{
Send objsend=new Send();
Recive objrecive=new Recive();
}
catch(Exception e)
{
System.out.println("Exception "+e);
}
}
}
class Send implements Runnable
{
public Send()
{
Thread trsend=new Thread(this);
trsend.start();
}
public void run()
{
try
{
Message M=new Message();
InputStreamReader isr=new InputStreamReader(System.in);
BufferedReader br=new BufferedReader(isr);
while(true)
{
System.out.println("Me(client)");
M.strmessage=br.readLine();
Socket client=new Socket("localhost",2000);
ObjectOutputStream oos=new ObjectOutputStream(client.getOutputStream());
oos.writeObject((Message)M);
oos.flush();
oos.close();
}
}
catch(Exception e)
{
System.out.println("Exception "+e);
}
}
}
class Recive implements Runnable
{
public Recive()
{
Thread trrecive=new Thread(this);
trrecive.start();
}
public void run()
{
try
{
while(true)
{
Socket client=new Socket("localhost",2000);
ObjectInputStream ois=new ObjectInputStream(client.getInputStream());
Message CNE=(Message)ois.readObject();
CNE.display();
ois.close();
}
}
catch(Exception e)
{
System.out.println("Exception "+e);
}
}
}
First of all, don't close the streams in every run().
Secondly, check whether port for server which you are using is free.
This program makes your pc both host and server.
import java.io.IOException;
import java.net.*;
public class ClientServer {
static byte[] buffer = new byte[100];
private static void runClient() throws IOException {
byte buffer[] = new byte[100];
InetAddress address = InetAddress.getLocalHost();
DatagramSocket ds=new DatagramSocket();
int pos = 0;
while (pos<buffer.length) {
int c = System.in.read();
buffer[pos++]=(byte)c;
if ((char)c =='\n')
break;
}
System.out.println("Sending " + pos + " bytes");
ds.send(new DatagramPacket(buffer, pos, address, 3000));
}
private static void runServer() throws IOException {
InetAddress address = InetAddress.getLocalHost();
DatagramSocket ds = new DatagramSocket(3000, address);
DatagramPacket dp = new DatagramPacket(buffer, buffer.length);
ds.receive(dp);
String s=new String(dp.getData(),0,dp.getLength());
System.out.print(s);
}
public static void main(String args[]) throws IOException {
if (args.length == 1) {
runClient();
} else {
runServer();
}
}
}
also follow this link
There could be multiple places where the exception could be thrown. Without a stack trace it is difficult to state so accurately, as to the cause of failure.
But the root cause, is essentially due to the fact that you are closing the InputStream of the socket in your Receiver threads after reading a message, and closing the OutputStream of the socket in your Sender threads after sending a message. Closing either of these streams will automatically close the socket, so you if attempt to perform any further operation on it, a SocketException will be thrown.
If you need to ensure that your server and client do not shutdown in such an abrupt manner, you'll have to keep reading the InputStream (until you get a special message to shutdown, for instance). At the same time, you'll also have to keep writing to the OutputStream. Two-way communication is definitely possible, and the posted code is capable of the same (if the socket remains open).
If you have to handle multiple clients, you'll need multiple reader and writer threads on the server, each listening on an instance of a Socket returned from ServerSocket.accept(); in simpler words, you need a reader-writer pair listening on a distinct socket on the server for each client. At the moment, multiple clients can connect to the Server, as each incoming connection is provided its own client Socket object on the Server, that is provided to individual reader and writer threads. The main Server thread can continue to receive incoming connections and delegate the actual work to the reader-writer pairs.
chat programms normaly have a server through which all communication goes. The reason is that other wise every client needs to know how to reach every other client. And that doesn't work in the general case.
So you'll have a server, every client registers and talks with the server, which will forward messages to other clients.
Mostly communication is done via HTTP cause this is likely to go through firewalls and proxies. You probably want to read up on long polling if you are planning for anything serious.