Keep client to server connection open and close on request - java

I have a TCP client application in Java, through this application i can communicate with a server application.
I have a simple method sendCommand which sends the message to the server:
void sendCommand(String command) throws IOException {
String ipaddress = "192.168.0.2";
Socket commandSocket = null;
PrintWriter out = null;
BufferedWriter out = null;
BufferedReader in = null;
BufferedWriter outToDetailFile = null;
FileWriter fstream = null;
String version = "";
int numberOfBallsInGame;
int ledCycleState = 1;
commandSocket = new Socket(ipaddress, 7420);
out = new BufferedWriter(new OutputStreamWriter(commandSocket.getOutputStream()));
in = new BufferedReader(new InputStreamReader(commandSocket.getInputStream()));
out.write("c");out.flush();
out.write(command);out.flush();
String message = in.readLine();
//System.out.println(message);
out.close();
in.close();
commandSocket.close();
}
Now, because the server application is on the machine which does not accept more than 2 connections in 20 seconds i need to modify my method and "split" it in 3 different methods (i think).
My plan is the following:
I would like to call the connection to the server in one thread, keep it opened untill i want to close it, but i should be able to send the commands between opening the connection and closing it.
I'm pretty new to Java and i'll try to explain here exactly what i want to do:
1) I want to open the connection to TCP server.
2) After opening the connection i want to be able to send commands to an already opened connection by calling this method:
void sendCommand(String command) throws IOException {
out.write("c");out.flush();
out.write(command);out.flush();
}
And after i'm finished with sending commands i want to call some method to close my running connection.
Because i'm pretty new to java it would be very nice if someone could show me how to achieve this or modify my method.
Thank you in advance,

Related

send objects from server to client in java sockets

