I'm learning Java socket programming, and I'm pretty positive my code is correct, but for some reason the server and the client don't communicate. I'm not quite sure if they're even connecting. Here is what I've done so far.
Server:
public static void main(String[] args) throws Exception
{
Main_Server server = new Main_Server();
server.run();
}
public void run() throws Exception
{
ServerSocket server = new ServerSocket(444); //Port
Socket sSocket = server.accept();
BufferedReader bfr = new BufferedReader(new InputStreamReader(sSocket.getInputStream()));
String clientMessage = bfr.readLine();
System.out.println("Client: "+clientMessage);
if (clientMessage != null)
{
PrintStream ps = new PrintStream(sSocket.getOutputStream());
ps.println("Message Received.");
}
}
Client:
public static void main(String[] args) throws Exception
{
Client_One client = new Client_One();
client.run();
}
public void run() throws Exception
{
Socket clientSocket = new Socket("localhost", 444);
PrintStream ps = new PrintStream(clientSocket.getOutputStream());
ps.println("Hello, server.");
BufferedReader bfr = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String serverMessage = bfr.readLine();
System.out.println("Server: "+serverMessage);
}
So I run the server first and the client after (I'm currently using NetBeans IDE 8.1). The programs run and just sit there, but nothing happens after that. Why is this? I just have two empty consoles.
Thank you for your time.
If you use a Buffer you need to flush it or close it, otherwise if the buffer is not full the data remains in the buffer. It is ok also to close it because as you can see from the javadoc closing a stream will also flush it.
From the javadoc of OutputStream you can see what flushing means:
Flushes this output stream and forces any buffered output bytes to be written out.
Note: additionally remember to close both input and output streams when you finished to use them, otherwise you still have not properly closed resources using memory.
Related
I am having problem even with this very basic client-server application. The client is not sending data/ the server is not receiving. I cannot understand where is the problem. I am even starting to think that i did not understand anything about sockets.
This is the Server code:
public class Server
{
public static void main(String args[])
{
try{
ServerSocket serverSocket = new ServerSocket(3000);
Socket socket = serverSocket.accept();
System.out.println("Client connected: "+socket.getInetAddress.toString());
Scanner scanner = new Scanner(socket.getInputStream());
while(true)
{
System.out.println(scanner.nextLine());
}
}catch(IOException e)
{
System.out.println("error");
}
}
}
This is the client code:
public class Client
{
public static void main(String args[])
{
Socket socket;
PrintWriter printWriter;
try {
socket = new Socket("127.0.0.1", 3000);
printWriter = new PrintWriter(socket.getOutputStream(), true);
while(true)
{
printWriter.write("frejwnnnnnnnnnnnnnnnnnnnnnnnnosfmxdawehtcielwhctowhg,vort,hyvorjtv,h");
printWriter.flush();
}
}catch(IOException e)
{
System.out.print("error\n");
}
}
}
If I run both on the same machine, the server prints correctly "client connected .....", but then prints no more.
What is the problem?
The server reads the next line. The client doesn't send any line ending. So the server can't possibly know that the line is supposed to be ended, and blocks until it finds an EOL in the stream. Or until the client closes its socket.
In client code, you decorate your output stream with PrintWriter, so you can use println.
Replace
printWriter.write("frejwnnnnn...rjtv,h");
printWriter.flush();
by:
printWriter.println("frejwnnnnn...rjtv,h");
Flush is useless since have request autoflush (true in PrintWriter constructor).
In server code, you can use a BuffererdReader decorator instead of Scanner:
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String inputLine;
while ((inputLine = br.readLine()) != null) {
System.out.println(inputLine);
}
Am I doing this right? When I try to run this on my computers loopback address I'm getting a "connection reset" error.
public class DateTimeClient {
public static void main(String[] args) throws IOException {
int port = Integer.parseInt(args[0]);
String host = args[1];
try {
System.out.println("Connecting....\n");
Socket socket = new Socket(host, port);
PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
BufferedReader reader = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
System.out.println("Date: " + reader.read());
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class DateTimeServer {
public static void main(String[] args) {
int portNum = Integer.parseInt(args[0]);
try {
ServerSocket socket = new ServerSocket(portNum);
Socket client = socket.accept();
BufferedReader reader = new BufferedReader(new InputStreamReader(
client.getInputStream()));
PrintWriter writer = new PrintWriter(client.getOutputStream());
Date date = new Date();
writer.print(date.toString());
} catch(Exception e) {
e.printStackTrace();
}
}
}
I grab the port to run the server on, the port to connect to and the host as arguments in the main method, create sockets and use BufferedReader and PrintWriter. I followed Oracle's tutorial on this pretty closely so I'm not sure where I coulda made a mistake.
#EJP is correct, but I think that the actual problem is that the server side is neither closing or flushing writer. When the server exits, the TCP/IP connection gets closed (by the server-side OS) without any data having been written to the socket. The client side JVM sees a reset connection and throws an exception.
Solution: Close your streams properly on the server side and the client side should see the data. (Flushing would work too ... but if you neglect to close the streams in all cases, you risk problems with server-side file descriptor leaks. Hence, closing is the best solution.)
You're only reading one character, not a date. Try sending and receiving a line.
I am trying to create a multiclient chat sort of server in which we have multiple clients connecting to server and whatever message a client enters, it gets displayed to all the clients(including the client who sent the message). I am not getting this output, instead the message just echoes only on the sender client and no other client. Code is quite long, hence i am displaying snippets of whichever code i think will help you understand error. In case, it is not enough, just comment which part you require. Thanks in advance. I am stuck on this since about hour and half, so i appreciate whatever help i would get.
The Server Class
public class Multiserver {
ServerSocket serversocket;
Socket socket;
ArrayList<Socket> al = new ArrayList<Socket>();
DataInputStream dis;
DataOutputStream dos;
Multiserver() throws IOException
{
serversocket = new ServerSocket(1036);
System.out.println("Server started on port 1036");
while(true)
{
socket = serversocket.accept();
System.out.println(socket);
al.add(socket);
Mythread thread = new Mythread(socket, al);
thread.start();
}
}
Thread used in server class
public class Mythread extends Thread{
Socket socket;
ArrayList al;
DataInputStream dis;
DataOutputStream dos;
Mythread(Socket socket, ArrayList al)
{
this.socket = socket;
this.al = al;}
public void run()
{
try{
String data ="";
dis = new DataInputStream(socket.getInputStream());
data = dis.readUTF();
if(!data.equals("stop"))
{
broadcast(data);
}
else
{
dos = new DataOutputStream(socket.getOutputStream());
// data = dos.readUTF();
dos.writeUTF(data);
dos.flush();
//dos.close();
}
}
catch(Exception e){
System.out.println("Run "+e);
}
}
public void broadcast(String data)
{
try{
Iterator it = al.iterator();
while(it.hasNext())
{
Socket socket1 = (Socket)it.next();
dos = new DataOutputStream(socket1.getOutputStream());
dos.writeUTF(data);
dos.flush();
}
}
catch(Exception e){
System.out.println("Broadcast running "+ e);
}
}
}
The client class
public class Multiclient {
Socket socket;
DataInputStream dis;
DataOutputStream dos;
Multiclient() throws IOException
{
socket = new Socket("127.0.0.1", 1036);
System.out.println(socket);
Mythreadc my = new Mythreadc(socket);
my.start();
}
Thread used in client class
public class Mythreadc extends Thread{
DataInputStream dis;
DataOutputStream dos;
Socket socket;
Mythreadc(Socket socket)throws IOException
{
this.socket = socket;}
public void run()
{
BufferedReader br = null;
try{
br = new BufferedReader(new InputStreamReader (System.in));
dos = new DataOutputStream(socket.getOutputStream());
String data = "";
do{
data = br.readLine();
dos.writeUTF(data);
System.out.println(data);
dos.flush();
}
while(!data.equals("stop"));
}
catch(Exception e)
{
System.out.println("Client input "+e);
}
finally{
try{
br.close();
dis.close();
dos.close();
}
catch(Exception e)
{
System.out.println("Closing "+e);
}
}
}
}
I am sorry i have put on such a long code, almost all the program. But i feel it is necessary to understand where the problem lies.I have tried and i think it lies in the part where we display data written in the client's socket in the client thread class but i don't know what it is ???
#EDIT: Forgot to mention. The client stops when he sends the message "Stop"!
There are two problems with your code that are preventing the clients from displaying more than one message.
Problem one: Your client code never actually displays or prints out the messages it receives from the server. The line
dos = new DataOutputStream(socket.getOutputStream());
creates an OutputStream you can use to write data to the socket, i.e. send messages to the server. But you never use the socket's InputStream, which is what you need to do to read data from the socket, i.e. receive messages from the server. When you see a message printed out on the client, you're actually just seeing the result of
System.out.println(data);
which has your client print the message it just sent.
In order for the client to accept input from the user and read messages from the server at the same time, you should probably use two threads on the client. One thread can just be the client thread you already wrote, since it takes care of accepting input from the user. The other thread should look something like this:
public class ClientReaderThread extends Thread {
Socket socket;
ClientReaderThread(Socket socket) {
this.socket = socket;
}
public void run() {
try (BufferedReader serverReader = new BufferedReader(
new InputStreamReader(socket.getInputStream()))){
String fromServer = serverReader.readLine();;
while(fromServer != null) {
if (fromServer.equals("stop"))
break;
System.out.println(fromServer);
fromServer = serverReader.readLine();
}
} catch (IOException e) {
System.out.println("Client error! Got exception: " + e);
}
}
}
(Note that I use the try-with-resources statement to construct the reader, which takes care of closing it when the client stops).
Then in your main client class, start both threads with the same socket:
Multiclient() throws IOException
{
socket = new Socket("127.0.0.1", 1036);
System.out.println(socket);
Mythreadc my = new Mythreadc(socket);
ClientReaderThread reader = new ClientReaderThread(socket);
my.start();
reader.start();
}
Problem two: Your server only reads and echoes a single line from each client, because the socket thread that handles each client (Mythread) doesn't contain a loop. With your setup of creating a single thread per client, run() only gets called once per client, so that run() method needs to handle every message that client sends.
Here's how the run() method in the server's thread should look:
public void run() {
try (BufferedReader inStream = new BufferedReader(
new InputStreamReader(socket.getInputStream()))){
String data = inStream.readLine();
while(data != null) {
if(data.equals("stop"))
break;
broadcast(data);
data = inStream.readLine();
}
}
catch(Exception e){
System.out.println("Run exception "+e);
} finally {
al.remove(socket); //This is important to do
}
}
I made an additional important change here: at the end of the run() method, when either the client disconnected or an exception happened, the thread removes its socket from the ArrayList. This ensures that other server threads, which all reference the same ArrayList, don't try to broadcast to the socket of a client that has disconnected. If you neglect to do this, you'll get an exception when a client sends a message to the server after another client has disconnected.
Miscellaneous notes
As I mentioned in my comment, you should give al a type of ArrayList<Socket> inside the thread class, and use a for-each loop instead of an Iterator to iterate over it in broadcast().
I'm using BufferedReader instead of DataInputStream to read from the socket. That's because DataInputStream.readUTF() and writeUTF() are deprecated, and have been replaced with BufferedReader.readLine() and PrintWriter.println().
The streams like dis and dos don't need to be instance variables in your thread classes, since they are only ever used inside the run() method. They can be local variables inside run(), like I did with inStream in my new run() method.
I think you just missed passing the ArrayList of Sockets Users Currently Connected to The Server to the thread
and Instead of Posting your Server Class You have just posted Client Program 2 times anyway ,
Your ServerClass should be build in this way : -
As soon as ServerClass recieves the request from any client, Server Class should add the Socket into ArrayList and create New Thread and just pass both to the MyThread Class
Edit :
It seems you haven't written code for Displaying the data you will get from the server .
At Client Side for Sending the Message You can simple write that in Main Thread that is under Your Client Class's Main Mehtod
You actually needed Thread at client side not for sending the message but rather for Listening the Message from the server,
because you never known when anyone can send you the message but you will always know when you want to send message to anybody connected to this chat App
Now coming to the Coding Part :
Client Class
public class Multiclient {
Socket socket;
DataInputStream dis;
DataOutputStream dos;
Multiclient() throws IOException
{
socket = new Socket("127.0.0.1", 1036);
System.out.println(socket);
Mythreadc my = new Mythreadc(socket);
my.start();
/**
* Here write out the code for taking input from Standard Console
*/
BufferedReader br = null;
try{
br = new BufferedReader(new InputStreamReader (System.in));
dos = new DataOutputStream(socket.getOutputStream());
String data = "";
do{
data = br.readLine();
dos.writeUTF(data);
System.out.println(data);
dos.flush();
}
while(!data.equals("stop"));
}
catch(Exception e)
{
System.out.println("Client input "+e);
}
}
Client Thread
try{
String data ="";
dis = new DataInputStream(socket.getInputStream());
while(data.equalsIgnorCase("stop")){
data = dis.readUTF();
System.out.println("Server Message : "+data);
}
}
catch(Exception e){
System.out.println("Run "+e);
}
Client Thread is not complete but i think this information is sufficient enough .
Hope It help you out , Your problem do remind me of College Days :)
I'm new to the network communication and I'm trying to build client-server application.
protected void init(){
Server myServer = new Server();
Client myClient = new Client();
}
That's my Client class:
public class Client {
public Client() {
init();
}
private void init() {
Socket echoSocket = null;
DataOutputStream os = null;
DataInputStream is = null;
DataInputStream stdIn = new DataInputStream(System.in);
try {
echoSocket = new Socket("localhost", 1234);
os = new DataOutputStream(echoSocket.getOutputStream());
is = new DataInputStream(echoSocket.getInputStream());
os.writeInt(stdIn.readInt());
echoSocket.getOutputStream().close();
echoSocket.getInputStream().close();
echoSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
And that's server:
public class Server {
public Server() {
init();
}
private void init() {
try {
boolean run = true;
ServerSocket ss = new ServerSocket(1234);
Socket s = ss.accept();
DataInputStream dis = new DataInputStream(s.getInputStream());
System.out.println(dis.readInt());
s.getInputStream().close();
s.getOutputStream().close();
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
First of all:
Can I initialize client and server simply like i did? new Server() and new Client()?
Question 2:
Is it important what i initialize at first? client or server?
Question 3:
When i compile this code with client first initialized, i become Connection refused: connect. I know it means that there is no listening socket running on the port you are trying to connect to. That's why server must go first, i think. Is it so? can i fix it using setSoTimeout and how?
Question 4:
When i compile it with server and then client, output is nothing. And i think it has nothing to do with client, because if i try to print "1", for example, it doesn't work either. I think it just waits for the client and does nothing that goes after. How can i fix this? maybe setSoTimeout goes here too?
You can't have both client and server in the same thread.
As you already have observed, the server accepts the connection and tries to read something. It doesn't know that the client is running in the very same thread.
Either make a multi-threaded application, where client and server have their own thread. Or make two prgrams that run independently of each other. The latter would be also the "normal case".
Make two different projects, first run server than client.
Server will write on console "Server started" than run client it will ask your name, type your name press ok . Your name will be sent to server and server will reply saying hello to you.
Here is server code
import java.net.*;
import java.io.*;
import javax.swing.*;
public class Server {
public static void main(String[] args) {
try{
ServerSocket ss= new ServerSocket(2224);
System.out.println("Serever started");
while(true)
{
Socket s=ss.accept();
InputStream is=s.getInputStream();
InputStreamReader isr=new InputStreamReader(is);
BufferedReader br=new BufferedReader(isr);
OutputStream os=s.getOutputStream();
PrintWriter pw=new PrintWriter(os);
String name=br.readLine();
String message="Hello "+name+"from server";
pw.println(message);
pw.flush();
}
}
catch(Exception exp)
{
System.out.println("Excepttion occured");
}
}
}
Here is client code
import java.net.*;
import java.io.*;
import java.util.Scanner;
import javax.swing.*;
public class Client {
public static void main(String[] args) throws IOException {
Socket s=new Socket("localhost",2224);
InputStream is=s.getInputStream();
InputStreamReader isr=new InputStreamReader(is);
BufferedReader br=new BufferedReader(isr);
OutputStream os=s.getOutputStream();
PrintWriter pw=new PrintWriter(os,true);
String message = JOptionPane.showInputDialog("Give your name");
pw.println(message);
pw.flush();
String servermessage = br.readLine();
JOptionPane.showMessageDialog(null, servermessage);
s.close();
}
}
I'm trying to implement a simple server(java application) and client(android app), where the client sends a string about 10 times a second. Everything works fine for a minute or so, after which the server stops receiving messages from the client. Relevant code below.
ClientThread.java
public class ClientThread implements Runnable{
static Socket socket;
static String message = "";
InetAddress serverAddr;
BufferedOutputStream bos;
public ClientThread(String message){
ClientThread.message = message;
}
#Override
public void run() {
try{
serverAddr = InetAddress.getByName(SERVER_IP);
if(socket != null && socket.isConnected())socket.close();
socket = new Socket(serverAddr, SERVER_PORT);
bos = new BufferedOutputStream (socket.getOutputStream());
OutputStreamWriter osw = new OutputStreamWriter(bos, "US-ASCII");
osw.write(message);
osw.flush();
socket.shutdownOutput();
socket.close();
}catch (Exception e) {
}
}
}
ServerThread.java
public class ServerThread extends Thread{
private ServerSocket serverSocket;
static String clientSentence;
public ServerThread(int port) throws IOException, AWTException{
serverSocket = new ServerSocket(port);
}
public void run() {
while(true){
try{
Socket server = serverSocket.accept();
BufferedReader d = new BufferedReader(new InputStreamReader(server.getInputStream()));
clientSentence = d.readLine();
System.out.println(clientSentence);
server.close();
}catch(IOException e){
e.printStackTrace();
break;
}
}
}
}
ClientThread.java is called about 10 times a second using:
Thread clientThread = new Thread(new ClientThread(message));
clientThread.start();
ServerThread.java is initialized and started using:
t = new ServerThread(8888);
t.start();
Any thoughts on why this would freeze after running for a bit? The only way to fix it is to restart the server, after which the same problem happens again after a minute. I spent a lot of time researching this issue but was unable to find a solution.
EDIT: I figured out the server freezes at the clientSentence = d.readLine(); part. Any idea why?
60 connection per second, one minute running: 3600 connections per minute.
Closing a socket doesn't release immediately the associated file descriptor. You may run out of resource at OS layer.
Try to run netstat on server side to see the active, pending and closed connections.
You may read this post on SU.
Your thread never exits and you keep creating new ones. So you run out of something: thread space, sockets, FDs, ...
This is all wrong. Either your thread should loop or you should create a new one. Not both.
Also:
You should use a single connection, not a new one per message.
You are reading lines but to sending them, unless the data already contains a newline, which it shouldn't.