Why does this program not work properly? Client reads SOME_MESSAGE and after that nothing happens. It seems that println method from server in some way have influence on transferring long type numbers.
SERVER
import java.net.*;
import java.io.*;
public class Server {
public static void main(String[] args) throws Exception {
ServerSocket socket = new ServerSocket(9999);
while (true) {
Socket sock = socket.accept();
PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(sock.getOutputStream())), true);
DataOutputStream outByte = new DataOutputStream(sock.getOutputStream());
out.println("SOME_MESSAGE");
outByte.writeLong(948L);
}
}
}
CLIENT
import java.net.*;
import java.io.*;
public class Client {
public static void main(String[] args) throws Exception {
Socket sock = new Socket("127.0.0.1", 9999);
DataInputStream inByte = new DataInputStream(sock.getInputStream());
BufferedReader in = new BufferedReader(new InputStreamReader(
sock.getInputStream()));
System.out.println(in.readLine());
long number = inByte.readLong();
System.out.println(number);
}
}
Your problem is that the BufferedReader is buffering bytes from the socket's input stream, so the long 948 value isn't in the DataInputStream because the BufferedReader has it read and is buffering it. In general you don't want to be using 2 different wrappers around the same underlying stream, especially if one is buffered. Same with your Server class, but that seems to at least be working.
Your Client needs to use only one wrapper for the socket's input stream. You should just stick with the DataInputStream and along with the Server code, use DataInputStream.readUTF() on the Client while using DataOutputStream.writeUTF() on the Server, getting rid of both the BufferedReader and the PrintWriter.
So on the Server:
while(true) {
Socket sock = socket.accept();
DataOutputStream outByte = new DataOutputStream(sock.getOutputStream());
outByte.writeUTF("SOME_MESSAGE");
outByte.writeLong(948L);
outByte.flush();
}
and on the Client:
public static void main(String[]args)throws Exception
{
Socket sock = new Socket("127.0.0.1",9999);
DataInputStream inByte = new DataInputStream(sock.getInputStream());
System.out.println(inByte.readUTF());
long number = inByte.readLong();
System.out.println(number);
}
It is interesting that java does not allow to do that having said that there is always a better solution. You can use serialization to do your job.
create a interface PayLoad like below
import java.io.Serializable;
public interface PayLoad extends Serializable
{
String getMessage();
//Java does not allow to define byte array of long
int getLength();
byte[] getbytes();
}
Then create an Implementation class like below
public class FilePayLoad implements PayLoad
{
private final String message;
private final int length;
private final byte[] bytes;
public FilePayLoad(String message, int length, byte[] bytes)
{
this.message = message;
this.length = length;
this.bytes = bytes;
}
#Override
public String getMessage()
{
return this.message;
}
#Override
public int getLength()
{
return this.length;
}
#Override
public byte[] getbytes()
{
return this.bytes;
}
}
Now change your server and client like below
Server
public class Server
{
public static void main(String[] args) throws Exception
{
ServerSocket socket = new ServerSocket(9999);
while (true)
{
Socket sock = socket.accept();
ObjectOutputStream out = new ObjectOutputStream(sock.getOutputStream());
byte[] bytes = "SOME_MESSAGE".getBytes();
out.writeObject(new FilePayLoad("SOME_MESSAGE", bytes.length, bytes));
out.flush();
}
}
}
Client
public class Client
{
public static void main(String[] args) throws Exception
{
Socket sock = new Socket("127.0.0.1", 9999);
ObjectInputStream inByte = new ObjectInputStream(sock.getInputStream());
PayLoad payLoad = (PayLoad) inByte.readObject();
System.out.println(payLoad.getMessage());
System.out.println(payLoad.getLength());
System.out.println(new String(payLoad.getbytes()));
}
}
Related
I created a simple server and a client, but the server could not read anything that was sent from the client. I also add a print statement after I sent the string, but it cannot be printed either.
public class Server {
public static void main(String[] args) throws IOException, ClassNotFoundException {
ServerSocket serverSocket = new ServerSocket(6666);
Socket clientSocket = serverSocket.accept();
System.out.println("accepting client at address " + clientSocket.getRemoteSocketAddress());
ObjectInputStream in = new ObjectInputStream(clientSocket.getInputStream());
ObjectOutputStream out = new ObjectOutputStream(clientSocket.getOutputStream());
String input = (String) in.readObject();
System.out.println(input);
out.writeObject("Received");
out.flush();
}
}
Below is the client, and I just want to send a string "?????does not send":
public class Test {
public static void main(String[] args) throws IOException, ClassNotFoundException {
Client client = new Client();
client.sentInfo();
}
private static class Client {
private ObjectInputStream objectInputStream;
private ObjectOutputStream objectOutputStream;
public Client() throws IOException {
Socket socket = new Socket("127.0.0.1", 6666);
this.objectInputStream = new ObjectInputStream(socket.getInputStream());
this.objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
}
public void sentInfo() throws IOException, ClassNotFoundException {
this.objectOutputStream.writeObject("?????does not send");
this.objectOutputStream.flush();
System.out.println("????????");
Message resp = (Message) this.objectInputStream.readObject();
System.out.println(resp.getMessage());
}
}
}
I tried something else, if I just use InputStream and use a buffer to read bytes, like this:
Server code
This is the client code: client code
The code in the two link above would work. However, it would not work if I tried to use ObjectInputStream:
This is the server: server
This is the client: client
This is the Message object I want to send: Message class
Can someone explain this for me please? Thanks!
To read Strings from a socket use something like this:
DataInputStream input = new DataInputStream(clientSocket.getInputStream());
String message = input.readUTF();
You can open multiple streams from a socket, so if you want to read something else that really needs the ObjectInputStream than it can be open as well. Don't forget to properly close the streams & sockets.
I basically was trying to give a response back from my server if my client sends me the message "Hello mr server". However it doesn't.
Here is my code :
public class Server {
public static final int PORT = 6666;
public static void main(String[] args) throws IOException {
new Server().runServer();
}
public void runServer() throws IOException {
ServerSocket serverSocket = new ServerSocket(PORT);
System.out.println("Server up and ready for connections.....");
while (true) {
Socket socket = serverSocket.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); //for fetching data
String str = br.readLine(); //for fetching data
System.out.println("Client Data:" + str + '\n');
String dataSendingToClient = "gg";
OutputStreamWriter os = new OutputStreamWriter(socket.getOutputStream()); //for sending data
PrintWriter out = new PrintWriter(os); //for sending data
out.println(dataSendingToClient);
os.flush();
if (br.equals("hey mr server")){
OutputStreamWriter os2 = new OutputStreamWriter(socket.getOutputStream()); //for sending data
PrintWriter out2 = new PrintWriter(os); //for sending data
out2.println("hey mr client");
os.flush();
}
}
}
}
You are using br.equals("hey mr server") which will always return false, since br is not a String, but a BufferedReader
Instead you should use your already defined str variable str.equals("hey mr server")
Also note that with your current code, your server will only read one message from the client before moving on to the next connection
If you want your server to read more messages from a single client, you will need to loop until the client sends a disconnect message/the socket closes
while(true)
{
Socket socket = serverSocket.accept();
BufferedReader br = [...];
PrintWriter out = [...];
for(String message = br.readLine(); message != null; message = br.readLine())
{
//do stuff
//message is each line from the client
}
}
If you have multiple clients trying to connect, you will need to multithread the connections
I would recommend a class to enclose the connection details and use Stacks to poll if the client sent data
public static void main(String[] args) //or whatever other method you're running in
{
List<Connection> clients = new ArrayList<Connection>(); //some data structure to hold the clients
//start accepting connections
new Thread(new Runnable()
{
public void run()
{
while(true)
Connection client = new Connection(serverSocket.accept());
}
}).start();
//do something with the clients, read/write/whatever
}
private class Connection extends Runnable
{
private BufferedReader reader;
private PrintWriter writer;
private Queue<String> messages;
public Connection(Socket s)
{
reader = [...];
writer = [...];
messages = new LinkedList<String>();
}
public void run()
{
//just keep reading
while(true)
messages.add(reader.readLine();
}
public String read()
{
messages.poll();
}
public void write(String msg)
{
writer.write(msg);
writer.flush();
}
}
Note: take that as rough pseudocode
I have been asked to take this post down, and in particular the code, by a superior of mine
Problem 1: Client did not receive message
Solution: Make sure port matches sending's port
Problem 2: Could not broadcast message
Solution: Use a broadcast address
// Client REceive
DatagramSocket socket = new DatagramSocket(null);
socket.setReuseAddress(true);
socket.bind(new InetSocketAddress("127.0.0.1", 4002));
// ClientSEnd
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
socket = new DatagramSocket();
socket.setReuseAddress(true);
Just add the port number to the Datagram socket in the receive. it will work fine.
Class - ClientReceive:
DatagramSocket socket = new DatagramSocket(4001);
Set the reuse address to true ..
that will make use of the address whatever it is 4001 4002..etc
socket.setReuseAddress(true);
The problem seems to be that DatagramSocket allows you to send a datagram to a given destination. In your case you are sending to localhost, so that all messages are sent to the local machine only and not to other clients. If you want to reach all network clients should use a broadcast address or use the MulticastSocket class instead DatagramSocket.
import java.net.*;
import java.io.*;
public class ClientSend implements Runnable
{
private Thread t;
private DatagramSocket socket;
private String name;
private String sendingMessage;
private int port;
public ClientSend(int port)
{
this.port = port;
}
public void run()
{
try{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
socket = new DatagramSocket();
socket.setReuseAddress(true);
while(true)
{
sendingMessage = br.readLine();
byte sendingData[] = sendingMessage.getBytes();
InetAddress clientAddress = InetAddress.getByName("224.0.0.3");
DatagramPacket sendingPacket = new DatagramPacket(sendingData, sendingData.length, clientAddress, 4011);
socket.send(sendingPacket);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void start()
{
t = new Thread(this);
t.start();
}
public static void main(String args[]) throws Exception
{
ClientSend CS = new ClientSend(4011);
CS.start();
}
}
import java.net.;
import java.io.;
public class ClientReceive implements Runnable
{
private Thread t;
public ClientReceive()
{
}
public void run()
{
try {
// DatagramSocket socket = new DatagramSocket(null);
MulticastSocket socket = new MulticastSocket(4011);
InetAddress group = InetAddress.getByName("10.10.222.120");
socket.joinGroup(group);
//socket.setReuseAddress(true);
//socket.bind(new InetSocketAddress("10.10.222.120", 4011));
while(true)
{
byte receivingData[] = new byte[1024];
DatagramPacket receivingPacket = new DatagramPacket(receivingData, receivingData.length);
socket.receive(receivingPacket);
String receivingMessage = new String(receivingPacket.getData(), 0, receivingPacket.getLength());
System.out.println("Received: " + receivingMessage);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void start()
{
t = new Thread(this);
t.start();
}
public static void main(String args[]) throws Exception
{
ClientReceive CR = new ClientReceive();
CR.start();
}
}
I'm trying to code an instant messaging system... Initially, I'm doing it this way, and once I get it to work I'll add the GUI.
Once a client sends a message to the server, the server is supposed to display it to all the other clients. How can I do that? I've been trying a few things but it keeps displaying only to the client that sent the message...
Thanks in advance!
SERVER
import java.io.*;
import java.net.*;
class Server {
//one per server
static int port = 3000;
private int backlog = 100;
ServerSocket main;
static DataOutputStream dataOut;
static DataInputStream dataIn;
static String scannerMessage;
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static class MailServer extends Thread {
//one per client
static int index;
String name = Client.name;
public MailServer(int index, DataInputStream in, DataOutputStream out) {
Server.dataIn = in;
Server.dataOut = out;
this.index = index; // thread index, one per client
}
public void run() {
while (true) {
try {
String receivedMessage = dataIn.readUTF();
//print receivedMessage to all clients
} catch (Exception e) {
break;
}
}
}
}
public Server(int port) throws Exception {
this.main = new ServerSocket(port);
}
// start a serve
public void serve() throws Exception {
int index = 1;
while (true) {
Socket socket = this.main.accept();
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
DataInputStream dataIn = new DataInputStream(in);
DataOutputStream dataOut = new DataOutputStream(out);
// handle the connection
// keep reading using an infintite loop
System.out.println("Handling connection to Client " + index + "...");
(new MailServer(index, dataIn, dataOut)).start();
index += 1; // add one every time a new client is added
}
}
public static void main(String[] args) throws Exception {
Server s = new Server(port);
System.out.println("Serving....");
s.serve();
}
}
CLIENT
import java.io.*;
import java.net.*;
class Client {
static String hostname = "127.0.0.1";
static int port = Server.port;
static Socket socket;
static String name;
static class Sender extends Thread {
DataOutputStream dataOut;
public Sender(DataOutputStream dataOut) {
this.dataOut = dataOut;
}
public void run() {
while(true) {
//get a message from the user
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
try {
String message = br.readLine();
dataOut.writeUTF(message);
dataOut.flush();
} catch(Exception e) {
break;
}
}
}
}
static class Receiver extends Thread {
DataInputStream dataIn;
public Receiver(DataInputStream dataIn) {
this.dataIn = dataIn;
}
public void run() {
while(true) {
try {
//RECEIVE A MESAGE FROM THE SERVER (ending in \n)
String msg = dataIn.readUTF();
while (msg != null) {
System.out.println(msg);
msg = dataIn.readUTF();
}
} catch(Exception e) {
break;
}
}
}
}
//client will require host name and the port
public Client(String hostname, int port) throws Exception {
socket = new Socket(hostname, port);
}
public void connect() throws Exception {
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
DataInputStream dataIn = new DataInputStream(in);
DataOutputStream dataOut = new DataOutputStream(out);
//handle the connection
System.out.println("Handling connection to server...");
Thread sender = new Sender(dataOut);
Thread receiver = new Receiver(dataIn);
sender.start();
receiver.start();
sender.join();
receiver.join();
System.out.println("Client " + Server.MailServer.index);
System.out.println("----------------------");
}
public static void main(String[] args) throws Exception {
Client c = new Client(hostname, port);
c.connect();
}
}
Update: I created a list of all the MailServer objects and then iterated through them to send the message to all the clients, as JP Moresmau suggested... but now the first Client to send something receives all the outputs. Why is this? How can I fix it... ? Thank you, and sorry if my questions seem too obvious or dumb, I'm still a Java noob:(
SERVER - UPDATED
package csci2020_assignment51;
import java.io.*;
import java.net.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
class Server {
//one per server
static int port = 3000;
private int backlog = 100;
ServerSocket main;
static DataOutputStream dataOut;
static DataInputStream dataIn;
static String scannerMessage;
static List<MailServer> mailServers = Collections.<MailServer>synchronizedList(new ArrayList<MailServer>());
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static class MailServer extends Thread {
//one per client
static int index;
String name = Client.name;
public MailServer(int index, DataInputStream in, DataOutputStream out) {
Server.dataIn = in;
Server.dataOut = out;
this.index = index; // thread index, one per client
}
public void run() {
while (true) {
try {
String receivedMessage = dataIn.readUTF();
String outputMessage = "Client " + index + " said: " + receivedMessage;
//print receivedMessage to all clients
for (MailServer mailserver : mailServers) {
dataOut.writeUTF(outputMessage);
}
} catch (Exception e) {
break;
}
}
}
}
public Server(int port) throws Exception {
this.main = new ServerSocket(port);
}
// start a serve
public void serve() throws Exception {
int index = 1;
while (true) {
Socket socket = this.main.accept();
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
DataInputStream dataIn = new DataInputStream(in);
DataOutputStream dataOut = new DataOutputStream(out);
// handle the connection
// keep reading using an infintite loop
System.out.println("Handling connection to Client " + index + "...");
MailServer mailServer = new MailServer(index, dataIn, dataOut);
mailServer.start();
mailServers.add(mailServer);
dataOut.writeUTF("Client " + index);
index += 1; // add one every time a new client is added
}
}
public static void main(String[] args) throws Exception {
Server s = new Server(port);
System.out.println("Serving....");
s.serve();
}
}
Have a static list of all the MailServer objects you create
static List<MailServer> servers=Collections.<MailServer>synchronizedList(new LinkedList<MailServer>);
...
MailServer s=new MailServer(index, dataIn, dataOut);
servers.add(s);
s.start();
Then loop through them all when one of them receives a message, and for all expect the receiver, write the message to their output.
The big problem in your code is that dataOut and dataIn are unique! You need to move them to the MailServer class. Each MailServer talks to one specific client and hence needs to have their own streams.
static class MailServer extends Thread {
DataOutputStream dataOut;
DataInputStream dataIn;
And your notification loop becomes:
for(MailServer mailServer:mailServers){
if (mailServer!=this){
mailServer.dataOut.writeUtf(...);
}
}
I also don't understand how you expect to get the Client.name in the server, since Client runs on another machine... Get rid of that for now.
Here is the Server
public class SocketMsg {
public static void main(String[] args) throws IOException{
ServerSocket ss = new ServerSocket("number goes here");
System.out.println("Server Ready");
ss.accept();
}
}
Client:
public class SocketMesg {
public static void main(String[] args) throws IOException{
Socket socket = null;
OutputStreamWriter osw;
String str = "Hello World";
try {
socket = new Socket("localhost", "number goes here");
osw =new OutputStreamWriter(socket.getOutputStream());
osw.write(str, 0, str.length());
} catch (IOException e) {
System.err.print(e);
}
finally {
socket.close();
}
}
Personally, the code works but the strings are not sending to the other host, I gave them the same number, but it is not working. The client is sending it back to the server on the DOS window. Did I make a error? What did I do wrong?
Your server-side at least needs the following.
Socket clientSocket = serverSocket.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
// process inputLine;
}
You need to flush outputstream to commit write buffer to the socket. Also be careful with charset if writing strings. This example explicitly uses UTF-8 through "low level" byte array buffer. I think you are practicing your first socket programming so I kept this very simple.
Server.java
import java.net.*;
import java.io.*;
public class Server {
public static void main(String[] args) throws Exception {
ServerSocket ss = new ServerSocket(1122);
System.out.println("Server Ready");
while(true) {
Socket socket = ss.accept();
InputStream is = socket.getInputStream();
// client must send 1-10 bytes, no more in single command
byte[] buf = new byte[10];
int read = is.read(buf, 0, buf.length);
String cmd = new String(buf, 0, read, "UTF-8");
System.out.println(cmd);
socket.close(); // we are done, this example reads input and then closes socket
}
}
}
Client.java
import java.net.*;
import java.io.*;
public class Client {
public static void main(String[] args) throws Exception {
Socket socket = null;
// send max of 10 bytes to simplify this example
String str = "ABCDEFGHIJ";
try {
socket = new Socket("localhost", 1122);
OutputStream os = socket.getOutputStream();
byte[] buf = str.getBytes("UTF-8");
os.write(buf, 0, buf.length);
os.flush();
} catch (IOException ex) {
System.err.print(ex);
} finally {
socket.close();
}
}
}