I have this code and for some reason it stucks at readline() line at servers end always waiting from client but client on the other end sends the data.
Both the server and client's code is available below.
Server Code
import java.io.*;
import java.net.*;
public class TCPServer {
public static final int SERVER_PORT = 6789;
public static void main(String argv[]) throws Exception {
String clientSentence;
String capitalizedSentence;
ServerSocket welcomeSocket = new ServerSocket(SERVER_PORT);
while (true) {
Socket connectSocket = welcomeSocket.accept();
InputStream sin = connectSocket.getInputStream();
BufferedReader inFromClient = new BufferedReader(new InputStreamReader(sin));
PrintWriter outToClient = new PrintWriter(connectSocket.getOutputStream(), true);
clientSentence = inFromClient.readLine();
capitalizedSentence = clientSentence.toUpperCase() + "\r\n";
outToClient.print(capitalizedSentence);
}
}
}
Client Code
import java.io.*;
import java.net.Socket;
public class TCPClient {
public static void main(String[] args) throws Exception {
String hostName = "localhost";
int port = 6789;
String sentence;
String modifiedSentence;
BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in));
Socket clientSocket = new Socket(hostName, port);
PrintWriter outToServer = null;
clientSocket.getOutputStream();
BufferedReader inFromServer = null;
inFromServer=new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
sentence = inFromUser.readLine();
outToServer.print(sentence + "\r\n");
modifiedSentence = inFromServer.readLine();
System.out.println("FROM SERVER: " +modifiedSentence);
clientSocket.close();
}
}
After fixing your syntax errors around outToServer, I think the problem lies in the way you're using PrintWriter around the output stream on the client's side. From the documentation:
Unlike the PrintStream class, if automatic flushing is enabled it will
be done only when one of the println, printf, or format methods is
invoked, rather than whenever a newline character happens to be
output. These methods use the platform's own notion of line separator
rather than the newline character.
Since you're using print with a manually appended new line, the message is never flushed to the socket's output stream. I believe you can fix this by using println instead:
outToServer.println(sentence);
Even better would be to use DataInputStream and DataOutputStream instead of BufferedReader and PrintWriter, as those are better suited for sending and receiving arbitrary data over a socket stream.
Related
I'm working on a basic Client-Server connection.
This code works perfectly yet the client can only send 1 message and receive its modification before closing the connection.
how can I make it to send and receive multiple messages?
I thought of using a while loop yet I didn't know how to implement it correctly.
I need to be able to send more than 1 message in order to have a consistent connection
The code below is a client sending a string to the server and the server turns it to uppercase.
//Server:
public class TCPServer {
public static void main(String argv[]) throws Exception
{
String clientSentence;
String capitalizedSentence;
ServerSocket welcomeSocket = new ServerSocket(6789);
while(true)
{
Socket connectionSocket = welcomeSocket.accept();
BufferedReader inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());
clientSentence = inFromClient.readLine();
capitalizedSentence = clientSentence.toUpperCase() + '\n';
outToClient.writeBytes(capitalizedSentence);
if(clientSentence.toUpperCase().trim().contentEquals("QUIT")) {
connectionSocket.close();
}
}
}
}
//Client:
public class TCPClient {
public static void main(String argv[]) throws Exception
{
String sentence;
String modifiedSentence;
Socket clientSocket = new Socket("LocalHost", 6789);
BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in));
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
System.out.print("Enter characters to be capitalized: ");
sentence = inFromUser.readLine();
outToServer.writeBytes(sentence + '\n');
modifiedSentence = inFromServer.readLine();
System.out.println("FROM SERVER: " + modifiedSentence);
}
}
the output for this code is:
Enter characters to be capitalized: hi
FROM SERVER: HI
Your Server can gets only one message from each client, because in your while-loop, in each iteration you call to welcomeSocket.accept(). This means that your server code stops until it gets new client connection.
Consider to use multi-threading if you want your server will support multiple clients. For example, take a look: on this post
I've the following Server.java:
public class Main {
public static void main(String args[]) throws Exception{
ServerSocket server = new ServerSocket(12345);
Socket client = server.accept();
OutputStream out = client.getOutputStream();
BufferedWriter writer = new BufferedWriter(new PrintWriter(out));
writer.write("Hello client");
writer.flush(); //After executing of that instruction there is no any output on the client
client.close(); //The client prints "Hello client"
}
}
and the Client.java:
public class Main {
#SuppressWarnings("resource")
public static void main(String args[]) throws Exception{
Socket s = new Socket("localhost", 12345);
BufferedReader r = new BufferedReader(new InputStreamReader(s.getInputStream()));
System.out.println(r.readLine());
s.close();
}
}
The issue is I can't get the reason why the client prints the string only after the connection was closed, but not after the stream was flushed. I thought flush() send a signal to the client that data-transfering process is over. Since, the client have to read all the data that was being send to it before calling flush(). What's wrong?
readLine() reads a complete line. To know that the line is complete, the reader needs to either find a newline character sequence, or the end of the stream. So it blocks until it sees one of those.
Realize that your client might very well do the following:
out.write("Hello ");
out.flush();
out.write("world!\n");
out.flush();
This sends a single line: "Hello world". And readLine() as its name indicates, is supposed to return that, not 2 lines "Hello " and "World".
So, if you want to send a line, you need to end its line terminator. Otherwise you're not sending a line, but only some characters.
Note that it would be easier if you used a PrintWriter correctly:
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(client.getOutputStream())));
out.println("Hello client");
i'm trying to create a simple java program where the client and the server will be both able to send and get strings and ints. I can do it work with only strings or only ints but i find it hard to combine them without making a mess. If someone can tell me the easiest way to do it i would be thankfull. Here is what i've done till now but it gives the wrong number back.
MyServer.java
package myserver;
import java.io.DataInputStream;
import java.util.Random;
import java.io.*;
import java.net.*;
public class MyServer
{
public static void main(String argv[]) throws Exception
{
String clientSentence;
String answer;
ServerSocket welcomeSocket = new ServerSocket(6789);
Socket connectionSocket = welcomeSocket.accept();
BufferedReader inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());
clientSentence = inFromClient.readLine();
Random rand = new Random();
int n = rand.nextInt(100) + 1;
System.out.println("Received: " + clientSentence);
answer = "Hey " + clientSentence + " guess a number from 1 to 100!" + '\n';
outToClient.writeBytes(answer);
DataInputStream integerFromClient = new DataInputStream(connectionSocket.getInputStream());
int k = integerFromClient.readInt();
System.out.println(k);
}
}
MyClient.java
package myserver;
import java.io.*;
import java.net.*;
class MyClient
{
public static void main(String argv[]) throws Exception
{
String sentence;
String modifiedSentence;
BufferedReader inFromUser = new BufferedReader( new InputStreamReader(System.in));
Socket clientSocket = new Socket("localhost", 6789);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
sentence = inFromUser.readLine();
outToServer.writeBytes(sentence + '\n');
modifiedSentence = inFromServer.readLine();
System.out.println("SERVER: " + modifiedSentence);
int k = inFromUser.read();
outToServer.writeInt(k);
clientSocket.close();
}
}
I suggest you use DataInputStream/DataOutputStream wrapped around BufferedInputStream/BufferedOutputStream. This will allow you to send
dos.writeUTF(string);
String s = dis.readUTF();
or
dos.writeInt(n);
int i = dis.readInt();
if you don't know what type you are going tow rite you can use a byte like this.
dos.writeByte('S');
dos.writeUTF(string);
dos.writeByte('i');
dos.writeInt(n);
and
for(int code; (code = dis.read()) != -1;) {
switch(code) {
case 'S':
String s = dis.readUTF();
process(s);
break;
case 'i':
int i = dis.readInt();
process(i);
break;
default:
throw new StreamCorruptedException("code: "+code);
}
}
You can extend this to sending complex data structures.
The "mess" in this case is just your message structure. You are sending the raw value over the socket with no information about what the value is, this makes it hard for the recipient to determine what data the value might be. I guess that is the main problem.
I would suggest that you pick a pre-existing format that lets you combine data types into one message. I would suggest JSON or xml, which are (un)marshallable very easily with a respective library.
Otherwise you could look into something simpler like the bencoding structure, combining the int 3 and the string "hello" into one message would look like this:
i3e5:hello
I have implement the simple TCP server and TCP client classes which can send the message from client to server and the message will be converted to upper case on the server side, but how can I achieve transfer files from server to client and upload files from client to server. the following codes are what I have got.
TCPClient.java:
import java.io.*;
import java.net.*;
class TCPClient {
public static void main(String args[]) throws Exception {
String sentence;
String modifiedSentence;
BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in));
Socket clientSocket = new Socket("127.0.0.1", 6789);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
sentence = inFromUser.readLine();
outToServer.writeBytes(sentence + "\n");
modifiedSentence = inFromServer.readLine();
System.out.println("FROM SERVER:" + modifiedSentence);
clientSocket.close();
}
}
TCPServer.java:
import java.io.*;
import java.net.*;
class TCPServer {
public static void main(String args[]) throws Exception {
int firsttime = 1;
while (true) {
String clientSentence;
String capitalizedSentence="";
ServerSocket welcomeSocket = new ServerSocket(3248);
Socket connectionSocket = welcomeSocket.accept();
BufferedReader inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());
clientSentence = inFromClient.readLine();
//System.out.println(clientSentence);
if (clientSentence.equals("set")) {
outToClient.writeBytes("connection is ");
System.out.println("running here");
//welcomeSocket.close();
//outToClient.writeBytes(capitalizedSentence);
}
capitalizedSentence = clientSentence.toUpperCase() + "\n";
//if(!clientSentence.equals("quit"))
outToClient.writeBytes(capitalizedSentence+"enter the message or command: ");
System.out.println("passed");
//outToClient.writeBytes("enter the message or command: ");
welcomeSocket.close();
System.out.println("connection terminated");
}
}
}
So, the TCPServer.java will be executed first, and then execute the TCPClient.java, and I try to use the if clause in the TCPServer.java to test what is user's input,now I really want to implement how to transfer files from both side(download and upload).Thanks.
So lets assume on server side you have received the file name and file path. This code should give you some idea.
SERVER
PrintStream out = new PrintStream(socket.getOutputStream(), true);
FileInputStream requestedfile = new FileInputStream(completeFilePath);
byte[] buffer = new byte[1];
out.println("Content-Length: "+new File(completeFilePath).length()); // for the client to receive file
while((requestedfile.read(buffer)!=-1)){
out.write(buffer);
out.flush();
out.close();
}
requestedfile.close();
CLIENT
DataInputStream in = new DataInputStream(socket.getInputStream());
int size = Integer.parseInt(in.readLine().split(": ")[1]);
byte[] item = new byte[size];
for(int i = 0; i < size; i++)
item[i] = in.readByte();
FileOutputStream requestedfile = new FileOutputStream(new File(fileName));
BufferedOutputStream bos = new BufferedOutputStream(requestedfile);
bos.write(item);
bos.close();
fos.close();
Assuming you want to continue to support sending messages as well as sending files back and forth...
As you have now, you are using writeBytes to send data from client to server.
You can use that to send anything, like the contents of files...
But you will need to define a protocol between your client and server so that they know when a file is being transferred rather than a chat message.
For example you could send the message/string "FILECOMING" before sending a file to the server and it would then know to expecting the bytes for a file. Similarly you'd need a way to mark the end of a file too...
Alternatively, you could send a message type before each message.
A more performant/responsive solution is to do the file transfer on a separate thread/socket - this means that the chat messages are not held up by the transfers. Whenever a file transfer is required, a new thread/socket connection is created just for that.
~chris
import java.io.*;
import java.net.*;
class TCPClient
{
public static void main(String argv[]) throws IOException
{
String sentence;
String modifiedSentence;
Socket clientSocket = new Socket("*localhost*", *portnum*); // new Socket("192.168.1.100", 80);
System.out.println("Enter your ASCII code here");
BufferedReader inFromUser = new BufferedReader( new InputStreamReader(System.in));
sentence = inFromUser.readLine();
// System.out.println(sentence);
while(!(sentence.isEmpty()))
{
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
outToServer.writeBytes(sentence);
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
modifiedSentence = inFromServer.readLine();
while(!(modifiedSentence.isEmpty()))
{
System.out.println("FROM SERVER: " + modifiedSentence);
break;
}
System.out.println("Enter your ASCII code here");
inFromUser = new BufferedReader( new InputStreamReader(System.in));
sentence = inFromUser.readLine();
}
System.out.println("socket connection going to be close");
clientSocket.close();
}
}
This question already has an answer here:
to read the packet of bytes on client(client Socket) from server(ServerSocket) using java
(1 answer)
Closed 7 years ago.
i m creating connection oriented server/client(TCP) socket.i have created whole server socket and i have written packet on server socket successfully and i have created client socket also but i m not be able to read packet so please give me the idea about read the packet(code or example) on client socket and tell clearly that can i read a packet on client socket or not if no then what should use in place of client and server socket
You don't generally read a packet at a time - you read from the InputStream returned by Socket.getInputStream(). You should almost certainly be treating the connection as a stream, rather than even attempting to handle individual packets.
If you still run into problems, it would really help if you could post some code to show how you're connecting the socket etc.
I had to implement such a thing for my networking course in college.
Here's an excerpt from the book
TCPServer.java
import java.io.*;
import java.net.*;
class TCPServer
{
public static void main(String argv[]) throws Exception
{
String clientSentence;
String capitalizedSentence;
ServerSocket welcomeSocket = new ServerSocket(6789);
while(true)
{
Socket connectionSocket = welcomeSocket.accept();
BufferedReader inFromClient =
new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());
clientSentence = inFromClient.readLine();
System.out.println("Received: " + clientSentence);
capitalizedSentence = clientSentence.toUpperCase() + '\n';
outToClient.writeBytes(capitalizedSentence);
}
}
}
TCPClient.java
import java.io.*;
import java.net.*;
class TCPClient
{
public static void main(String argv[]) throws Exception
{
String sentence;
String modifiedSentence;
BufferedReader inFromUser = new BufferedReader( new InputStreamReader(System.in));
Socket clientSocket = new Socket("localhost", 6789);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
sentence = inFromUser.readLine();
outToServer.writeBytes(sentence + '\n');
modifiedSentence = inFromServer.readLine();
System.out.println("FROM SERVER: " + modifiedSentence);
clientSocket.close();
}
}
Hopefully this will be sufficient to figure out what you did wrong. Good luck!