I have a client/server connected over socket.
the client writes integer value to be read by the server
I use readInt() in ObjectOutputStream to write this value
and in the server side I use readInt() in ObjectInputStream to read this value.
But the server doesn't read any anything, it freeze at readInt()
What problem in reading using ObjectInputStream?
I was used DataOutputStream, and reading and writing was successful, but ObjectInputstream can read integer and other primitive type, what is the problem?
public class Server {
ServerSocket listener;
private static final int PORT = 9001;
private Socket socket;
private ObjectInputStream obin = null;
private ObjectOutputStream obout = null;
public Server() throws Exception{
listener = new ServerSocket(PORT);
run();
}
public void run() throws Exception{
socket = listener.accept();
obout = new ObjectOutputStream(socket.getOutputStream());
obout.flush();
obin = new ObjectInputStream(socket.getInputStream());
int h=obin.readInt();
System.out.println(h);
obout.writeInt(77);
}
public static void main(String[] args) throws Exception {
Server s = new Server();
}
}
and the client
public class Client {
private ObjectInputStream oin = null;
private ObjectOutputStream oot = null;
private Socket socket = null;
public Client() throws Exception{
String serverAddress = "127.0.0.1";
socket = new Socket(serverAddress, 9001);
oot = new ObjectOutputStream(socket.getOutputStream());
oot.flush();
oin = new ObjectInputStream(socket.getInputStream());
oot.writeInt(66);
int u = oin.readInt();
System.out.println(u);
}
public static void main(String[] args) throws Exception{
Client c= new Client();
}
}
When you run this code is supposed to get at the server 66
and at the client 77,
But actually I do not get anything. Why?
After every write you should flush() as it clears the output buffer which sends the bytes over the network. So your Server run method should be:
public void run() throws Exception {
socket = listener.accept();
obin = new ObjectInputStream(socket.getInputStream());
int h = obin.readInt();
System.out.println(h);
obout = new ObjectOutputStream(socket.getOutputStream());
obout.writeInt(77);
obout.flush();
}
and your Client constructor:
public Client() throws Exception {
String serverAddress = "127.0.0.1";
socket = new Socket(serverAddress, 9001);
oot = new ObjectOutputStream(socket.getOutputStream());
oot.writeInt(66);
oot.flush();
oin = new ObjectInputStream(socket.getInputStream());
int u = oin.readInt();
System.out.println(u);
}
If you're doing this as an exercise it's fine, but if you're going to run code based on this in production consider using higher level network libraries like protocol buffers.
Related
I Have Class like below trying to connect two client socket to a server but when they get accepted by server I can only send data to the server through first socket (named s1 in code) and the second socket can do not send data to the server
public class Client_1 {
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
Socket s1 = new Socket("localhost", 8888);
Socket s2 = new Socket("localhost", 8888);
BufferedOutputStream bos1 = new BufferedOutputStream(s1.getOutputStream());
ObjectOutputStream oos1 = new ObjectOutputStream(bos1);
oos1.flush();
BufferedOutputStream bos2 = new BufferedOutputStream(s2.getOutputStream());
ObjectOutputStream oos2 = new ObjectOutputStream(bos2);
oos2.flush();
BufferedInputStream bis1 = new BufferedInputStream(s1.getInputStream());
ObjectInputStream ois1 = new ObjectInputStream(bis1);
BufferedInputStream bis2 = new BufferedInputStream(s2.getInputStream());
ObjectInputStream ois2 = new ObjectInputStream(bis2);
oos1.writeObject("a message from first client s1");
oos1.flush();
oos2.writeObject("a message from second client s2"); // sever does not receive this one
oos2.flush();
}
}
here is server code waiting for client
public class Main {
public static void main(String[] args) throws IOException {
WaitForClient();
}
public static void WaitForClient() throws IOException {
ServerSocket serverSocket = new ServerSocket(8888);
int i = 0;
while(true) {
Socket client = serverSocket.accept();
i++;
System.out.println(i + " client connected");
ClientThread clientThread = new ClientThread(client);
Thread thread = new Thread(clientThread);
thread.setDaemon(true);
thread.start();
}
}
and this is ClientThread who get info from socket
public class ClientThread implements Runnable {
Socket clientSocket;
ObjectInputStream oIStream;
ObjectOutputStream oOStream;
Object inputObject;
BufferedInputStream bIS;
BufferedOutputStream bOS;
public ClientThread(Socket clientSocket) {
this.clientSocket = clientSocket;
}
#Override
public void run() {
try {
bOS = new BufferedOutputStream(clientSocket.getOutputStream());
bIS = new BufferedInputStream(clientSocket.getInputStream());
oOStream = new ObjectOutputStream(bOS);
oOStream.flush();
oIStream = new ObjectInputStream(bIS);
while (clientSocket.isConnected()) {
if (bIS.available() > 0) {
inputObject = oIStream.readObject();
doService(inputObject);
System.out.println(inputObject.toString());
inputObject = null;
}
}
System.out.println("connection is closed!!!");
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
System.out.println("socket exception" + e.getMessage());
}
}
}
and this is what printed to console
1 client connected
2 client connected
a message from first client s1 // input from the first socket but nothing from the second socket
This code should work,Are you getting any error in doService method?. In case any exception while loop will break and print statement will not be executed. Otherwise it should print data from both client
I got basic client-server chat application. Server side seems to work, when I connect with it via telnet, it receives the message and sends it back to all connected clients. I can't achieve the same using my own client tho.
So from the beginning, Server class
public class Server {
private Properties properties;
private ServerSocket serverSocket;
private Set<ClientConnection> clientConnections;
public Server() throws IOException {
clientConnections = new HashSet<>();
serverSocket = new ServerSocket(9999);
while(true){
Socket clientSocket = serverSocket.accept();
ClientConnection clientConnection = new ClientConnection(clientSocket, this);
clientConnections.add(clientConnection);
clientConnection.start();
}
}
public Set<ClientConnection> getClientConnections() {
return clientConnections;
}
}
On every connection is new ClientConnection created that at the beginning, sends "Hello from server" to new client (working if connects via telnet) and then, listens for all incoming messages and broadcast them to all connected clients, again - working if telnet is a client.
public class ClientConnection extends Thread {
private final Socket clientSocket;
private final Server server;
private OutputStream outputStream;
private InputStream inputStream;
public ClientConnection(Socket clientSocket, Server server) {
this.clientSocket = clientSocket;
this.server = server;
}
#Override
public void run(){
try {
handleClient();
} catch (IOException e) {
e.printStackTrace();
}
}
private void handleClient() throws IOException {
outputStream = clientSocket.getOutputStream();
inputStream = clientSocket.getInputStream();
outputStream.write("Hello from server".getBytes());
System.out.println("New client connected");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String incomingMessage;
while((incomingMessage = bufferedReader.readLine()) != null) {
for(ClientConnection connection : server.getClientConnections()) {
connection.getOutputStream().write(incomingMessage.getBytes());
}
System.out.println(incomingMessage);
}
clientSocket.close();
}
public OutputStream getOutputStream() {
return outputStream;
}
}
And then, I got Client application with ServerConnection class
public class ServerConnection{
private Socket socket;
private OutputStream outputStream;
private InputStream inputStream;
private BufferedReader bufferedReader;
private String host;
private int port;
public ServerConnection(String host, int port) {
this.host = host;
this.port = port;
}
public void connect() throws IOException {
socket = new Socket(host, port);
outputStream = socket.getOutputStream();
inputStream = socket.getInputStream();
outputStream.write("Hello from client".getBytes());
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String incommingMessage;
while((incommingMessage = bufferedReader.readLine()) != null) {
System.out.println(incommingMessage);
}
}
}
And it actually is registered by the server side (prints "New client connected"), but it isn't receiving "Hello from client" and the client isn't receiving any messages from the server.
Please try to send new lines at the end of your message from client, i.e.: outputStream.write("Hello from client\r\n\".getBytes());, as you are using bufferedReader.readLine() in your sever code. So BufferedReader is waiting for line end and nothing is happening.
I will not write the code for you, as you have what you need. But here is a flow, that took me a while myself to fully understand, which should help you out.
Server:
Start -> Accept connection -> Read InStream -> Write OutStream (FLUSH THE TOILET OF DATA) -> Loop
Client:
Start -> Connect -> Write OutStream (FLUSH THE TOILET OF DATA) -> Read InStream -> Close Connection
I want to send multiple data type over socket.
I have that code:
when I create client, it generates public and private keys and sends the public to serve and the serve stores it.
when client wants to send message to another client, it gets his public key from the server to encrypt the message.
But when I run this code it freeze at client in dest_public_key=(PublicKey) oin.readObject()
Why it stop at here?
Why it doesn't read the PublicKey's object that the handler writes to it?
Is there any problems in streams?
public class Server {
private static final int PORT = 9001;
ServerSocket listener;
private Handler h[] = new Handler[5];
public PublicKey[] keys = new PublicKey[5];
private int clientCount = 0;
public Server() throws Exception{
System.out.println("The server is running.");
listener = new ServerSocket(PORT);
run();
}
public void run() throws Exception{
System.out.println("Waiting for a client ...");
while (true) { addClient(listener.accept());}
}
private void addClient(Socket socket) throws Exception{
h[clientCount] = new ServerHandler(this, socket,clientCount);
h[clientCount].open(clientCount);
h[clientCount].start();
clientCount++;
}
public void store(int id,PublicKey key){
keys[id]=key;}
public PublicKey getPublicKey(int id){
return keys[id]; }
public static void main(String[] args) throws Exception {
Server s = new Server();}
}
handle class
public class Handler extends Thread {
private Server server;
private Socket socket;
private int ID = -1;
private DataInputStream streamIn = null;
private DataOutputStream streamOut = null;
private ObjectInputStream obIn = null;
private ObjectOutputStream obOut = null;
public Handler(Server _server, Socket _socket, int i){
super();
server = _server;
socket = _socket;
ID = i;
}
public void run()
{ while (true)
{ try
{
int dest=streamIn.readInt();
PublicKey dest_public_key=server.getPublicKey(dest);
obOut.writeObject(dest_public_key);
obOut.flush();}}
}
public void open(int i)
{
PublicKey publick = null;
try {
streamOut = new DataOutputStream(socket.getOutputStream());
streamIn = new DataInputStream(socket.getInputStream());
obOut = new ObjectOutputStream(socket.getOutputStream());
obIn = new ObjectInputStream(socket.getInputStream());
publick=(PublicKey)obIn.readObject();
server.store(ID,publick);
streamOut.writeInt(i);
streamOut.flush();
} catch (Exception e) {
e.printStackTrace();}
}}
client class
public class Client extends implements Runnable {
DataInputStream din;
DataOutputStream dot;
ObjectInputStream oin;
ObjectOutputStream oot;
public Client() {
try {
socket = new Socket(serverAddress, 9001);
din = new DataInputStream(socket.getInputStream());
dot = new DataOutputStream(socket.getOutputStream());
oot = new ObjectOutputStream(socket.getOutputStream());
oin = new ObjectInputStream(socket.getInputStream());
RSA.generateKey();
public_key=RSA.keys.getPublic();
private_key=RSA.keys.getPrivate();
oot.writeObject(public_key);
oot.flush();
int j =din.readInt(); // read number from server
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
Client client = new Client();
PublicKey dest_public_key=null;
System.out.println("enter client that you would to send to it");
Scanner input = new Scanner( System.in );
int select = input.nextInt();
dot.writeInt(select);
dot.flush();
dest_public_key=(PublicKey) oin.readObject();
}
}
I have this code:
Socket incomingConnection = serverSocket.accept();
String strategy = "1";
Client client = new Client(incomingConnection, this, strategy);
Constructor of Client:
public Client(Socket socket, ChatServer chatServer, String strategy) throws IOException{
this.socket = socket;
this.inputStream = socket.getInputStream();
this.outputStream = socket.getOutputStream();
this.chatServer = chatServer;
this.instance1 = new Strategy1(chatServer, this);
this.instance2 = new Strategy2(chatServer, this);
this.strategy = (this.instance1.getName().equals(strategy1) ? this.instance1 : this.instance2);
this.strategy.setStreams();
}
Now how looks like Strategy1:
public class Strategy1{
public Strategy1(ChatServer server, Client client) throws IOException{
this.chatServer = server;
this.client = client;
}
public void setStreams() throws IOException{
inputStream = new ObjectInputStream(client.getInputStream());
outputStream = new ObjectOutputStream(client.getOutputStream());
}
And the same Strategy2.
Method in Client class :
client.getInputStream() {
return inputStream;
}
// similar for outputStream
The problem is : when Client's constructor tries to execute strategy.setStreams(), the program blocks on new ObjectInputStream().
When I move setStream() method's containment into Constructor of Strategy1 then it works!
Why?
Swap these lines:
inputStream = new ObjectInputStream(client.getInputStream());
outputStream = new ObjectOutputStream(client.getOutputStream());
Creating an ObjectInputStream reads from the socket. If you create input streams first on both ends of the connection, it will deadlock. The safest is to always create output streams first.
I am creating a program where multiple clients can connect to a server. The message sent by a client will be broadcast to all other client connections on the server.
My problem is that the message is broadcast to only the client it has come from, and I cannot spot the error in my code.
Can anyone help me spot where the problem is or how I could improve the code?Thank you.
EDIT:
public class MsgClient{
private Socket client;
private ObjectInputStream input;
private DataOutputStream output;
private BufferedReader keyboard;
private String cmdInput;
public MsgClient(String name, String server, int port){
try{
client = new Socket(server, port);
DataInputStream sInput = new DataInputStream(client.getInputStream());
output = new DataOutputStream(client.getOutputStream());
input = new ObjectInputStream(client.getInputStream());
keyboard = new BufferedReader(new InputStreamReader(System.in));
output.writeUTF(name);
while(true){
System.out.println("Send a msg to the server: ");
cmdInput = keyboard.readLine();
output.writeUTF(cmdInput);
System.out.println(sInput.readUTF());
}
}
catch (Exception e){
e.printStackTrace();
}
}// end constructor
public static void main(String args[]) throws IOException {
if(args.length != 3)
throw new RuntimeException("Syntax: java MsgClient <username> <servername> <port>");
MsgClient aClient = new MsgClient(args[0], args[1], Integer.parseInt(args[2]));
} // end main
}
public class MsgServer {
public MsgServer(int PORT) throws IOException{
ServerSocket server = new ServerSocket(PORT);
System.out.println("Server Established...");
while(true){
Socket client = server.accept();
DataInputStream input = new DataInputStream(client.getInputStream());
ObjectOutputStream oo = new ObjectOutputStream(client.getOutputStream());
DataOutput output = new DataOutputStream(client.getOutputStream());
System.out.println("New client accepted");
String clientName = input.readUTF();
ClientHandler handler = new ClientHandler(clientName, client); // construct and run thread.
handler.start();
System.out.println("Handler started!");
}//end while
}//end of constructor
public static void main(String args[]) throws IOException {
if(args.length != 1)
throw new RuntimeException("Syntax: java MsgServer requires <PORT> number");
new MsgServer(Integer.parseInt(args[0]));
}
}
public class ClientHandler extends Thread {
Socket client;
DataInputStream din;
DataOutputStream dout;
String name;
String clientMsg;
protected static Vector socketVector = new Vector();
public ClientHandler (String name, Socket client) throws IOException{
this.name = name;
this.client = client;
din = new DataInputStream(client.getInputStream());
dout = new DataOutputStream(client.getOutputStream());
}
// Code run at every start()
public void run(){
try{
socketVector.addElement(this);
clientMsg = din.readUTF(); // inside or outside loop?
while(true){
broadcast( name + " has joined auction on IP " + client.getInetAddress());
broadcast( name + " says: " + clientMsg);
}
} catch(IOException ex){
System.out.println("-- Connection to user lost");
} finally{
socketVector.removeElement(this);
broadcast(name + " has left");
try{
client.close();
}catch (IOException ex){
System.out.println("socket to user already closed?");
}
}
}
Another issue is here, in the MsgClient code:
cmdInput = keyboard.readLine();
output.writeUTF(cmdInput);
System.out.println(sInput.readUTF());
A client will not receive a message until after it has sent one.
Where is the broadcast() method?
You are creating two sets of streams in the server. The accept loop shouldn't create any streams or do any I/O. All that should be done in the thread that handles the connection.
You don't need the ObjectInput/OutputStreams at all here.
When you get any IOException other than a read timeout on a socket you must close it. You should also print out the exception's own message, rather than just making up your own.