Client-server socket program not experiencing deadlock as expected - java

I have an example socket program. The client just sends numbers and the server echoes them back.
Client:
public class Client {
private Socket socket;
private BufferedReader in;
private PrintWriter out;
public Client(String hostname, int port) throws IOException {
socket = new Socket(hostname, port);
//Create a BufferedReader with buffer size of 1
in = new BufferedReader(new InputStreamReader(socket.getInputStream()), 1);
out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
}
public void sendRequest(String x) throws IOException {
out.print(x + "\n");
out.flush();
}
public void close() throws IOException {
in.close();
out.close();
socket.close();
}
public String getReply() throws IOException {
String reply = in.readLine();
return reply;
}
public static void main(String[] args) {
try {
Client client = new Client("localhost", 4949);
for (int i = 0; i < 100000; i++){
System.err.println("Sending: "+i);
client.sendRequest(String.valueOf(i));
}
for (int i = 0; i < 100000; i++){
client.getReply();
}
client.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
Server:
public class Server {
private ServerSocket serverSocket;
public Server(int port) throws IOException {
serverSocket = new ServerSocket(port);
}
private void handle(Socket socket) throws IOException {
System.err.println("client connected");
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// Create a PrintWriter with buffer size 1
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()), 1));
try {
for (String line = in.readLine(); line != null; line = in.readLine()) {
out.print(line + "\n");
out.flush();
}
} finally {
out.close();
in.close();
}
}
public void serve() throws IOException {
while (true) {
// block until a client connects
Socket socket = serverSocket.accept();
try {
handle(socket);
} catch (IOException ioe) {
ioe.printStackTrace(); // but don't terminate serve()
} finally {
socket.close();
}
}
}
public static void main(String[] args) {
try {
Server server = new Server(4949);
server.serve();
} catch (IOException e) {
e.printStackTrace();
}
}
}
This may seem like an obvious question, but why is the input buffer to the Client not filling up and causing deadlock? The Client sends 10000 numbers before ever reading any replies. Wouldn't this cause the client's receive buffer to fill up, also causing the server's sending buffer to fill up? I even make the buffer size for the BufferedReader and BufferedWriter as small as possible.However, when I run this code, there is no deadlock.

Because you're overlooking the existence of the socket send buffer at the sender, and the socket receive buffer at the receiver. These are in the kernel, and they can clearly hold all the server's output between them.

Related

OutputStreamWriter and InputStreamReader for a Socket in Java, What am I doing wrong?

Using Sockets in java,
public class Server {
private static ServerSocket server;
private static int port = 9876;
static Socket p1 = null;
static Socket p2 = null;
public static void main(String args[]) throws IOException, ClassNotFoundException{
server = new ServerSocket(port);
Thread p1t = new Thread(new Runnable() {
#Override
public void run() {
try {
System.out.println("[Server] Waiting for connection");
p1 = server.accept();
System.out.println("[Server] Client connected");
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(p1.getOutputStream()));
BufferedReader in = new BufferedReader(new InputStreamReader(p1.getInputStream()));
String msg = String.valueOf(in.readLine());
System.out.println(msg);
out.write(msg);
} catch (Exception e) {
e.printStackTrace();
}
}
});
p1t.start();
}
}
and
public class Client {
public static void main(String[] args) throws UnknownHostException, IOException, ClassNotFoundException, InterruptedException{
Socket socket = new Socket(InetAddress.getLocalHost().getHostName(), 9876);
if(socket.isConnected()) {
System.out.println("[Client] Connected");
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
new Thread(new Runnable() {
#Override
public void run() {
while(true) {
try {
System.out.println(in.readLine());
} catch (IOException e) {
e.printStackTrace();
}
}
}
}).start();
while(true) {
Scanner s = new Scanner(System.in);
out.write(s.nextLine());
}
}
}
}
The client is supposed to send a message to the server, and the server is supposed to relay that message back to the client; but either the BufferedReader for Client and Server are not reading anything that is sent, or the BufferedWriter for Client and Server is not sending anything.
I've also tried manually sending text using out.write("test"); in both classes.
What am I doing wrong in this situation?

Java client-server

