Multithreaded FTP Server in Java - java

I'm making a multithreaded FTP server in Java and I have a question about to go about handling multiple clients. Right now, I have a Server that looks like this:
public class Server {
private static final int HOST_PORT = 6000;
private ServerSocket serverSocket;
public Server(ServerModel serverModel) throws IOException {
serverSocket = new ServerSocket(HOST_PORT);
}
public void start() {
try {
acceptClients();
} catch (IOException e) {
e.printStackTrace();
}
}
private void acceptClients() throws IOException {
while (true) {
Socket client = serverSocket.accept();
ServerModel serverModel = new ServerModel();
Thread worker = new Thread(new ServerWorker(client, serverModel));
worker.start();
}
}
}
And a ServerWorker object which is responsible for interpreting client commands and responding to them:
public class ServerWorker implements Runnable {
private ServerRemoteHandler serverRemoteHandler;
private ServerModel serverModel;
private static final int GET_CODE = 1;
private static final int PUSH_CODE = 2;
private static final int CHANGE_DIRECTORY_CODE = 3;
private static final int PRINT_WORKING_DIRECTORY_CODE = 4;
private static final int FILE_EXISTS_CODE = 5;
private static final int LIST_FILES_DIRECTORIES_CODE = 6;
private static final int EXIT_CODE = 0;
public ServerWorker(Socket client, ServerModel serverModel) throws IOException {
this.serverModel = serverModel;
try {
serverRemoteHandler = new ServerRemoteHandler(client);
} catch (IOException e) {
e.printStackTrace();
}
}
private void parseCommand() {
int command;
try {
while (true) {
command = serverRemoteHandler.getCommand();
switch (command) {
case CHANGE_DIRECTORY_CODE:
changeDirectory();
break;
case PRINT_WORKING_DIRECTORY_CODE:
printWorkingDirectory();
break;
case FILE_EXISTS_CODE:
fileExists();
break;
case LIST_FILES_DIRECTORIES_CODE:
listFilesDirectories();
break;
case GET_CODE:
pushFile();
break;
case PUSH_CODE:
getFile();
break;
case EXIT_CODE:
exit();
break;
}
}
} catch (IOException e) {
exit();
}
}
private void printWorkingDirectory() throws IOException {
serverRemoteHandler.printWorkingDirectory(serverModel.getCurrentPath());
}
private void changeDirectory() throws IOException {
String fileName = serverRemoteHandler.getFileName();
boolean success = serverModel.changeDirectory(fileName);
serverRemoteHandler.changeDirectory(success);
}
private void fileExists() throws IOException {
String fileName = serverRemoteHandler.getFileName();
serverRemoteHandler.fileExists(serverModel.fileExists(fileName));
}
private void pushFile() throws IOException {
File file = serverModel.getFile(serverRemoteHandler.getFileName());
long fileSize = serverModel.getFileSize(file);
serverRemoteHandler.pushFile(file, fileSize);
}
private void listFilesDirectories() throws IOException {
serverRemoteHandler.listFilesDirectories(serverModel.listFilesDirectories());
}
private void getFile() throws IOException {
String fileName = serverRemoteHandler.getFileName();
File file = new File(serverModel.getCurrentPath() + File.separator + fileName);
serverRemoteHandler.getFile(file);
}
private void exit() {
serverRemoteHandler.exit();
}
#Override
public void run() {
while (true) {
parseCommand();
}
}
}
Each ServerWorker has an Object called RemoteHandler whose job is to send and receive information from the streams. My questions are regarding this line:
Thread worker = new Thread(new ServerWorker(client, serverModel));
Is this thread safe? Is this a good way of implementing it? Thank you.

