Sending data to sockets in an arraylist of Sockets - java

I have made a chat server that my clients can connect to but the clients don't get the messages the other sent. This is the code that does it all. Sending and receiving and setting up output streams.
public void run()
{
while(true)
{
for(int i = 0; i < ClientConnector.Connections.size(); i++)
{
try
{
if(Socket != null)
{
ObjectOutputStream Output = new ObjectOutputStream(Socket.getOutputStream());
ObjectInputStream Input = new ObjectInputStream(Socket.getInputStream());
whileChatting(Input, Output);
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
public static void sendMessage(String message, String returnedMessage, ObjectOutputStream out)
{
try
{
System.out.println("[Server] " + message);
if(!message.isEmpty())
{
out.writeObject("\247c[Server]\247d " + message);
out.flush();
System.out.println("[Chat] Sent: " + message);
}
else
{
out.writeObject(returnedMessage);
System.out.println("[Chat] Sent: " + returnedMessage);
}
out.flush();
System.out.println("[Info] Flushing remaining data to stream.");
}
catch(IOException ioException)
{
System.out.println("[Warning] Error: ioException # sendMessage line 76.");
}
}
public static void whileChatting(ObjectInputStream input, ObjectOutputStream output) throws IOException
{
String message = "";
do
{
try
{
message = (String) input.readObject();
System.out.println(message);
sendMessage("", message, output);
}
catch(ClassNotFoundException classNotFoundException)
{
System.out.println("[Warning] Error: ClassNotFoundException # whileChatting line 1-7.");
System.out.println("idk wtf that user sent!");
}
}while(!message.equals("/stop"));
}
I am wondering. How would i make this send what one person sends to all the clients? I keep a list of sockets in an array list of sockets. That looks like this.
public static ArrayList<Socket> Connections = new ArrayList<Socket>();
As each client connects it stores their Socket it this list. If there is a better way of doing this then please let me know.

If these are remote clients, then a MulticastSocket might do the trick. If these are local clients, then a publish/subscribe messaging service like HornetQ would work (clients subscribe to the message queue, and HornetQ takes care of the routing).

I don't see the point of the loop, when you don't make any use of the iteration variable. Surely you should be sending to ClientConnector.Connections.get(i)?
Another problem here is that you are creating a new ObjectInputStream and ObjectOutputStream on every iteration. That won't work. You must use the same pair of those streams per socket for the life of each socket, at both ends.

Related

Sending and receiving TCP simuntainously

I'm trying to create a TCP client/server that sends and receives messages. My problem right now is that I can't do them both simultaneously. I'm sending a message to the server and reading it just fine, but after each received message to the server, I also want to send back a response to the client acknowledging it.
I'm sending several messages per second to the server, but when I try to re-send a message to the client, it just gets stuck, no message on either end. I can however send in either direction, client to server and server to client, but only one way.
This is the client handler for the server:
public TCPClientHandler(Socket client, int bufferSize) throws IOException {
this.client = client;
messageToClient = new PrintWriter(client.getOutputStream(),true);
recvFromClient = new BufferedReader(new InputStreamReader(client.getInputStream()));
buffer = new byte[bufferSize];
}
#Override
public void run() {
try {
/* Read the data from the client.
* If the message is larger than the server buffer we close the connection.
* If the client closes connection we get exception and we catch it
* at the end.
*/
while (true) {
if (recvFromClient.readLine().getBytes().length > buffer.length){
break;
}
/* Receiving and printing message */
buffer = Arrays.copyOf(recvFromClient.readLine().getBytes(),
recvFromClient.readLine().getBytes().length);
String messageFromClient = new String(buffer,StandardCharsets.UTF_8);
System.out.println("Client message: " + messageFromClient);
messageToClient.println();
/* Sending message to client */
}
} catch (IOException e) {
System.out.println("Connection to client lost...");
} finally {
System.out.println("Connection closed on thread " + Thread.currentThread().getName());
messageToClient.close();
try {
recvFromClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
This is the client:
public class TCPEchoClient {
/*
Args input
1. Server Address
2. Server Port
3. Socket Buff Size
4. Transfer Rate
5. Message
*/
public void run(String args[]){
try {
// Dummy values
InetAddress host = InetAddress.getByName("localhost");
int serverPort = 4950;
int buffSize = 100;
int transferRate = 5;
String echoMessage = "112312451265214126531456234321";
String receive;
System.out.println("Connection to server on port " + serverPort);
Socket socket = new Socket(host,serverPort);
socket.setReceiveBufferSize(buffSize);
System.out.println("Just connected to " + ocket.getRemoteSocketAddress());
// Writer and Reader to write and read to/from the socket.
PrintWriter writeToServer = new PrintWriter(socket.getOutputStream(),true);
BufferedReader recvFromServer = new BufferedReader(new `InputStreamReader(socket.getInputStream()));`
if (transferRate < 1){
writeToServer.println(echoMessage);
}else {
// Continuously send messages with 1 second between x amount of
// messages, until client is aborted.
while (true) {
for (int i = 0; i < transferRate; i++) {
writeToServer.println(echoMessage);
receive = new String(recvFromServer.readLine().getBytes(), StandardCharsets.UTF_8);
System.out.println(receive);
}
Thread.sleep(1000);
}
}
// Close reader/writer and socket
writeToServer.close();
recvFromServer.close();
socket.close();
} catch (SocketException e){
System.out.println("Socket exception...");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
TCPEchoClient client = new TCPEchoClient();
client.run(args);
}
}
I would like to read the messages that are transmitted as bytes, store them in the buffer, and THEN read the message, but so far no success.
Fixed the issue. I moved the receive part inside the client to AFTER the thread sleep.

simple multi-threaded server chat using java

I'm creating a java chat server that handles multi clients I use this simple code for server
public class Server extends Thread {
ServerSocket serverSocket = null;
Socket socket = null;
private int unique_id;
ArrayList<Clients> cl;
public Server(int port) {
try {
serverSocket = new ServerSocket(port);
cl = new ArrayList<>();
this.start();
} catch (Exception e){
System.out.println("Error 5");
e.printStackTrace();
}
}
#Override
public void run(){
System.out.println("Server Start");
while (true){
try {
socket = serverSocket.accept();
Clients t = new Clients(socket); // add it to thread
cl.add(t);
t.start();
System.out.println("Connected " + String.valueOf(cl.size())); // printed ok
}catch (Exception e){
System.out.println("Error 4");
e.printStackTrace();
}
}
}
public synchronized void SendToAll(String s){ // this function used by client when one of client socket send a message then server send it to all
System.out.println("Sended is excuted"); // excuted normal each time i send a message from client but not send to all
for (int i = 0; i < cl.size(); i++){
cl.get(i).WriteToSocket(s);
}
}
public static void main(String args[]){
int port = 5002;
Server server = new Server(port); // start server
//server.run(); // start connections wait for it
}
class Clients extends Thread { // class extends thread
public Socket socket = null;
DataInputStream input = null; // read input
DataOutputStream output = null; // read output
public int myid = 0; // unique id for each client
public Clients(Socket soc) {
socket = soc;
try {
input = new DataInputStream(socket.getInputStream());
output = new DataOutputStream(socket.getOutputStream());
myid = ++unique_id;
System.out.println("Client Start Thread"); // printed ok !
} catch (IOException e){
System.out.println("Error 1");
e.printStackTrace();
}
}
public void WriteToSocket(String s) { // used to write a message to this socket
try {
output.write(s.getBytes());
}catch (IOException e){
System.out.println("Error 2");
e.printStackTrace();
}
}
#Override
public void run() { // run thread function wait for messages from clients
while (true){
try {
String s = input.readLine();
if (s.contains("quite")) {
socket.close();
input.close();
output.close();
cl.remove(this);
this.stop();
}
if (!s.isEmpty()) {
SendToAll(s);// when message come and not empty it use server function to send them to all clients
}
}catch (IOException e){
System.out.println("Error 3");
e.printStackTrace();
}
}
}
}
}
everything works fine when clients connect the server accept the connection and the client thread started
but the problem when I sent a message from the client it didn't received by the server I try my client application in java too with Qt c++ server and it works ?
so what did I do wrong here make the server can't receive the message ?
this my first time in network programming using java
Edit
I solve the NullPointerException the problem was that when client log out I didn't remove his socket from the ArrayList solved by making client before close send message contains quite so when I see it i remove his socket from array list Another Quetiosn Here i don't know how this message sentthe System.out.println() that is in the SendToAll function printed to the screen each time client send a message but why the message not send again to all clients ? actually the main problem is that server can't send the message to all clients in the array list after message comes from one client the problem not solved stell found
Client Code class
public class ClientSocket extends Thread {
public Socket socket = null;
public DataInputStream input = null;
public DataOutputStream output = null;
MainChat chat = null;
public ClientSocket(String ip, int port,MainChat ch) {
try {
socket = new Socket(ip,port);
input = new DataInputStream(socket.getInputStream());
output = new DataOutputStream(socket.getOutputStream());
chat = ch;
this.start();
}catch (IOException e){
}
}
#Override
public void run() {
while (true){
try {
String s = input.readLine();
if (!s.isEmpty()){
chat.WriteToScreen(s.trim());
}
}catch (IOException e){
}
}
}
public void WriteToSocket(String s) throws IOException{
output.write(s.getBytes());
}
}
Edit
when i use this code in main the SendToAll function send the message to all clients !! why when i use it from clients class using Thread it not sended to all ?
public static void main(String args[]){
int port = 5002;
Server server = new Server(port); // start server
//server.run(); // start connections wait for it
while (true) {
String s = in.next();
server.SendToAll(s + "\n"); // message sended to all client !!
}
}
The problem is that readLine reads until it finds a line terminator of end of file. This is why it works with other server in QT C++ but not with the Java server.
Please see here:
https://docs.oracle.com/javase/7/docs/api/java/io/DataInput.html#readLine()
https://docs.oracle.com/javase/7/docs/api/java/io/DataInputStream.html#readLine()
Please note that readLine in DataInputStream is deprecated. You should use BufferedReader to read a line (with readLine) as indicated in the DataInputStream link.
So, add '\n' to the end of the string sent and it will work.
I solve the problem, I am sorry for that it was my fault I forget to add \n in sendToAll function so this what cause the problem so no \n the clients can't read the line because I use readLine in DataInputStream
anyway I try another method to read bytes instead of readLine it's I think it's better especially when you receive UTF-8 char and after that changes from bytes to String

How to write a minimalistic Java Client for OpenMQ

Please help an MQ nubee to write his first Java Client, I got a little bit lost in the Oracle docs.
I have OpenMQ up and running.
In the OpenMQ Administration Console I established a broker named "MyFirstTest"
1 of 6 services is "jms" (which seems to be the most easy to use service), this service is up and running, too (saying: Service state running).
So I come to the interesting part.
How do I connect to the broker "MyFirstTest", then to send a message in, and last but least read this message perhaps from a second client.
I think I have to find the already existing queue instead of using
new com.sun.messaging.Queue
Any example or link to is appreciated.
public class HelloWorldMessage {
public static void main(String[] args) {
try {
ConnectionFactory myConnFactory;
Queue myQueue;
myConnFactory = new com.sun.messaging.ConnectionFactory();
Connection myConn = myConnFactory.createConnection();
Session mySess = myConn.createSession(false, Session.AUTO_ACKNOWLEDGE);
myQueue = new com.sun.messaging.Queue("MyFirstTest");
//Create a message producer.
MessageProducer myMsgProducer = mySess.createProducer(myQueue);
//Create and send a message to the queue.
TextMessage myTextMsg = mySess.createTextMessage();
myTextMsg.setText("Hello World");
System.out.println("Sending Message: " + myTextMsg.getText());
myMsgProducer.send(myTextMsg);
//Create a message consumer.
MessageConsumer myMsgConsumer = mySess.createConsumer(myQueue);
//Start the Connection created in step 3.
myConn.start();
//Receive a message from the queue.
Message msg = myMsgConsumer.receive();
//Retreive the contents of the message.
if (msg instanceof TextMessage) {
TextMessage txtMsg = (TextMessage) msg;
System.out.println("Read Message: " + txtMsg.getText());
}
//Close the session and connection resources.
mySess.close();
myConn.close();
} catch (Exception jmse) {
System.out.println("Exception occurred : " + jmse.toString());
jmse.printStackTrace();
}
}
}
//Assuming server supports multiple clients, your client can look like this:
//Ref: http://docs.oracle.com/javase/tutorial/networking/sockets/readingWriting.html
//untested code
class client{
.....
....
private static Socket echoSocket;
//main can be in another class also
public static void main(.... args[]){
client nodeI,nodeII;
nodeI = new client("speaker/sender");
nodeII = new client("listener/recvr");
nodeI.connect2Server();
nodeI.sendMssgInstr2Server(node);
}
public void connect2Server(){
try {
echoSocket = new Socket("<jms.srvr.ip>", <port#>);
} catch (UnknownHostException e) {
System.err.println("Don't know about host: <jms.srvr.ip>.");
System.exit(1);
}
}
public void sendMssgInstr2Server throws IOException (client RecipientClientNodeII){
out = new PrintWriter(echoSocket.getOutputStream(), true);
out.println("sending message:"+mssgQueue.poll() + " =>recipient client is now reading:"+RecipientClientNodeII.receive);
}
public void receive(){
try{
in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
}catch (IOException e) {
System.err.println("Couldn't get I/O for "+"the connection to: <jms.srvr.ip>.");
System.exit(1);
}
while(1)
in.readLine();
}
//other methods
.......
.......
}; //class client ends

getInputStream blocks?

Using Input/Output stream to pass objects between my client and server. I can both send and receive objects with my server, and and now i want the same for the client which as of now only can send. So i gave my client an ObjectInputStream. However, when i initilazie it, it blocks! Been searching around and found answers but no solution.
Please help!
public GameConnection(String strPort, TextArea chat)
{
this.port = Integer.parseInt(strPort);
System.out.println("GameConnection::Constructor(): Connecting on port " + port);
this.chat = chat;
connect = new Connection();
sendObject();
}
public void sendObject()
{
try
{
obj_stream.writeObject(new String("GameServer received a message!"));
}
catch(Exception e){System.out.println("GameConnection::sendObject(): " + e);}
}
protected class Connection extends Thread
{
private boolean alive = true;
public Connection()
{
try
{
socket = new Socket(host, port);
System.out.println("Connected to GAMESERVER" + host + " on port + " + port);
obj_stream = new ObjectOutputStream(socket.getOutputStream());
// Next line BLOCKS!!!
//ObjectInputStream stream = new ObjectInputStream(socket.getInputStream());
}
catch (IOException ioe)
{
System.out.println("Connection::constructor() " + ioe);
Terminate();
}
catch (NullPointerException npe)
{
System.out.println("Connection::constructor() " + npe);;
Terminate();
}
}
I tried using them in different threads but it had the same problem, at least for me :(
yes, this question has been asked many times before. the object stream format has a header, and the ObjectInputStream reads that header on construction. therefore, it is blocking until it receives that header over the socket. assuming your client/server code looks similar, after you construct the ObjectOutputStream, flush it. this will force the header data over the wire.

how to communicate between client and server in java

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.

Categories