This problem is bugging me for over a day now and I cannot find a fix for it.I am writing a chat application in Java.The problem is that the server cannot send messages to the clients,but can only receive it.Here are my classes:
Server class:
public class Server implements Runnable {
static InetAddress address;
static ArrayList<Integer> clients=new ArrayList<Integer>();
static ArrayList<Socket> socs=new ArrayList<>();
static String message="";
static DataOutputStream toClient;
static ServerSocket socket;
static Socket socketNew;
static boolean running=false;
public Server(InetAddress address){
this.address=address;
}
public static void main(String[] args) throws IOException
{
socket=new ServerSocket(8000);
System.out.println("Server started on port 8000");
running=true;
while(true)
{
socketNew=socket.accept();
socs.add(socketNew);
address=socketNew.getInetAddress();
System.out.println("connected to client at address: "+address);
Server server=new Server(address);
new Thread(server).start();
}
}
public void run() {
{
try {
BufferedReader br = new BufferedReader(new InputStreamReader(socketNew.getInputStream()));
String message=br.readLine();
System.out.println(message);
for(Socket s:socs) //sending the above msg. to all clients
{
OutputStream os=os = s.getOutputStream();
PrintWriter pw = new PrintWriter(os, true);
pw.write(message);
pw.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void message() {
}
}
Here is my client class' relevant functions:
private void receive_data()
{
BufferedReader br;
try {
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String message=br.readLine();
console(message);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void send_data() {
OutputStream os;
try {
os = socket.getOutputStream();
PrintWriter pw = new PrintWriter(os, true);
pw.println(this.name+": "+textField.getText());
pw.flush();
textField.setText("");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Also,the server stop taking any messages from the client after the very first message.I thought that problem can be eliminated by enclosing the contents of the run() method in server class inside while loop.But it is throwing exceptions that way.Any solutions to the above problem?
public void run() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(socketNew.getInputStream()));
String message;
PrintWriter out;
while ((message = br.readLine()) != null) {
for (Socket s : socs) // sending the above msg. to all clients
{
out = new PrintWriter(s.getOutputStream(), true);
out.println(message);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
There you go. Tested it with a small client i quickly wrote myself and it works.
And you definitely should work on your code formatting. (mainly those scope brackets that are there for no reason.)

Sending bulk messages to all clients

I would like to know, how to send messages to all connected clients. To be more specific - to all ServerThreads.
Here are my classes:
public class Client {
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws IOException {
Socket kkSocket = null;
PrintWriter out = null;
BufferedReader in = null;
try {
kkSocket = new Socket("127.0.0.1", 4444);
out = new PrintWriter(kkSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(kkSocket.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("Don't know about host: localhost.");
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to: localhost.");
System.exit(1);
}
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
String fromUser, fromServer;
while (!(fromUser = stdIn.readLine()).equalsIgnoreCase("#quit")) {
out.println(fromUser);
fromServer = in.readLine();
System.out.println(fromServer);
}
out.close();
in.close();
stdIn.close();
kkSocket.close();
}
}
Server: http://pastebin.com/ZpBydK58
ServerThread: http://pastebin.com/CwAM72c3
Assign each new ServerThread to a array. Then you can make a method in Server that loops through the ServerThread array and sends a message to each, and in ServerThread make a method to send a message.
Example:
public class Server {
public final static int maxClients = 10000;
public final static ServerThread[] clients = new ServerThread[maxClients];
public static int numOfClients = 0;
public static ServerSocket server;
public static void main(String[] args){
try{
server = new ServerSocket(4444);
while (numOfClients<maxClients){
clients[numOfClients+1] = new ServerThread(server.accept());
numOfClients++;
clients[numOfClients].start();
}
while (true){
server.accept().close();
}
}catch(Exception error){error.printStackTrace();}
}
public static void sendMessage(String message){
for (int i=0;i<numOfClients;i++){
clients[i].sendMessage(message);
}
}
}

Null pointer exception occurs while trying to read repeatedly from an InputStream

The code works fine when I close the client just after sending one instruction. But when I want a client and server connection to persist, so that the client can send multiple instructions to the server one after another, I get a Null pointer exception at the server and the message java.net.SocketException: Socket is closed at the client. This happens after the client sends a file to the server and the server successfully receives it. Need help. The error occurs at the Connection class code line switch(clientMsg). It seems to me that for some reason the BufferedReader in goes null, but I might be mistaken about that. The code is as follows. Thanks.
Server
public class server {
private static ServerSocket serverSocket;
private static Socket socket = null;
public static void print(Object s) {
System.out.println(s);
}
#SuppressWarnings("resource")
public static void main (String args[]) throws IOException {
System.out.print("Specify listening port: ");
Scanner _a = new Scanner(System.in);
int a = _a.nextInt();
try{
serverSocket = new ServerSocket(a);
}
catch(IOException e) {
System.out.println(e);
}
while (true) {
try {
socket = serverSocket.accept();
print("Connected to " + socket);
Thread client = new Thread(new Connection(socket));
client.start();
}
catch (IOException e) {
print(e);
}
}
}
}
Connection
public class Connection implements Runnable {
public static void print(Object s) {
System.out.println(s);
}
private Socket socket;
private BufferedReader in = null;
public Connection(Socket client) {
this.socket = client;
}
#Override
public void run(){
try {
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
String clientMsg;
while (true) {
clientMsg = in.readLine();
switch (clientMsg) {
case "1":
receiveFile(); //method code not included
break;
default:
print("Command not recognized");
break;
}
//in.close();
}
}//try run()
catch (IOException e) {
print(e);
}
}
Client
public class client {
private static Socket connectToServer;
private static String fileName;
private static BufferedReader keybrdIn;
private static PrintStream msgToServer;
public static void println(Object e) {
System.out.println(e);
}
public static void print(Object e) {
System.out.print(e);
}
public static void main(String args[]) throws IOException{
try{
print("Enter IP: ");
String ip = new Scanner(System.in).nextLine();
print("Enter port: ");
int port = new Scanner(System.in).nextInt();
connectToServer = new Socket(ip, port);
keybrdIn = new BufferedReader(new InputStreamReader(System.in));
}catch(IOException e) {
println(e);
}
msgToServer = new PrintStream(connectToServer.getOutputStream());
while (true) {
try {
switch(Integer.parseInt(action())) { //action() method code not included
case 1:
msgToServer.println("1");
sendFile();
break;
default:
println("Invalid input");
break;
}
}catch (IOException e) {
println(e);
}
}
}
sendFile()
public static void sendFile() throws IOException {
print("Enter file name: ");
fileName = keybrdIn.readLine();
File file = new File(fileName);
byte[] bytearray = new byte[8192];
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
DataInputStream dis = new DataInputStream(bis);
OutputStream os = connectToServer.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
dos.writeUTF(file.getName());
int count;
while ((count = dis.read(bytearray)) > 0){
dos.write(bytearray, 0, count);
}
dis.close();
dos.flush();
dos.close();
}
receiveFile()
public void receiveFile() {
try {
int count;
DataInputStream clientFileStream = new DataInputStream(socket.getInputStream());
String fileName = clientFileStream.readUTF();
OutputStream fileOutput = new FileOutputStream("_" + fileName);
byte[] mybytearray = new byte[8192];
BufferedOutputStream bos = new BufferedOutputStream(fileOutput);
System.out.println("Downloading " + fileName + " ...");
//outToClient().writeBytes("Uploading. Please wait...\n");
while ((count = clientFileStream.read(mybytearray)) > 0){
bos.write(mybytearray, 0, count);
}
fileOutput.close();
bos.close();
clientFileStream.close();
}
catch (IOException e) {
print(e);
}
}
In sendFile(), you close the data output stream which closes your underlying connection's output stream.
According to the documentation of Socket.getOutputStream():
"Closing the returned OutputStream will close the associated socket".
Since you already closed stream, it will also close socket as well as Eyal mentioned. However, at the moment you close the stream, server side will aware of that and return -1 for read() results.
So, even if you didn't specify file length at beginning, this will generally works well.
However, since you already closed stream, you can't reuse it no matter what. To fix this issue, probably you need to change your Client class so that Client should create socket connection, send files, close socket. That's one lifecycle of opened client socket.
Or maybe in while loop of Client class, 1) take ip, port, and filename to send 2) Create new Thread and provide those information so let thread open connection, send file, close connection 3) and in the meantime, client while() can keep take next ip, port, and filename to send from the user. By doing this, you don't need to make client program wait until file transfer to be completed.
Regarding the NPE in the server, readLine() returns null at end of stream. You are ignoring it. You should be testing for it immediately after the call, and if null close the socket and exit the read loop.

Java Server And Client Socket Need Fix

Hello, I am new to java socket programming and I was just looking to see if somebody could give me some help.
I will post the code for the client and server then i will explain my problem...
reader = new BufferedReader(new InputStreamReader(socket.getInputStream));
while(running)
{
String line = reader.readLine();
if(line != null)
{
System.out.println(line);
stream = new PrintStream(socket.getOutputStream());
stream.println("return: " + line);
}
}
}catch(IOException e)
{
System.out.println("Socket in use or not available: " + port);
}
}
public static void main()
{
run();
}
//Client
public static String ip;
public static int port;
public static Socket socket;
public static PrintStream stream;
public static BufferedReader reader;
public static void main(String args[])
{
try
{
socket = new socket(ip, port);
stream = new PrintStream(socket.getOutputStream());
stream.println("test0");
reader = new BufferedReader(new InputStreamReader(socket.getInputStream));
String line = reader.readLine();
if(line != null)
{
System.out.println(line);
}
stream.println("test1");
line = reader.readLine();
if(line != null)
{
System.out.println(line);
}
}catch(IOException e)
{
System.out.println("could not connect to server!");
}
}
So my problem is even if I get rid of the loop and try to make it send the string twice it won't send it. It will only do it once unless I close and make a new socket on the client side. So if anybody could give me an explanation to what I am doing wrong that would be great, and thank you so much.
Why are you openning your outstream inside your loop?
stream = new PrintStream(socket.getOutputStream());
Take this statement outside the loop and write to your stream inside your loop.
Please keep it simple,
Try using InputStream, InputStreamReader, BufferedReader, OutputStream, PrintWriter.
Client Side:
Socket s = new Socket();
s.connect(new InetSocketAddress("Server_IP",Port_no),TimeOut);
// Let Timeout be 5000
Server Side:
ServerSocket ss = new ServerSocket(Port_no);
Socket incoming = ss.accept();
For Reading from the Socket:
InputStream is = s.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
boolean isDone = false;
String s = new String();
while(!isDone && ((s=br.readLine())!=null)){
System.out.println(s); // Printing on Console
}
For Writing to the Socket:
OutputStream os = s.getOuptStream();
PrintWriter pw = new PrintWriter(os)
pw.println("Hello");
Make sure you flush the output from your server:
stream.flush();
Thanks a lot to everybody who answered but i figures out what it was all along.
i read through some of the Oracle socket stuff and figured out that the server was supposed to be the first to send a message than the client receive and send and receive... so on and so forth so i will post my new code here in hopes somebody else trying to figure out the same thing can find it with ease
//Client
public static String ip;
public static int port;
public static Socket socket;
public static PrintWriter print;
public static BufferedReader reader;
public Client(String ip, int port)
{
this.ip = ip;
this.port = port;
//initiate all of objects
try
{
socket = new Socket();
socket.connect(new InetSocketAddress(ip, port), 5000);
print = new PrintWriter(socket.getOutputStream());
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//start connection with server
String line = reader.readLine();
System.out.println(line);
} catch (IOException e)
{
e.printStackTrace();
}
}
//quick method to send message
public void sendMessage(String text)
{
print.println(text);
print.flush();
try
{
String line = reader.readLine();
System.out.println(line);
} catch (IOException e)
{
e.printStackTrace();
}
}
}
public static void main(String args[])
{
client.sendMessage("test");
client.sendMessage("test2");
client.sendMessage("test3")
}
//Server
public static int port = 9884;
public static boolean running = true;
public static ServerSocket serverSocket;
public static Socket socket;
public static PrintWriter writer;
public static BufferedReader reader;
public static void run()
{
try
{
serverSocket = new ServerSocket(port);
socket = serverSocket.accept();
writer = new PrintWriter(socket.getOutputStream(), true);
writer.println("connection");
while(running)
{
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = reader.readLine();
if(line != null)
{
System.out.println(line);
writer.println(line);
writer.flush();
}
}
} catch (IOException e)
{
e.printStackTrace();
}
}
public static void main(String args[])
{
run();
}

Categories