Yes it is threadsafe. Everything in that line is method-local, so it is only accessible by the current thread, and then the worker thread starts while this one loops and gets a new set of values for these variables.
(That doesn't imply the entire program is thread-safe, of course.)

Related

Multithread Server and Client with sockets in Java

I am trying to create for a university project a server / slave / client project.
The server should open 2 ports, one port will be for the connection of the slave and another port for the client.
I have setup 2 threads 1 for the client and another for the slave. The client should sent random numbers to server and server should forward randomly those numbers to slave instances. The slave should check if the current number exist on their list and if it's not available to store it, otherwise they should sent a message to server that the number already exist.
Then I created the client thread which consist of 2 threads, one for sending the numbers to server and another thread to read messages coming from the server.
There is something wrong with the code of the PrintWriter, I cannot make it to send the numbers to server when the code is inside the thread. If I move the code on the main and cancel the thread the messages are being sent without any issue.
What could be the issue for this?
Below is the current code from server (master) and the client.
public class Client {
private static final int NUMBERS = 50;
private static final int AMPLITUDE = 100;
private static int masterPort;
public Client(int port) {
this.masterPort = port;
}
public static void main(String[] args) throws IOException{
String serverHostname = "127.0.0.1";
System.out.println("Αναμονή για σύνδεση στον σέρβερ " + serverHostname + " στην πόρτα 30091.");
Socket echoSocket = null;
BufferedReader in = null;
try {
echoSocket = new Socket(serverHostname, 18889);
in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("Δεν μπορεί να πραγματοποιηθεί σύνδεση με τον σέρβερ: " + serverHostname);
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to: " + serverHostname);
System.exit(1);
}
ClientOut clientOut = new ClientOut(echoSocket);
clientOut.start();
ClientIn clientIn = new ClientIn(in);
clientIn.start();
in.close();
echoSocket.close();
}
public static class ClientOut extends Thread {
private PrintWriter out;
public ClientOut(Socket echoSocket) throws IOException {
this.out = new PrintWriter(echoSocket.getOutputStream(), true);
}
#Override
public void run() {
System.out.println("Ο client συνδέθηκε!");
Random rnd = new Random();
try {
for (int i=0; i<NUMBERS; i++) {
int num = rnd.nextInt(AMPLITUDE);
System.out.println(num);
out.println(num);
TimeUnit.SECONDS.sleep(1);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
out.close();
}
}
public static class ClientIn extends Thread {
private BufferedReader in;
public ClientIn(BufferedReader in) {
this.in = in;
}
#Override
public void run() {
}
}
}
public class Master {
private int slavePort;
private int clientPort;
private SlaveThread slaveThread;
private ClientThread clientThread;
private boolean running = false;
public static int slaveConnected; // Slave connection counter
public Master(int slavePort, int clientPort) {
this.slavePort = slavePort;
this.clientPort = clientPort;
this.slaveConnected = 0;
public void startServer() {
try {
this.slaveThread = new SlaveThread(slavePort);
this.clientThread = new ClientThread(clientPort);
System.out.println( "Αναμονή για σύνδεση client / slave" );
slaveThread.start();
clientThread.start();
} catch (IOException e) {
e.printStackTrace();
}
}
public void stopServer() {
running = false;
this.slaveThread.interrupt();
this.clientThread.interrupt();
}
class SlaveThread extends Thread {
private ServerSocket slaveSocket;
SlaveThread(int slavePort) throws IOException {
this.slaveSocket = new ServerSocket(slavePort);
}
#Override
public void run() {
running = true;
while (running) {
try {
// Call accept() to receive the next connection
Socket slSocket = slaveSocket.accept();
System.out.println("Δημιουργήθηκε μια νέα σύνδεση Slave");
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class ClientThread extends Thread {
private ServerSocket clientSocket;
ClientThread(int clientPort) throws IOException {
this.clientSocket = new ServerSocket(clientPort);
}
#Override
public void run() {
running = true;
while (running) {
try {
Socket clSocket = clientSocket.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(clSocket.getInputStream()));
System.out.println("Δημιουργήθηκε μια νέα σύνδεση Client");
String inputLine;
while ((inputLine = in.readLine()) != null) {
System.out.println("Client: " + inputLine);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
Master server = new Master( 30091, 18889);
server.startServer();
// Automatically shutdown in 1 minute
try {
Thread.sleep( 60000 );
} catch(Exception e) {
e.printStackTrace();
}
server.stopServer();
}
I found the solution.
The Socket should be created on the Client Thread constructor and not to be passed as reference.
So the client should be
public class Client {
private static final int NUMBERS = 50;
private static final int AMPLITUDE = 100;
private static int masterPort;
public Client(int port) {
this.masterPort = port;
}
public static void main(String[] args) throws IOException{
String serverHostname = "127.0.0.1"; //Ορίζουμε την διεύθυνση που είναι ο σέρβερ
System.out.println("Αναμονή για σύνδεση στον σέρβερ " + serverHostname + " στην πόρτα 30091.");
ClientOut clientOut = new ClientOut(serverHostname);
clientOut.start();
ClientIn clientIn = new ClientIn(serverHostname);
clientIn.start();
}
public static class ClientOut extends Thread {
private Socket echoSocket;
private PrintWriter writer;
ClientOut(String serverHostname) throws IOException {
this.echoSocket = new Socket(serverHostname, 18889);
this.writer = new PrintWriter(echoSocket.getOutputStream(), true);;
}
#Override
public void run() {
System.out.println("Ο client συνδέθηκε!");
Random rnd = new Random();
try {
for (int i=0; i<NUMBERS; i++) {
int num = rnd.nextInt(AMPLITUDE);
System.out.println(num);
writer.println(num);
TimeUnit.SECONDS.sleep(1);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
writer.close();
}
}

Java: Publisher-Observer pattern: High CPU Usage

I have a ServerSocket Thread that accepts a connection and starts a socket handler. This part seems to be working fine with no memory leaks or high cpu usage. I added a Publisher thread and an observer thread and now, my java program is reporting high CPU usage.
Subject.java:
public interface Subject {
public void attach(Observer o);
public void detach(Observer o);
public void notifyUpdate(Message m);
}
MessagePublisher.java:
public class MessagePublisher extends Thread implements Subject{
private List<Observer> observers = new ArrayList<>();
private boolean readyToPublish = false;
private ConcurrentLinkedQueue<Message> msgHolder;
public MessagePublisher(ConcurrentLinkedQueue<Message> _queue){
this.msgHolder = _queue;
}
#Override
public void attach(Observer o) {
observers.add(o);
}
#Override
public void detach(Observer o) {
observers.remove(o);
}
#Override
public void notifyUpdate(Message m) {
for(Observer o: observers) {
o.update(m);
}
}
public void run(){
this.readyToPublish = true;
while (readyToPublish)
{
try
{
Message _m = (Message)this.msgHolder.poll();
if(!_m.equals(null)){
System.out.println("Polled message: " + _m.getMessage());
System.out.println("Number of subscribers: " + observers.size());
notifyUpdate(_m);
}
}
catch(Exception j) { }
try { sleep(9); }
catch(Exception e) { }
}
EndWork();
}
public void EndWork(){
this.readyToPublish = false;
this.observers.clear();
}
}
Main.java:
public static void main(String[] args) {
// TODO code application logic here
ConcurrentLinkedQueue<Message> msgHolder = new ConcurrentLinkedQueue<Message>();
ServerSocketThread _socketThread = new ServerSocketThread(msgHolder);
_socketThread.start();
MessagePublisher _publisher = new MessagePublisher(msgHolder);
_publisher.start();
UIServerSocketThread _uiSocketThread = new UIServerSocketThread(_publisher);
_uiSocketThread.start();
}
UIServerSocketThread.java:
public class UIServerSocketThread extends Thread{
private ServerSocket objServerSocket;
private Socket objSocket;
private int iPort = 21001;
private FileHandler obj_LogFileHandler;
private Logger obj_Logger;
private int file_size = 8000000;
private int numLogFiles = 20;
private UIClientSocketThread objCltSocket;
private MessagePublisher objPublisher;
private boolean running = false;
public UIServerSocketThread(MessagePublisher _publisher){
this.running = true;
try {
this.obj_LogFileHandler = new FileHandler("uiserver.log.%g", file_size, numLogFiles);
this.obj_LogFileHandler.setFormatter(new SimpleFormatter());
}
catch ( IOException obj_Exception ) {
this.obj_LogFileHandler = null;
}
catch ( SecurityException obj_Exception ) {
this.obj_LogFileHandler = null;
}
this.obj_Logger = null;
if ( this.obj_LogFileHandler != null ) {
this.obj_Logger = Logger.getLogger("eti.logger.uiserver");
this.obj_Logger.addHandler(this.obj_LogFileHandler);
}
try {
this.objServerSocket = new ServerSocket(this.iPort);
} catch(IOException i){
//i.printStackTrace();
this.obj_Logger.info(i.getMessage());
}
this.objPublisher = _publisher;
}
public void run() {
StringBuffer sMsg;
sMsg = new StringBuffer();
while ( this.running ) {
try {
this.objSocket = this.objServerSocket.accept();
} catch(Exception e){
sMsg.append("Error accepting ui socket connection\n");
sMsg.append(e.getMessage());
this.obj_Logger.info(sMsg.toString());
}
try {
this.objCltSocket = new UIClientSocketThread(this.objSocket, this.obj_Logger);
if(!this.objPublisher.equals(null)){
this.obj_Logger.info("Attacing clientObserver");
this.objPublisher.attach(this.objCltSocket);
}
this.objCltSocket.start();
} catch(Exception r) {
sMsg.append("Error \n");
sMsg.append(r.getMessage());
this.obj_Logger.info(sMsg.toString());
}
}
this.objPublisher.EndWork();
stopServerSocketThread();
} // end run
public void stopServerSocketThread() {
try {
this.running = false;
this.objServerSocket.close();
this.objServerSocket = null;
this.obj_Logger.info("Server NOT ACCEPTING Connections!!");
} catch(Exception e ) {
this.obj_Logger.info(e.getMessage());
}
}
}
I am not sure where the issue is. Any help is appreciated.
You have two infinite loops in your application. One is in class MessagePublisher with function run(). And another one is in class UIServerSocketThread. This will cause high CPU usage.

Thread running in debug mode, but doesn't work in real time

I've written server app, which works on few threads. We have networking thread to connect and exchange data with client app, dataBaseConnector thread, which connect with sqlite data base, and userInterface thread, which is for simple control of the program.
Main:
public class Main {
public static void main(String[] args) throws Exception {
ServerSocket serverSocket = new ServerSocket(9000);
DataContainer dataContainer = new DataContainer();
DataBaseConnector dataBaseConnector = new DataBaseConnector(dataContainer);
UserInterface userInterface = new UserInterface(dataBaseConnector, dataContainer);
Thread userInterfaceThread = new Thread(userInterface);
Thread dataBaseConnectorThread = new Thread(dataBaseConnector);
userInterfaceThread.start();
dataBaseConnectorThread.start();
while(dataContainer.workingStatus){
new Thread(new Handler(new Networking(dataContainer, serverSocket.accept()))).start();
}
}
}
User Interface:
public class UserInterface implements Runnable {
private final String WELCOME = "Witaj w programie Auction House! Jest to serwer aplikacji";
private final String MENU = "Menu:";
private final String OPTION_ONE = "1. Zapisz dane do bazy";
private final String OPTION_TWO = "2. Zamknij serwer";
private final String OPTION_THREE = "3. Przywroc menu";
private DataBaseConnector dataBaseConnector;
private DataContainer dataContainer;
private int userChoice = 0;
public UserInterface(DataBaseConnector dataBaseConnector, DataContainer dataContainer) {
this.dataBaseConnector = dataBaseConnector;
this.dataContainer = dataContainer;
setUpMenu();
}
#Override
public void run() {
while (dataContainer.workingStatus){
getUserChoice();
makeUserRequest();
}
}
private void setUpMenu() {
System.out.println(WELCOME);
System.out.println(MENU);
System.out.println(OPTION_ONE);
System.out.println(OPTION_TWO);
System.out.println(OPTION_THREE);
}
private void getUserChoice() {
Scanner scanner = new Scanner(System.in);
userChoice = scanner.nextInt();
}
private void makeUserRequest() {
switch (userChoice) {
case 1: {
dataContainer.lockTheLock();
dataContainer.checkPoint = true;
dataContainer.unlockTheLock();
break;
}
case 2: {
dataContainer.lockTheLock();
dataContainer.workingStatus = false;
dataContainer.unlockTheLock();
break;
}
case 3: {
setUpMenu();
break;
}
}
}
}
1 - is for writing data into Data Base
2 - is for shutting down server
3 - is for printing menu again
and DataBaseConnector (short version):
public DataBaseConnector(DataContainer dataContainer) {
getJDBCDriverClass();
connection = connectToDataBase();
statement = createStatement();
this.dataContainer = dataContainer;
createTables();
selectDataFromDataBase();
updateDataContainer();
clearLists();
}
#Override
public void run() {
while (dataContainer.workingStatus) {
if (dataContainer.checkPoint) {
dataContainer.lockTheLock();
dropTables();
createTables();
setClientList();
setAuctionList();
setItemList();
instertDataIntoDataBase();
dataContainer.checkPoint = false;
dataContainer.unlockTheLock();
}
}
}
And the lock:
public class Lock {
private boolean isLocked = false;
public synchronized void lock() throws InterruptedException {
while (isLocked) {
wait();
}
isLocked = true;
}
public synchronized void unlock() {
isLocked = false;
notifyAll();
try {
wait(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
And the problem: When running in debug mode in eclipse, everything works fine, but in real time when i'm choosing 1 in console nothing is happening, but when choosing 3, the menu prints again.
When you work in Eclipse, the program is on your computer, but when you work on a network there may be a problem on firewall of network. Check that the 9000 port that uses the socket is open on the firewall, of course only in the network in which you use it.

Why used heap is always increasing in my MINA application?

I have an application which consists of two parts as server and client.
It works like this :
Client connects to the server and sends a string; server receives the string and returns an ArrayList (by converting string) which contains 10000 elements.
I wrote a class (ClientConnector.java) which simulates many clients use one connection to take those 10000 elements from server.
When I run this two programs, server side is ok. However on the client side, used heap is always increasing ! I tried to release the used objects by "null" but the used memory is still getting larger and larger.
http://s10.postimage.org/egf4ugrd5/mem.png
My Server Side Codes :
Client.java
public class Client {
private static final int PORT = 7571;
ClientHandler handler = new ClientHandler("hey");
IoConnector connector;
boolean available = true;
public synchronized void setAvailable(boolean available) {
this.available = available;
}
public synchronized boolean isAvailable() {
return available;
}
public void starter() throws InterruptedException {
Thread t = new Thread(new Runnable() {
#Override
public void run() {
connector = new NioSocketConnector();
connector.getSessionConfig().setReadBufferSize(2048);
TextLineCodecFactory t = new TextLineCodecFactory(Charset.forName("UTF-8"));
t.setEncoderMaxLineLength(20 * 150000);
t.setDecoderMaxLineLength(20 * 150000);
connector.getFilterChain().addLast("logger", new LoggingFilter());
connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(t));
connector.setHandler(handler);
ConnectFuture future = connector.connect(new InetSocketAddress("localhost", PORT));
future.awaitUninterruptibly();
if (!future.isConnected()) {
return;
}
IoSession session = future.getSession();
session.getConfig().setUseReadOperation(true);
session.getCloseFuture().awaitUninterruptibly();
connector.dispose();
}
});
t.start();
Thread.sleep(300);
}
public void conClose() {
connector.dispose();
}
public ClientHandler getHandler() {
return handler;
}
public void reqInf() {
handler.reqInfo();
}
public static void main(String[] args) {
try {
Client c = new Client();
c.starter();
} catch (InterruptedException ex) {
System.out.println("error");
}
}
}
ClientHandler.java
public class ClientHandler extends IoHandlerAdapter {
long time;
private final String values;
IoSession session;
public ClientHandler(String values) {
this.values = values;
}
#Override
public void sessionOpened(IoSession session) throws InterruptedException {
this.session = session;
}
public ArrayList<String> convert(String str) {
Gson gson = new Gson();
return gson.fromJson(str, ArrayList.class);
}
#Override
public void messageReceived(IoSession session, Object message) throws InterruptedException {
try {
ArrayList<String> test = convert(message.toString());
System.out.println("TIME : " + (System.currentTimeMillis() - time) + " strList:" + test.size());
message = null;
test = null;
} catch (Exception ex) {
ex.printStackTrace();
}
}
#Override
public void exceptionCaught(IoSession session, Throwable cause) {
session.close();
System.out.println(cause.toString());
}
#Override
public void sessionClosed(IoSession session) {
System.out.println("Connection Lost");
}
public void reqInfo() {
time = System.currentTimeMillis();
session.write("test");
}
}
My Server Side :
Server.java
public class Server {
private static final int PORT = 7571; //TEST PORT
IoAcceptor acceptor = new NioSocketAcceptor();
public Server() throws IOException {
TextLineCodecFactory t = new TextLineCodecFactory(Charset.forName("UTF-8"));
t.setEncoderMaxLineLength(20*150000);
t.setDecoderMaxLineLength(20*150000);
acceptor.getFilterChain().addLast("logger", new LoggingFilter());
acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(t));
// acceptor.getFilterChain().addLast("threadPool", new ExecutorFilter(Executors.newCachedThreadPool()));
Executor executor = new ThreadPoolExecutor(5, 70, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
acceptor.getFilterChain().addLast("threadPool", new ExecutorFilter(executor));
acceptor.setHandler(new ServerHandler());
acceptor.getSessionConfig().setReadBufferSize(2048);
acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 1000);
//timer();
acceptor.bind(new InetSocketAddress(PORT));
System.out.println("***Mina Server is ready !");
System.out.println("");
System.out.println("");
}
public static void main(String[] args) throws IOException {
Server m = new Server();
}
}
ServerHandler.java
public class ServerHandler extends IoHandlerAdapter {
private final Logger logger = (Logger) LoggerFactory.getLogger(getClass());
IoSession sessions;
//Communication communication;
public ServerHandler() throws IOException {
loader();
// communication = new Communication(this);
}
#Override
public void sessionOpened(IoSession session) {
// set idle time to 10 seconds
session.getConfig().setIdleTime(IdleStatus.BOTH_IDLE, 1000);
System.out.println("Client Connected !!!");
//session.setAttribute("Values: ");
this.sessions = session;
}
public String toGSon(ArrayList<String> list) {
Gson gson = new Gson();
String str = gson.toJson(list);
return str;
}
ArrayList<String> str = new ArrayList<String>();
public void loader() {
for (int i = 0; i < 10000; i++) {
str.add("test" + i);
}
}
#Override
public void messageReceived(IoSession session, Object message) throws InterruptedException {
long time = System.currentTimeMillis();
session.write(toGSon(str));
System.out.println("TIME : " + (System.currentTimeMillis() - time));
}
#Override
public void sessionIdle(IoSession session, IdleStatus status) {
System.out.println("Socket #" + session.getId() + " is disconnecting... (IDLE)");
session.close();
}
#Override
public void exceptionCaught(IoSession session, Throwable cause) {
System.out.println("------------>" + cause.toString());
session.close();
}
}
And my Main Class
public class ClientConnector {
public ClientConnector() throws InterruptedException {
Client cl = new Client();
cl.starter();
while (true) {
cl.reqInf();
Thread.sleep(100);
}
}
public static void main(String[] args) throws InterruptedException {
ClientConnector cl = new ClientConnector();
}
}
You must remove below code from client side.
session.getConfig().setUseReadOperation(true);
Above code will cause memory leak.
One of our developers found an issue in Mina with the way clean up was being done and a patch was applied to version 2.0.8. Since as of today this is "snapshot" you have to grab it from git and build it yourself. Here is the command to get it from git:
git checkout 2.0
Repository uri:
git clone http://git-wip-us.apache.org/repos/asf/mina.git
This code is not enough to reach to a pin pointed answer.
Heap size continuous increase and no effect of GC --> Signs of memory leak.
Probably you should Profile your application and use some OQL Tools to find out which class is using char[], which here is the culprit looking at heap dump in your case

Java Socket Server Not Receiving Messages?

Alright, so I'm not sure if there really is an error or not.
I've created a listening server using Java and NetBeans, and am trying to get the protocol to work.
However, for some reason it doesn't want to accept incoming messages.
It will accept incoming connections and set up the object used for handling a client, but just wont receive any messages.
I'm not sure what's going on, am I doing something wrong? Also, I already have port 7777 port forwarded, and I'm doing testing using "127.0.0.1".
======================================================================
I currently have 3 classes:
The main class, GMServer:
public class GMServer {
public static void main(String[] args) throws IOException {
CreateListener createListener = new CreateListener("USA Server East",7777,500);
}
}
======================================================================
The CreateListener class:
public final class CreateListener {
private ServerSocket listenSocket = null;
private String serverName = "";
private int serverPort = 7777;
private int serverMax = 500;
private boolean terminate = false;
private double connectID = 0;
private String currentUser = "-1";
private listenParser[] connections;
private int listenArray = 0;
public listenParser[] users;
public int usercount;
private boolean listenerConnected = true;
public double getCID() {
this.connectID++;
return this.connectID;
}
public CreateListener(String sName, int sPort, int sMax) throws IOException {
//Set the server name, port, and max users.
this.serverName = sName; this.serverPort = sPort; this.serverMax = sMax;
//Try to create a listener socket.
try { this.listenSocket = new ServerSocket(this.serverPort); } //If not successful, output error and end program.
catch (IOException e) { System.err.println("Could not create a listening server on port "+this.serverPort); System.exit(7777); }
//Let the console know that the listening server was created successfully.
System.out.println("Creating Server: \""+serverName+"\" On Port "+serverPort+"...");
while(listenerConnected) {
try {
Socket accepted = this.listenSocket.accept();
new listenParser(accepted,getCID(),sMax).start();
} catch (IOException e) {
//Socket Wasn't Accepted?
}
}
//Close down server after anything should cause the constant loop to end.
listenSocket.close();
}
}
======================================================================
and then the listenParser class (where it should be handling all traffic from clients):
public class listenParser extends Thread {
public Socket[] global_sockets;
public int connections = 0;
private PrintWriter _out = null;
private BufferedReader _in = null;
private double cid = 0;
private Socket socket = null;
private String currentUser = "";
private int timeout = 0;
private boolean connectionOpen = true;
private int socketTimeout = 0;
private int socketTimeoutMax = 1000;
private String room = "";
private long x = 0;
private long y = 0;
public listenParser(Socket sock, double acID, int maxUsers) {
super("listenParser");
this.socket = sock;
System.out.println("Connected To A Client...");
}
public String readString(BufferedReader tmpBuffer) {
try {
return tmpBuffer.readLine();
} catch (IOException e) {
return "";
}
}
public String protocol(String arg) {
String RETURN = "";
switch(arg) {
case "login": currentUser = "1"; break;
case "echo": this._out.println(readString(this._in)); break;
default: /*Do Nothing*/ break;
}
//Only allow access to these commands if the user is logged in.
if (currentUser!="") {
switch(arg) {
default: break;
}
}
return RETURN;
}
public boolean good() {
if (this.currentUser.equals("")) {
return false;
}
return true;
}
#Override
public void run() {
try {
_out = new PrintWriter(socket.getOutputStream(),true);
_in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
connections++; if (connections>500) { connectionOpen = false; }
while(connectionOpen) {
try {
String arguments, reply;
arguments = this._in.readLine();
reply = protocol(arguments);
socketTimeout = 0;
} catch (IOException e) {
socketTimeout++;
if (socketTimeout>socketTimeoutMax) {
connectionOpen = false; break;
}
}
}
_out.close();
_in.close();
socket.close();
System.out.println("Client Disconnected...");
} catch (IOException e) {
e.printStackTrace();
}
}
}
You are reading lines. Are you sending lines? Very common mistake. readLine() will block until it receives a newline, or EOS.
Speaking of EOS, the first thing you must do with the result of readLine() is check it for null, and if so close the socket and break out of the reading loop.

Categories

Resources