I am not an expert in networking. However, I started a big project in Java, I already made the SQL database and most of the server, I am only working with TCP at the moment, and I was using Strings as operation identifiers server-side, I don't know if this is correct but is working. Problem is there are operations that require me to send data during all the time while client is connected (like the chat I tried to implement in the last "if" sentence) and I donĀ“t know how to implement it client-side without catching wrong information from other operations like bet results or other things. Should I just use a different port?
public static class Users extends Thread{
private final Socket socket;
private final Connection connection;
private final DataInputStream dataInputStream;
private final DataOutputStream dataOutputStream;
public Users(Socket socket, Connection connection) throws IOException {
this.socket=socket;
this.connection=connection;
this.dataInputStream=new DataInputStream(socket.getInputStream());
this.dataOutputStream=new DataOutputStream(socket.getOutputStream());
}
#Override
public void run(){
while (true){
try {
String operation= dataInputStream.readUTF();
if(operation.equals("Login")){
//censored//
}
if(operation.equals("Register")){
//censored//
}
if(operation.equals("GetClientData")){
//censored//
}
if(operation.equals("Deposit")){
//censored//
}
if(operation.equals("Withdraw")){
//censored//
}
if(operation.equals("PlaceBetOnRoulette")){
//censored//
}
if(operation.equals("PlaceBetOnCrash")){
//censored//
}
if(operation.equals("PlaceBetOnCoinFlip")){
//censored//
}
if(operation.equals("PlaceBetOnSlot")){
//censored//
}
if (operation.equals("SendMessage")){
String message= new String();
message= dataInputStream.readUTF();
if (!message.equals("") && !message.isEmpty()){
for (int i=0;i<arrayList.size();i++){
Socket chatVolatileSocket = (Socket) arrayList.get(i);
DataOutputStream volatileMessageSender= new DataOutputStream(chatVolatileSocket.getOutputStream());
volatileMessageSender.writeUTF(message);
}
}
};
}
catch (IOException e) {
e.printStackTrace();
break;
}
}
try {
arrayList.remove(socket);
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
I recommend establishing a more formal message protocol. On a project I am working on I am sending JSON with several common fields like "type" and "time" over web sockets. This can be done similarly using XML if you prefer. This way you can structure your messages.
Also, I meant add this in the comments, but I might as well include this here: Don't use Data streams. Just use plain old Input/OutputStreams. Data streams are Java-only and will lock you into choices that down the road you may very well regret.
Related
I'm programming in Java and i'm making a socket connection between server and several clients (using threads).
In the client side i made an opened Socket that connects to the server in a respective port and i send several objects, then the client disconnects.
In the server side i made a ServerSocket (where the client connects) and i use the accept() method to get the Socket, i don't want the socket to close so i keep it opened until i want (using a method for example), then i create an stream (ObjectInputStream) and read every object sent from the client, but i don't want it to close too. To continue the understanding of my problem here is the class i made:
import java.io.*;
import java.net.*;
public class ServerConnection implements Runnable{
private Socket connection;
public ServerConnection(Socket c){
connection = c;
}
#Override
public void run() {
// I used String i this example, but the real code use a Object sending system that i created
// because i needed to send different objects in one object (this ones implements Serializable).
String msg;
try {
ObjectInputStream inStream = new ObjectInputStream(connection.getInputStream());
do{
inStream.
msg = ((String)inStream.readObject());
System.out.println(msg);
}
while(!msg.equals("FINISH CONNECTION"));
} catch (IOException ex) {
System.err.println("run() - (io): "+ex.getMessage());
try {
connection.close();
} catch (IOException ex1) {
System.err.println("run() - (io/io): "+ex.getMessage());
}
} catch (ClassNotFoundException ex) {
System.err.println("run() - (classNF): "+ex.getMessage());
}
}
// The main method was created to make tests
// I'll use objects of this class to every client connection
public static void main(String[] args){
try {
ServerSocket server = new ServerSocket(8010);
Socket connection = server.accept();
ServerConnection svConnection = new ServerConnection(connection);
Thread theThread = new Thread(svConnection);
theThread .start();
} catch (IOException ex) {
System.err.println(ex.getMessage());
}
}
}
This can receive the Strings i sent from the client, but the do-while isn't able to catch exceptions, the IOException is throwed when the Stream has no more Strings, so i want to prevent the throwing of that exception when the stream doesn't have more Strings to read, i tried to use recursive try-catch but i know that is not recommended. So there is another solution to this?
(Every answer is welcome. Thanks)
(EDIT)
For those one who needs the client code, so here it is:
import java.io.*;
import java.net.*;
public class ClientConnnection{
// There is a method that i don't make yet
public static void main(String[] args){
try {
Socket socketToServer = new Socket("localhost",8010);
ObjectOutputStream outStream = new ObjectOutputStream(socketToServer.getOutputStream());
outStream.writeObject(new Message("Hello :D"));
outStream.writeObject(new Message("How r u?"));
outStream.writeObject(new Message("Other message"));
outStream.flush();
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
}
}
I have written a Java Chat Server program.
This is a simple standalone program for Server.
I have to run this then run Client to get Chat working.
What are some possible Unit Test scenarios for the server program? Can anyone show me some example of unit test based on this code?
I have never written a unit test code before and I can't really think of what needs to be tested here.. I think testing Connection can be one but what else? (and how to?)
public class SimpleChatServer {
static final Logger logger = LogManager.getLogger(SimpleChatServer.class);
ArrayList<PrintWriter> clientOutputStreams;
private BufferedReader reader;
private Socket sock;
private ServerSocket serverSock;
public class ClientHandler implements Runnable{
public ClientHandler(Socket clientSocket){ // Socket Connection
try {
sock = clientSocket;
InputStreamReader isReader = new InputStreamReader(sock.getInputStream());
reader = new BufferedReader(isReader);
} catch(Exception ex) {
logger.trace(ex);
}
}
public void run() {
String message;
try {
while ((message = reader.readLine()) != null) {
System.out.println("read " + message);
tellEveryone(message);
}
} catch(Exception ex) {
logger.trace(ex);
}
} //close run
} //close ClientHandler
public static void main (String[] args) throws Exception
{
new SimpleChatServer().listen();
}
#SuppressWarnings("resource")
public void listen()
{
clientOutputStreams = new ArrayList<PrintWriter>();
try {
ServerSocket serverSock = new ServerSocket(8000); //port number 8000 was used
while(true) {
Socket clientSocket = serverSock.accept();
PrintWriter writer = new PrintWriter(clientSocket.getOutputStream());
clientOutputStreams.add(writer);
Thread t = new Thread(new ClientHandler(clientSocket));
t.start();
}
} catch (Exception ex) {
logger.trace("Server Error", ex);
} finally {
try
{
serverSock.close();
}
catch(Exception e){}
}
} // close go
public void tellEveryone(String message)
{
Iterator<PrintWriter> it = clientOutputStreams.iterator();
while(it.hasNext()) {
try {
PrintWriter writer = (PrintWriter) it.next();
writer.println(message);
writer.flush();
} catch (Exception ex) {
logger.trace(ex);
}
} // end while
} // close tellEveryone
}
I was going to crib an answer from Pragmatic Unit Testing, but suggest you just find a copy. At the very least you should consider whether results are right, whether your boundary conditions are correct, and if you can force error conditions.
Testing results often means making sure combinations of input get the expected results. Boundaries are reflected in the related "0, 1, many" rule, where you do silly stuff to see if your code has implicit boundaries that can be reached with bad, null or unexpected values.
For example, what happens if you pass huge Strings to your methods that take them? What about strings with weird Unicode chars in them? No line breaks?
Forcing error conditions means making sure things degrade gracefully and/or throw under the expected situation.
Think about your code as a brittle little appliance and then pretend a poo-flinging monkey, a 14-yr old hacker and your non-hacker grandmother (I know some exist) are all taking turns on it.
EDIT: I have corrected the mistake below in the code, by adding a line into the server code
I'm trying to write some socket code that will allow me to send data from one computer to another for a game (which for simplicity's sake, we can think of as tic-tac-toe, not much data needs to be sent, just a couple of numbers). In order to achieve this I have written two classes, Server and Client. At the moment I am testing through the localhost using port 1234, and I am only using one single instance of the program (though the same problem occurs when trying to use two instances).
Firstly here's the code, and then I can go into more depth about the problem, and what testing I've done to attempt to work out what is going wrong:
public class Server
{
private ServerSocket server;
private Socket socket;
private Client socketHandler;
private static final int DEFAULT_PORT = 1234;
public Server() { this(DEFAULT_PORT); }
public Server(int port)
{
Thread thread = new Thread()
{
public void run()
{
try
{
System.out.println("Attempting to Establish Connection");
server = new ServerSocket(port);
socket = server.accept();
socketHandler = new Client(port, socket); //THIS LINE ADDED
System.out.println("Server Online!");
}
catch (Exception e)
{
e.printStackTrace();
}
}
};
thread.setDaemon(true);
thread.start();
}
//ADJUSTED
Client getSocketHandler()
{
return socketHandler;
}
public void kill()
{
try
{
if (socket != null) socket.close();
if (server != null) server.close();
}
catch(IOException e)
{
e.printStackTrace();
}
finally
{
socket = null;
server = null;
}
}
}
public class Client
{
public static final int DEFAULT_PORT = 1234;
public static final String DEFAULT_HOST = "localhost";
private static final String THUMP_THUMP = "thump thump";
private static final int PULSE = 1000;
private int port;
private String ip;
private Socket socket;
private BufferedReader input = null;
private PrintWriter output = null;
boolean closed = true;
String data = "";
public Client() { this(DEFAULT_PORT, DEFAULT_HOST, null); }
public Client(int port) { this(port, DEFAULT_HOST, null); }
public Client(int port, String ip) { this(port, ip, null); }
public Client(int port, Socket server) { this(port, DEFAULT_HOST, server); }
public Client(String ip) { this(DEFAULT_PORT, ip, null); }
public Client(String ip, Socket server) { this(DEFAULT_PORT, ip, server); }
public Client(Socket server) { this(DEFAULT_PORT, DEFAULT_HOST, server); }
public Client(int port, String ip, Socket server)
{
socket = server;
this.ip = ip;
this.port = port;
Thread thread = new Thread()
{
public void run()
{
try
{
initialise(server);
String line;
startHeartbeat();
while (isClosed()) {} //first it is closed, lets wait for it to open before we start waiting for it to close!
System.out.println("We are about to listen!");
while (!isClosed())
{
System.out.println("pre-read"); //this line was used to determine that the code was hanging on the next line
line = input.readLine(); //offending line
System.out.println("post-read"); //this line was used to determine when the block was lifted
if (line != null)// || line != THUMP_THUMP)
{
System.out.println(line);
data += line + "\n";
}
}
System.out.println(data);
kill();
System.out.println("Connection Closed!");
}
catch (SocketException e)
{
e.printStackTrace();
System.out.println("Server closed!");
}
catch (Exception e)
{
e.printStackTrace();
}
}
};
thread.setDaemon(true);
thread.start();
}
private void initialise(Socket server)
{
try
{
if (server == null) socket = new Socket(ip, port);
input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
output = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
}
catch (IOException e) { e.printStackTrace(); }
}
public boolean post(String text)
{
synchronized(this)
{
output.println(text);
output.flush();
return !output.checkError();
}
}
public void kill()
{
try
{
if (input != null) input.close();
if (socket != null) socket.close();
}
catch(IOException e) { e.printStackTrace(); }
finally
{
input = null;
socket = null;
}
}
public void killOutputStream()
{
try
{
if (output != null) output.close();
}
catch (Exception e) { e.printStackTrace(); }
finally
{
output = null;
}
}
//////////////////////////////////
///////// Socket Control /////////
//////////////////////////////////
synchronized boolean isClosed()
{
return closed;
}
synchronized void setClosed(boolean b)
{
closed = b;
}
//We need to make sure that the socket is still online, to ensure the reading stops when the connection closes.
void startHeartbeat()
{
Thread heartbeat = new Thread()
{
public void run()
{
while (output != null)
{
setClosed(post(THUMP_THUMP) ? false : true); //post returns true on success
synchronized(this)
{
try
{
this.wait(PULSE);
}
catch (InterruptedException e) {}
}
}
setClosed(true);
}
};
heartbeat.setDaemon(true);
heartbeat.start();
}
}
The Problem
When the client is started (after having created the server) it fails to read any data sent through (or even the heartbeat), in fact the code does not go past line = input.readLine() in the reading thread (which is from now on called the offending line), except it seems, until the server is disconnected (see below).
Here is the order of regular testing:
Server() is called and the resulting Server is stored in the serverConnection variable then
Client(serverConnection != null ? serverConnection.getSocket() : null) is called and the new Client is stored in clientConnection.
Because we can test whether it is working using the heartbeat no other data needs to be sent, and the server is terminated by calling serverConnection.kill() and then clientConnection.killOutputStream() after letting some time elapse.
and this is the result:
Attempting to Establish Connection Server Online!
We are about to listen!
Connection Closed!
where the empty line represents the non null data received over the course of the connection, ie that there is none.
I expect this:
Attempting to Establish Connection
Server Online!
We are about to listen!
thump thump
thump thump
thump thump (and so on, every second)
Connection closed!
I spent time performing different tests by commenting out or changing the code slightly with the same testing format (except for the special case, which is number 6) and made these observations:
Observations
Only when the socket is closed and the output stream is closed, does the program move past the offending line.
When the readline() method starts to process (shortly before the heartbeat cuts it off) it detects nothing in the stream, not even THUMP_THUMP.
When the socket is closed, but the output stream is not, the readline() method starts to process, only to detect nothing, heartbeat cuts it off. No SocketException even though it would be expected.
If the socket is NOT closed, and only the output stream is closed, a SocketException is triggered, suggesting the socket is closed.
I used netstat -an in command prompt, and when the server is started the port 1234 is LISTENING. When the client connects, it is still LISTENING, implying that there is no connection.
I set up some python code to connect to itself over port 1234,
however I made a mistake in the python code, and as such the server
didn't close, and was still open. So I decided to connect the java
client to the server and see what happens. I did this by running
Client(null) which is the client code for the non-host. It
resulted in the port reading ESTABLISHED, and the python server was
echoing back the "thump thump", and the java code was successfully
reading it. No hanging, it worked perfectly.
This leads me to believe that the problem lies in the server code, as the python server was able to communicate sucessfully with the Java client, but the Java client is unable to communicate with the Java server.
Before performing this testing I had been concentrating on the Client code, believing that it was at fault. All the questions I have found here with similar symptoms (see here, here and here, among others) have turned up blank for me, having written in their solutions (most were due to the output stream not flushing, or the \n ommitted, which I have not failed to do, or the solution not fixing my problem, and so having been removed in favor of the heartbeat in this case). I originally based my code off of this article.
After 4 days of trying to figure out this problem I am at a loss for what to do... What am I missing here? Why is the Server code not working as I expect it to? If anybody needs any more clarification on my code then please ask!
As an after-note, the testing code is run through a simple minimalistic GUI written in javafx (not fxml though), whether that would be a problem or not I'm sure, I would think not, due to it working with the Python server. This code is compiled in Java 8
I'm a little confused about why you think it would go any furthur than input.readLine() considering there is no handling of inputs/outputs on the server side....
Client/Server connections are like a game of tennis, as one side serves the other must receive the ball and then serve it back(maybe with different information). Your server side must handle the input it recieves from the start heartbeat method, and then send you back a response. the input.readLine() function blocks the thread until it receives data from the other end, so yes the code stops there and waits for your server to send the "tennis ball" back. In the server class you should add an input and output stream that handle the heart beat inputs and send back a string of data to the client.
Server:
OutputStream os = socket.getOutputStream();
InputStream is = socket.getInputStream();
String response = "thump thump";
while(true){
is.read();
os.write(response.getBytes());
os.flush();
}
with this example, the client should remain unchanged and just add the above code to your server.
i am creating a multiple-client/server app whenever any client disconnects from
my server it just hangs.
how can i set any condition that will tell me print some message whenever
any client disconnects from the server
here is my server code
class ServerThread implements Runnable {
public void run() {
Socket socket = null;
try {
System.out.println("server starting.......");
serverSocket = new ServerSocket(SERVERPORT);
} catch (IOException e) {
e.printStackTrace();
}
while (!Thread.currentThread().isInterrupted()) {
try {
System.out.println("Ready to accept.......");
socket = serverSocket.accept();
System.out.println(" client Connected with ip address =" +socket.getRemoteSocketAddress().toString());
CommunicationThread commThread = new CommunicationThread(socket);
new Thread(commThread).start();
} catch (IOException e) {
e.printStackTrace();
System.out.println("catch block");
}
}
}
}
class CommunicationThread implements Runnable {
private Socket clientSocket;
private BufferedReader input;
public CommunicationThread(Socket clientSocket) {
this.clientSocket = clientSocket;
try {
this.input = new BufferedReader(new InputStreamReader(this.clientSocket.getInputStream()));
} catch (IOException e) {
e.printStackTrace();
}
}
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
String read = input.readLine();
updateConversationHandler.post(new updateUIThread(read));
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
any help will be appreciated
It's not clear whether you mean disconnect because the conversation was over (ie: everything completed successfully) or the disconnect is because of some network problems (or the client canceled the request).
If it's the first case, then it's easy: the protocol you are using (your own, or http, or whatever) is in charge of defining how to determine that a conversation was over. If that situation arises, then you just close the socket.
If it's the second case, then you'd have to have an algorithm in place to determine whether or not the connection must be closed. For instance, by implementing a timeout, or a slow-read threshold. Take a look at the Socket's javadoc for instructions on how to set a timeout.
It's also worth noting that it's fine to create your own servers when you want to practice or learn something, but you'd be better off using an existing solution, like vert.x or a slimmed down version of Wildfly, for instance. The overhead of such servers is very low, nowadays, while still providing very robust networking capabilities.
guys! i wrote simple server client (udp) application. Now i am trying to make server that accepts many clients. As, i understood, i need to create functions, that accepts and handle clients, but i am confused about apps structure. Can u check if i have right skeleton for my app? Mayb u can give me some hint or example. All advice appreciated! :)
class MultiServer {
private DatagramSocket serversocket;
public MultiServer() {
try {
this.serversocket = new DatagramSocket(6789);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void start() throws IOException {
while(true) {
DatagramSocket serversock = serversocket.accept();
new Thread(new ClientHandler(serversock)).start();
}
}
public static void main(String[] args) {
Server1 server = new Server1();
try {
server.start();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class ClientHandler implements Runnable {
private final DatagramSocket clientsocket;
ClientHandler(DatagramSocket sock) {
this.clientsocket = sock;
}
#Override
public void run() {
//receive packet, send msg, get ip, get portnumber ?
}
}
}
So you want your server to be able to operate with multiple requests at the same time? Good, it's how most web-servers work. You have to understand the basic concepts of multi-threading and concurrency.
A simple server can only handle ONE thing at a time. What happens if another request is received while the server is dealing with something else? Nothing, so the application isn't very efficient and not scalable at all.
If you haven't used multiple threads in your applications yet and don't know much about concurrency, it's a great time to have a go, read the Oracle Concurrency Lesson, or find a tutorial online, there are plenty.
Now, once (or if) you know how threading works make sure you break down your functions as much as possible and see what functions can happen at the same time. An example of a Web Server that i can think of is this:
A separate thread to listen on the port for requests. Once a request is received, place it in the 'request pool' and queue it to be processed
A separate thread (or multiple threads/thread pool) that process the request
Your structure looks like you have both receive and process in the same Runnable. Anyway, this is just an idea, you'll have to see what's more applicable to your application. Also, have a look at the Concurrency tools that newer Java versions provide, Java 6 and 7 provide a lot of tools you can use that are very effective (but also quite hard to understand and use in my opinion).
Good luck!
You are looking for a Threadpooled Server. The way you started is good. Now you simply implement a Java execution Service to Handle the requests. The threadpool has a fixed of thread. It does take your requests and put those in a queue and if a request is done it takes the next request. So you normaly dont lose any requests.
Here is a small example i made:
public class PoolServer implements Runnable {
private static final int DEFAULT_PORT = 8080;
private static final String CONFIG = "config.xml";
protected ServerSocket serverSocket = null;
protected boolean isStopped = false;
protected Thread runningThread = null;
protected ExecutorService threadPool = Executors.newFixedThreadPool(100);
protected int serverPort;
public PoolServer() {
// getting the port from the XML
this.serverPort = getPortFromXML();
}
public void run() {
synchronized (this) {
this.runningThread = Thread.currentThread();
}
openServerSocket();
// accepting loop
while (!isStopped()) {
Socket clientSocket = null;
try {
// accept the client
clientSocket = this.serverSocket.accept();
clientSocket.setSoTimeout(2000);
} catch (IOException e) {
if (isStopped()) {
return;
}
throw new RuntimeException("Error accepting client connection",
e);
}
this.threadPool.execute(new ThreadHandler(clientSocket));
}
// loop end
// server stopped shut down the ThreadPool
this.threadPool.shutdown();
}
private synchronized boolean isStopped() {
return this.isStopped;
}
public synchronized void stop() {
this.isStopped = true;
try {
this.serverSocket.close();
} catch (IOException e) {
throw new RuntimeException("Error closing server", e);
}
}
private void openServerSocket() {
try {
this.serverSocket = new ServerSocket(this.serverPort);
} catch (IOException e) {
throw new RuntimeException("Cannot open port " + this.serverPort, e);
}
}
At this point this.threadPool.execute(new ThreadHandler(clientSocket)); i do execute the request if a thread is free. Else it get into the queue of the Threadpool.
You can even change it from a Fixed to some other Threadpools! Just take a look at the Executors and take what you need. Executors
Hope this helps!