I want to send objects from the server to the client in java sockets. I can send them from client to the server, however I am struggling to send them from server to client. I am new to Java so I'm still learning the basics. I know its something relatively minor that I need to do, however i am struggling with it at the moment. Can someone add the bits of code that i am missing?
Open another connection in another thread and let the client be server, and server be client. So in one thread you send A -> B, in another thread you open another socket and begin to send b B -> A.
The problem with low level sockets is that if one side is writing, the other should be listening. That means you have to implement command-query protocol, which is a heavy task. So with my proposal you will use two ports but you know that you will have 2 pipes of data flow.
A --8888--> B
A <--8889-- B
It will be easier if you are just starting with sockets.
You can use ObjectOutputStream to send an object through the socket and ObjectInputStream to receive one:
private ObjectOutputStream oos;
private ObjectInputStream ois;
public SocketHandler(Socket cs) {
this.oos = new ObjectOutputStream(cs.getOutputStream());
this.ois = new ObjectInputStream(cs.getInputStream());
}
public void sendObject(Object o) {
this.oos.writeObject(o);
this.oos.flush();
}
public Object receiveObject() {
return this.ois.readObject();
}
That was assuming you want to send and receive an Object. You can also use PrintWriter and BufferedReader to send and receive String messages and after parsing it:
private PrintWriter pw;
private BufferedReader br;
public SocketHandler(Socket cs) {
this.pw = new PrintWriter(cs.getOutputStream());
this.br = new BufferedReader(new InputStreamReader(cs.getInputStream()));
}
public void sendMsg(String msg) {
this.pw.println(msg);
this.pw.flush();
}
public String receiveMsg() {
return this.br.readLine();
}
Below I have an example of some Server-Side code that I used for an application a while ago, then I will give you an explanation as to what's going on here:
first you need to create your ServerSocket in order to accept client requests (as you already know):
ServerSocket serverSocket = new ServerSocket(1002);
while(true) {
Then you need to enter a while loop in order to receive requests for as long as the Server program is alive
Socket clientSocket = serverSocket.accept();
System.out.println("Connection made to: " + clientSocket);
BufferedReader br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
String messageString = "";
String line;
System.out.println("Enter while loop to retrieve client message...");
while((line = br.readLine()) != null) {
String clientRequestLine = line;
if(clientRequestLine.contains("check return user credentials")) {
String userNamePassWord = clientRequestLine.replace("check return user credentials", "");
userNamePassWord = userNamePassWord.trim();
String[] userNamePassWordSplitter = userNamePassWord.split(" ");
String userName = userNamePassWordSplitter[0];
String passWord = userNamePassWordSplitter[1];
System.out.println("Username: " + userName + "\nPassword: " + passWord);
boolean isValidUserNamePassWord = ReturnPatientCredentials.checkUserNamePassWord(userName, passWord);
if(isValidUserNamePassWord) {
System.out.println("valid");
out.println("valid");
}
else {
System.out.println("invalid");
out.println("invalid");
}
}
Above you need to start a BufferedReader in order to store an InputStream (the data) from the client socket. You also need to create a PrintWriter so that you can send data to the OutputStream and you need to pass your clientSocket as the argument for the OutputStream. Next you'll create variables to get the message and the "line" of date from the client and enter a while loop. You can then store the line in a variable and read the data or whatever you need to do. We use our PrintWriter (out) to send data back with the println() method and then we can break out of the loop when needed.

Java Message sent from client to server

I'm using a socket to connect my client with the server, I need a way so that when somebody tries to login on the client with an account, it sends the username and password to the server, and checks if the account exists. I just need to know how to make it send the message to the server when they press login.
i tried this to make it send a message to the server
public static void sendmsg(String a, String b)
{
try
{
String host = "127.0.0.1";
int port = 43655;
InetAddress address = InetAddress.getByName(host);
socket = new Socket(address, port);
//Send the message to the server
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
String sendMessage = a;
bw.write(sendMessage);
bw.flush();
System.out.println("Message sent to the server : "+sendMessage);
//Get the return message from the server
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String message = br.readLine();
System.out.println("Message received from the server : " +message);
}
catch (Exception exception)
{
exception.printStackTrace();
}
finally
{
//Closing the socket
try
{
socket.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
nice you are working with Sockets, well I have an approach you can try, and maybe if it is useful you can consider for your implementation.
First of all I will create an entity to handle those values and fill it with the incoming data.
class UserAuth {
private String username;
private String password;
//Consider here your getters and setters, I am not including them
}
I will use the entity as the parameter for the method while sending and maybe you can fill it as something like:
UserAuth attemptingUser = new UserAuth(...)
ObjectInputStream works fine for these kind of scenarios. If you still want to work with Strings, you can use BufferedReader and try to merge your username and password as one single String and use the .readLine() method to obtain (separated with commas), then use String methods such Split but I find that could take some more time, should be better if you handle it with an object. But it depends on the complexity you want to add to your application :).
class AuthClient {
public void sendMsg(UserAuth attemptingUser) {
String host = "localhost";
int port = 2055;
//1. Create the socket
Socket sender = new Socket(host, port);
//2. Create an object output stream to write the object into the stream
ObjectOutputStream outputWriter = new ObjectOutputStream(sender.getOutputStream());
//3. Write (send the object)
outputWriter.writeObject(attemptingUser);
//4. Close
outputWriter.close();
sender.close();
}
}
class AuthServer {
ServerSocket ss = new ServerSocket(2055);
public void receiveMsg() {
//1. Accept the connection
Socket conn = ss.accept();
//2. Receive the flow
ObjectInputStream readStream = new ObjectInputStream(conn.getInputStream());
//3. Read the object
UserAuth userReceived = readStream.readObject();
//4. Verify against file, db or whatever
if (userReceived.getUsername().equals("admin") && userReceived.getPassword().equals("admin")) {
//Authentication
}
}
}
(This is added as the part I edit for what you asked me in the comments)
public void sendMsg(String username, String password) {
String host = "localhost";
int port = 2055;
//1. Create the socket
Socket sender = new Socket(host, port);
//2. Create the UserAuth object based on the parameters you received
UserAuth myuser = new UserAuth();
myuser.setUsername(username);
myuser.setPassword(password);
//3. Follow same instructions for the creation of ObjectOutputStream...
ObjectOutputStream objectWriter = new ObjectOutputStream(sender.getOutputStream());
objectWriter.writeObject(myuser);
//That is what I would use if I keep your structure
}
If you want to keep your structure using Strings, I would simplify and reduce impact of I/O by using the String methods. Since you know you are always expecting user/password, I would merge your two params in one single String or use special char and on server side handle with StringTokenizer class. Or maybe handle with the "split" method. You have many options here.
So far, this will be my approach for the problem you are facing. Hope it helps somehow. Best regards and happy coding :).
What you have done looks OK to me but it all depends on what the server is expecting to receive. What is the terminating character as you have not sent one unless it's already contained within your String a variable.
If the server is expecting an end of line character (which you don't currently send) you can use a PrintWriter instead of a BufferedWriter like this
pw = new PrintWriter(socket.getOutputStream(), true);
pw.println(a);
Your server would then be doing something like this
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String value = br.readLine();

TCP/IP communication thread

I want to make a TCP/IP communication in Java but i want to open the TCP/IP port, send commands and then close that port.
I know i can open connection, send command, and then close connection in one method but the problem is: the machine i'm connecting to can't accept more that 5 connections and when the connection closes machine won't accept any other connection for about 6 seconds.
My goal is to open connection in one thread, send commands for some time and then after i'm finished i want to close connection.
This is how i'm doing it now:
void sendCommand(String command) throws IOException {
String ipaddress = "192.168.0.2";
Socket commandSocket = null;
PrintWriter out = null;
BufferedWriter out = null;
BufferedReader in = null;
BufferedWriter outToDetailFile = null;
FileWriter fstream = null;
commandSocket = new Socket(ipaddress, 7420);
out = new PrintWriter(commandSocket.getOutputStream(), true);
out = new BufferedWriter(new OutputStreamWriter(commandSocket.getOutputStream()));
in = new BufferedReader(new InputStreamReader(commandSocket.getInputStream()));
out.write("c");out.flush();
out.write(command);out.flush();
String message = in.readLine();
//System.out.println(message);
out.close();
in.close();
commandSocket.close();
}
I basicaly need to split this method in 3 parts, one part which I call to open the connection, 2nd part to send commands (i need to send commands from my swing form) and then when i'm finished with sending commands i need to close connection on button click (or any other event).
The question is: How to send commands in already opened connection and then close that connection when i'm finished with sending commands.
I'm trying to achieve something like this
-Method openConnection should open connection.
-Method sendCommand should send (multiple commands at random time intervals (every 5-10 seconds)) connection to already opened socket (opened with method opneConnection)
-Method closeConnection should close connection that has ben opened by openConnection.
why not create a ServerSocket on the receiving end, put it on an endless loop so its always listening, and open a thread for each new incoming connection.
you can now have endless connections.
if you need a code example just say so...
that's how I built my server/client application
If you're asking how to refactor your code to have 3 methods here is how to do it :
Socket openConnection(String ipaddress) throws IOException {
return new Socket(ipaddress, 7420);
}
void sendCommand(Socket commandSocket, String command) throws IOException {
PrintWriter out = null;
BufferedWriter out = null;
BufferedReader in = null;
BufferedWriter outToDetailFile = null;
FileWriter fstream = null;
out = new PrintWriter(commandSocket.getOutputStream(), true);
out = new BufferedWriter(new OutputStreamWriter(commandSocket.getOutputStream()));
in = new BufferedReader(new InputStreamReader(commandSocket.getInputStream()));
out.write("c");out.flush();
out.write(command);out.flush();
String message = in.readLine();
//System.out.println(message);
}
void closeConnection(Socket commandSocket) throws IOException {
commandSocket.close();
}
Now you have to call the first method (openConnection) once when you load your form or when you want to send your first command.
Then for each command, call the second method (sendCommand), it will only send commands without closing the connection.
Finally, call the third method (closeConnection) when all the commands are sent (or when you close your form).
One important thing is not to close the input/output streams/writers as it could close the socket.
I just used your code without trying to correct or improve it, I think there will be some compilation failures (ex: declare the out variable twice).
If you're asking how to use efficiently your server with its limits (5 connections max, wait 6 minutes between additional connections) you can do this :
Use a connection pool (Object pool pattern, Connection pool).
The principle of a connection pool is that instead of asking a connection directly, you ask it to the pool that will create it (connect) for you and give it to you.
When you have finished with your connection (not anymore commands to send), you return it to the pool instead of closing it directly to make it available to other treads/consumers.
You may have to hand code the connection pool class by yourself with the limits you specified :
5 connection maximum
if you close a connection, wait for 6 mins before reopening it
To optimize it and avoid the 6 min waiting limit, you could also try to reuse connections in a reasonable way.

(Client - Server) Java control when Server's serversocket accepts client(s) is not working [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I am currently learning about Sockets and my homework is to create a chat room where multiple clients can talk freely. The hint given by the teacher was that the chat room server only accepts the client when the client attempts to send a message. This homework is supposed to be done without using threads.
Following the hint given, I tried to create unbound ServerSocket and Socket in both the client and the server code. The key idea is that when the client attemps to send a message to the server, the client code would connect the unbound Socket, which will then trigger the server to connect the unbound ServerSocket and to accept the client.
However, when I run the code, both the server and client code are running, and they claim that all the connections are made, but I could not transmit messages between the client and the server at all.
I have tried finding answers online, but I could not find any. I would like to ask if my way of deciding when the server accepts the client is correct.
my ChatRoom Server:
public class ChatRoom {
public static void main(String[] args) throws Exception {
int portNum = 4321;
ServerSocket serverSocket = new ServerSocket();
int count = 1;
while (true) {
// redeclare everything each round
Socket socket = null;
PrintWriter out = null;
BufferedReader in = null;
BufferedReader stdIn = null;
String inputLine = null;
// accept each time round
serverSocket.bind(new InetSocketAddress(portNum));
socket = serverSocket.accept();
System.out.println("newly accepted!");
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
stdIn = new BufferedReader(new InputStreamReader(System.in));
if (!((inputLine = in.readLine()).equals("Bye"))) {
System.out.println("Client says: " + inputLine);
out.println(stdIn.readLine());
out.flush();
System.out.println("Message Count: " + count);
count++;
}
else {
out.println(inputLine);
serverSocket.close();
socket.close();
out.close();
in.close();
}
}
}
}
my ChatRoomClient:
public class ChatRoomClient {
public static void main(String[] args) throws Exception {
String hostName = "localhost";
int portNumber = 4321;
Socket echoSocket = new Socket(); // creates an unbound socket
PrintWriter out = null;
BufferedReader in = null;
BufferedReader stdIn = null;
String userInput;
do {
out = null;
in = null;
stdIn = null;
// each time round the unbound socket attempts to connect to send a message
echoSocket.connect(new InetSocketAddress(hostName, portNumber));
System.out.println("successfully connected");
out = new PrintWriter(echoSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
stdIn = new BufferedReader(new InputStreamReader(System.in));
userInput = stdIn.readLine();
out.flush();
System.out.println("Server says: " + in.readLine());
}
while (!userInput.equals("Bye"));
// close everything
echoSocket.close();
in.close();
stdIn.close();
}
}
Thanks!
The hint given by the teacher was that the chat room server only accepts the client when the client attempts to send a message. This homework is supposed to be done without using threads.
The hint given by the teacher doesn't make sense. The client has to connect, then the server accepts. The client can't send a message without connecting first. Maybe the teacher really means that the client shouldn't connect until he has something to send?
Following the hint given, I tried to create unbound ServerSocket and Socket in both the client and the server code. The key idea is that when the client attemps to send a message to the server, the client code would connect the unbound Socket, which will then trigger the server to connect the unbound ServerSocket and to accept the client.
But that won't happen. It's impossible. If you try to connect to a port that isn't listening, you will get a ConnectException. The only way to put the port into listening state is to bind the ServerSocket. There is no magical back-door by which the server can possibly know that the client wants to connect so it should now do the bind.
This homework is supposed to be done without using threads.
Impossible to 'create a chat room where multiple clients can talk freely' that way, unless you are expected to use non-blocking I/O, or abuse the available() facility, or use a connection per message, but then I don't see how you can communicate one client's messages to the other clients, unless you're allowed to batch them up.
There are too many imponderable aspects of this assignment as you have described it. The question as posed doesn't actully make sense, and your proposed solution certainly doesn't. You should just go ahead and write your program the normal way, with a connect, an accept, and some I/O. Get it working while your teacher comes up with a clarification.
Ah... With out using thread for the server you will not be able to serve multiple clients. Anyway, your current codes have issues and your logic are not correct.
Your stdIn should be declare and instantiated outside of the loop, you don't need to keep on creating the stdIn object for each loop.
Your "in" socket accept() and echoSocket.connect() should also be outside of the loop, this is why you are not getting any answer from the server because you are not listening on the same line. It's like your phone, keep on FLASH to dial the new number each time. all point to the same server, but it is different connection.
So, the idea is to establish a connection between server and client (single connection) that can communicate both way (via input and output stream). Then you can loop and talk start with the client, then server receive, then server talk, then client receive then client talk.... until client say Bye...
for more: http://ta.cnci.org/basicirc
thought I would like to update, I managed to solve my problem without using threads. Just sockets haha. Thought it would be good to post my answer for reference..
my ChatRoom Server:
public class ChatRoomServer {
public static void main(String[] args) throws Exception {
ServerSocket serverSocket = new ServerSocket(4321);
while(true) {
Socket clientSocket = serverSocket.accept();
BufferedReader in = new BufferedReader
(new InputStreamReader(clientSocket.getInputStream()));
String inputLine = in.readLine();
System.out.println("Client says: " + inputLine);
in.close();
clientSocket.close();
}
}
}
my ChatRoom Client:
public class ChatRoomClient {
public static void main(String[] args) throws Exception {
String hostName = "localhost";
int portNum = 4321;
BufferedReader stdIn = new BufferedReader
(new InputStreamReader(System.in));
while (true) {
String userInput;
userInput = stdIn.readLine();
Socket echoSocket = new Socket(hostName, portNum);
PrintWriter out = new PrintWriter
(echoSocket.getOutputStream(), true);
out.println(userInput);
out.flush();
out.close();
echoSocket.close();
if (userInput.equals("Bye")) {
stdIn.close();
break;
}
}
}
}

server client communication java

I have this client, the server information is not important. The output of this code is very random.
class Client {
public static void main(String args[]) throws Exception
{
BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in));
Socket clientSocket = new Socket("127.0.0.1", 10004);//this will become the addr of the server you want to input.
InetAddress host = clientSocket.getInetAddress();
// System.out.println(host);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
boolean exit = false;
while (!exit) {
while (inFromServer.ready()) {
System.out.println(inFromServer.readLine());
}
String sentence = inFromUser.readLine();
outToServer.writeBytes(sentence + "\n");
}
clientSocket.close();
}
}
If I run this in debug mode, it has always the correct result. E.g.
please insert password
the user types pass
pass correct
please type command
and you type command
etc
etc
When it's not in debug mode, all goes wrong. I don't even get the initial request from server. What is going on? I think the read line might be executed too fast?
in.ready() does not wait for any data to be available. It the server hasn't sent the data yet when you client reads that line, you're going to skip the readLine() completely.
Just remove that while and do a plain readLine().
If there are phases where you need to wait for multiple lines from the server, you'll need to implement more logic. Usually, the server will send an "end of message" marker to signify to the client that it is done. For example, when the server is done, it could send the message "END-OF-MESSAGE". In the client code, you would do:
boolean serverDone = false;
while (!serverDone) {
String message = in.readLine();
if (message == null) {
// handle this problem: the server has closed the connection
serverDone = true; // or return, or throw
} else if ("END-OF-MESSAGE".equals(message)) {
serverDone = true;
}
}

Categories