serversocket server + client issues - java

ok is hard for me to describe my problem now but then i will try my best to in order for me to get some assist.
technically i have a server.java and client.java as a super class. and my layout structure for my server and client connection goes like this
MAIN SERVER --- CLIENT/SERVER ----- CLIENT
my main problem is the this CLIENT/SERVER part is 1 driver class that calls 2 different classes which is CLIENT and SERVER together... and this creates a problem when my CLIENT sends something that needs to be received by MAIN SERVER side needs to go through CLIENT/SERVER part. if is that condition happens..
the CLIENT of course need to interact with CLIENT/SERVER (SERVER) part because is a SERVER that accepts the CLIENT data. but now i wanted the (SERVER) part in the CLIENT/SERVER to transfer the data to (CLIENT) in the CLIENT/SERVER part so that it can be send to the MAIN SERVER
how is it possible for me to write something that allows the CLIENT/SERVER to interact with each other so it can transfer the data between them vise versa? how ever this is my code for calling the CLIENT and SERVER together
public class Slave {
public static void main(String args []) throws IOException{
try{
// set Config file settings to slave mode
Config cfg = new Config("Slave");
String MasterServerIP = cfg.getProperty("ServerIP");
String MasterServerPort = cfg.getProperty("ServerPort");
String SlaveServerPort = cfg.getProperty("ListeningPort");
System.out.println("Slave Client connecting to Master Server");
// start connect to master server by calling the SlaveClient class
new SlaveClient(MasterServerIP,Integer.parseInt(MasterServerPort)).start();
int numClient = 0;
ServerSocket listener = new ServerSocket(Integer.parseInt(SlaveServerPort));
System.out.println("Server starts running");
try{
while(true){
// start listening to the server port by calling SlaveServer class
new SlaveServer(listener.accept(), numClient++, Integer.parseInt(SlaveServerPort)).start();
}
} finally {
listener.close();
}
} catch (FileNotFoundException file) {
System.out.println("File Not Found Error: "+file.getMessage());
}
}
}
the above is only the driver class that calls the 2 object class which is the SERVER and CLIENT side.
i will attach my slaveserver and slaveclient code here but i am not sure how to do it like you said
public class SlaveServer extends Server {
private JFrame frame = new JFrame();
private JTextArea msgArea = new JTextArea();
private JTextArea connectionArea = new JTextArea();
// SlaveServer Constructor
public SlaveServer(Socket socket, int numClient, int port) {
super(socket, numClient, port);
}
public void writeToMsg(String msg){
msgArea.append(msg+"\n");
}
public void writeToConnection(String msg){
connectionArea.append(msg+"\n");
}
public void run(){
try{
startGUI();
// initial BufferedReader and PrintWriter object by binding it with Socket
BufferedReader in = new BufferedReader(new InputStreamReader(getSocket().getInputStream()));
PrintWriter out = new PrintWriter(getSocket().getOutputStream(), true);
// welcome message send from server to client
out.println("Welcome to the Slave Server port:"+getPort()+" client #"+getNumClient());
while(true){
String readmsg = in.readLine();
writeToMsg(readmsg);
}
} catch (IOException e){
writeToMsg("Error in closing Socket");
}
writeToConnection("Connection from client #"+getNumClient()+" is closed");
}
}
public class SlaveClient extends Client{
private BufferedReader in;
private PrintWriter out;
private JFrame frame = new JFrame();
private JTextArea msgArea = new JTextArea();
private JTextArea connectionArea = new JTextArea();
// SlaveClient Constructor
public SlaveClient(String ip, int port) {
super(ip, port);
}
public void run(){
startGUI();
Socket sock = null;
try {
sock = new Socket(getIp(), getPort());
} catch (IOException e) {
e.printStackTrace();
}
try {
in = new BufferedReader(new InputStreamReader(sock.getInputStream()));
} catch (IOException e) {
e.printStackTrace();
}
try {
out = new PrintWriter(sock.getOutputStream(), true);
} catch (IOException e) {
e.printStackTrace();
}
out.println("TEST");
// while loop for reading message from server
while(true){
try {
getMsg(in);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

So you are trying to write a proxy?
You you need to give the server half of the proxy a reference to the client half, so that it can forward the data.
Then create a method in the client half to accept messages from the server half.
So each message you read in at the server half, you pass to the client half. The client half can then pass it to the real server.

Related

Socket inside bukkit plugin closes after use

I am trying to open a socket inside a bukkit plugin so i could send data to it using php or node but instead of socket remaining open after one use it just closes and also server does not load before this happens what should i do i am out of ideas.
Main:
public class Main extends JavaPlugin {
public void onEnable() {
saveDefaultConfig();
getConfig().options().copyDefaults(true);
System.out.println("[INFO] Main class loaded.");
start();
}
public void start() {
SocketServer server = new SocketServer();
try {
server.start(getConfig().getInt("port"), getConfig().getString("socket-password"));
System.out.println("[INFO] Main successfully called start.");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Socket server class:
When called this should read information convert it into array check the first item in array and use it as auth code then array should be converted into string and used in Command executor class. This works fine but after one use this just closes
public class SocketServer {
private ServerSocket serverSocket;
private Socket clientSocket;
private PrintWriter out;
private BufferedReader in;
public void start(int port, String socketpwd) throws IOException {
System.out.println("[INFO] Socket server listening on: " + port);
serverSocket = new ServerSocket(port);
clientSocket = serverSocket.accept();
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
Boolean enabled = true;
try {
// Socket authentication
String message = in.readLine();
String suffix[] = message.split(" ");
System.out.println("Socket auth code used: "+ suffix[0]);
System.out.println("Socket pwd is: " + socketpwd);
if (socketpwd.equals(suffix[0])) {
out.println("Auth sucessfull!");
// do the following command from args here
String command = suffix[1];
int suffixL = suffix.length;
// add arguments to command
for (int i = 2; i < suffixL; i++) {
command = command + " " + suffix[i];
}
// call req exec
System.out.println("[INFO] Socket server contacted Request executor with: " + command);
RequestExecutor.executor(command);
enabled = false;
}
else {
out.println("Unrecognised auth code!");
}
} catch (NullPointerException e) {
System.out.println("Exception prevented!");
}
}
public void stop() throws IOException {
in.close();
out.close();
clientSocket.close();
serverSocket.close();
}
}
Other problem as i mentioned is that bukkit server does not fully load before one request has been made to this socket.
Thank you for your help.
First of all you shouldn't be running a socket like that on the main thread, typically you should be running this on an async task using the Bukkit scheduler.
Then once you open the socket you should create a while loop to continuously poll for a connection and handle the incoming data. Instead what you are doing is opening the socket, reading a line and then dropping the connection.
You want to be doing something similar to
while(true){
Socket socket = serverSocket.accept();
}
See this webpage for some more info.

Messages are only being sent to the client that sent them in my chat program

In my chat client/server program I'm having trouble broadcasting the messages to all connected clients. The messages sent only seem to be sent back to the original server even though I'm iterating through an ArrayList. I have an ArrayList of sockets and a method that takes in the read message as a parameter and creates a PrintWriter for each socket. I think the problem has to do with my Client class (excuse me if I'm wrong) but I haven't been able to figure out what.
The Client Class:
public class H7Client extends Thread implements ActionListener{
private JTextField jtfPortName = new JTextField(20);
private JTextField jtfHostName = new JTextField(20);
private String hostName;
private int portNumber;
private JTextArea jtaChat = new JTextArea("Send a message to the client", 15,40);
private JTextArea jtaRecive = new JTextArea("WELCOME TO THE CHAT!", 15,40);
private JTextField jtfUName = new JTextField("user");
public H7Client(){
JFrame defaultFrame = new JFrame();
JLabel jlPortName = new JLabel("Enter The Port number");
JLabel jlHostName = new JLabel("Enter the Host name");
JLabel jlUName = new JLabel("Enter a username");
JButton jbSetSocketInfo = new JButton("Confirm Port and Host Info");
JButton jbExit = new JButton("Exit");
JButton jbSendText = new JButton("Send");
jbSetSocketInfo.addActionListener(this);
jbExit.addActionListener(this);
jbSendText.addActionListener(this);
JPanel jpNorth = new JPanel();
JPanel jpCenter = new JPanel();
JPanel jpLabels = new JPanel();
defaultFrame.add(jpNorth,BorderLayout.NORTH);
jpNorth.add(jbSetSocketInfo,BorderLayout.EAST);
jpNorth.add(jbSendText, BorderLayout.CENTER);
jpNorth.add(jbExit,BorderLayout.WEST);
defaultFrame.add(jpCenter,BorderLayout.CENTER);
jpCenter.add(jtaChat,BorderLayout.SOUTH);
jpCenter.add(jpLabels,BorderLayout.NORTH);
jpLabels.setLayout(new GridLayout(2,3));
jpLabels.add(jlHostName);
jpLabels.add(jlPortName);
jpLabels.add(jlUName);
jpLabels.add(jtfHostName);
jpLabels.add(jtfPortName);
jpLabels.add(jtfUName);
defaultFrame.add(jtaRecive,BorderLayout.SOUTH);
defaultFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
defaultFrame.setLocationRelativeTo(null);
defaultFrame.setSize(800,800);
defaultFrame.setVisible(true);
}
public void setClientComms(String message){
try{
// open communications to the server
Socket s = new Socket(hostName, portNumber);
ClientThread ct = new ClientThread(s, message);
}
catch(IOException e){
e.printStackTrace();
}
}
class ClientThread extends Thread{
public ClientThread(Socket sock, String msg) {
try {
// open input stream
InputStream in = sock.getInputStream();
BufferedReader br = new BufferedReader(
new InputStreamReader(in));
// open output stream
OutputStream out = sock.getOutputStream();
PrintWriter pout = new PrintWriter(
new OutputStreamWriter(out));
// write something to the server
pout.println(msg);
// make sure it went
pout.flush();
// read something back from server
String incomingMessage = br.readLine();
// print the something to the user
System.out.println("Message: " + msg);
//jtaChat.setText("");
jtaRecive.append("\n" + msg);
// Send the terminating string to the server
pout.println("quit");
pout.flush();
// close everything
pout.close();
br.close();
sock.close();
} catch (UnknownHostException uhe) {
System.out.println("What host you speak of?");
} catch (IOException ioe) {
System.out.println("Bad IO?");
ioe.printStackTrace();
}
}
}
public void actionPerformed(ActionEvent event) {
if (event.getActionCommand().equals("Exit")) {
System.exit(0);
} else if (event.getActionCommand().equals("Send")) {
String chatMessage = jtaChat.getText();
jtaChat.setText("");
setClientComms(chatMessage);
} else if (event.getActionCommand().equals("Confirm Port and Host Info")) {
hostName = jtfHostName.getText();
//NEED TO ADD IN WAY TO HANDLE IP ADDRESSES
portNumber = Integer.parseInt(jtfPortName.getText());
}
}
public static void main(String [] args) {
new H7Client();
}
}
The Server Class:
public class H7Server{
public ArrayList<Socket> clients = new ArrayList<Socket>();
public static void main(String[] args){new H7Server();}
public H7Server()
{
ServerSocket ss = null;
try {
System.out.println("getLocalHost: "+ InetAddress.getLocalHost() );
System.out.println("getByName: "+InetAddress.getByName("localhost") );
ss = new ServerSocket(16789);
Socket cs = null;
while(true){ // run forever once up
//try{
cs = ss.accept(); // wait for connection
clients.add(cs);
ThreadServer ths = new ThreadServer( cs );
ths.start();
} // end while
}
catch( BindException be ) {
System.out.println("Server already running on this computer, stopping.");
}
catch( IOException ioe ) {
System.out.println("IO Error");
ioe.printStackTrace();
}
} // end main
class ThreadServer extends Thread {
Socket cs;
public ThreadServer( Socket cs ) {
this.cs = cs;
}
public void run() {
BufferedReader br;
String clientMsg;
try {
br = new BufferedReader(
new InputStreamReader(
cs.getInputStream()));
clientMsg = br.readLine(); // from client
System.out.println("Server read: " + clientMsg);
while(clientMsg != null) {
sendMessage(clientMsg);
}
} catch (IOException e) {
System.out.println("Inside catch");
e.printStackTrace();
}
}
public synchronized void sendMessage(String s){
try{
for(Socket sock: clients) {
PrintWriter pw = new PrintWriter(new OutputStreamWriter(sock.getOutputStream()));
pw.println(s);
pw.flush();
}
}
catch(IOException e){
e.printStackTrace();
}
}
} // end class ThreadServer
}
There are problems with both your client class, as you suspected, and also the server class. There are two things you need to fix.
First, you receive the message from the server but aren't doing anything with it. The client receives incomingMessage in the try block of ClientThread's constructor but is unused. A possible fix is to append it to jtaReceive and to remove the other append, but don't do this.
For real-time chatting, the client must have a minimum of two threads: one to send messages, and one to constantly check if there are any messages to receive. Perhaps, this is what you were trying to achieve with ClientThread but it unfortunately does not work. In addition to the wrong code, your use of ClientThread creates a Thread but never actually runs it. You need to have a thread that, in the run method, contains a forever while loop that constantly receives messages from the server. One implementation is this: (you can rename to anything you like)
class ReceiverThread extends Thread {
private BufferedReader s;
public ReceiverThread(Socket sock) throws IOException {
s = new BufferedReader(new InputStreamReader(sock.getInputStream()));
}
#Override
public void run() {
while (true)
try {
String message = s.readLine();
// ...code to do whatever with message...
} catch (IOException e) {
e.printStackTrace();
}
}
}
Furthermore, you also need to create a socket that stays open (maybe create and start this thread with the socket when you confirm host and port info).
The problem with the server class is a problem that gets us all: the notorious ConcurrentModificationException. You can read about it here, but basically this exception is thrown when you modify (add, remove, etc.) a data structure when you aren't supposed to. The data structure in question is the ArrayList of Socket's, and the when is during the for-each loop when you are sending the message. Basically, while that loop is running, the while loop creating Socket's is adding them to the ArrayList and throwing the exception. To fix, you need to stop modifying the ArrayList when you are in the for loop, possibly by removing the while loop, holding the while loop until the for loop is finished, or even having a Queue of sockets to be added when the for loop is active, but there are many ways to do this.
I am assuming that your server will only receive one message, just to test, but if you decide that you want to be able to chat more than one message, you must use the extra thread you use for client class.
Best of luck :).
Note: I advise against use of AWT thread (the thread that calls actionPerformed) for networking stuff/anything that may take some time, or your application GUI will actually freeze.

what happens to a message when it gets to a server without reading stream in java?

If I have a server and a client and I opened a socket between the two:
1.Is it possible that the client will have a printWriter stream, in order to write things to the socket, but the server won't have in the mean time a bufferReader?
If the answer of 1 is yes, if that client will send a message to the server (who currently doesn't have a reading stream), what will happend to this message until te server will create a reading stream and read the message?
thank you
This is not at all specific to Java, but TCP/IP. There are buffers to keep the data received, so it's not possible that some data would be lost because one end isn't "ready" yet. This is because TCP will retransmit data that hasn't been acknowledged as received, guaranteeing that all the bytes that are written are received on the other (barring obvious cases).
in addition to #Kayaman's answer:
consider this Compile-able simple Java implemented example:
Server Side:
import java.io.*;
import java.net.*;
public class SimpleServer implements Runnable{
int serverPort = 45000;
ServerSocket serverSocket = null;
boolean isStopped = false;
public SimpleServer(int port){
this.serverPort = port;
}
public void run(){
try {
serverSocket = new ServerSocket(serverPort);
} catch (IOException e) {
System.err.println("Cannot listen on this port.\n" + e.getMessage());
System.exit(1);
}
while(!isStopped){
try {
Socket clientSocket = serverSocket.accept();
} catch (IOException e) {
// do nothing
}
}
}
public static void main(String[] args) throws IOException {
SimpleServer server = new SimpleServer(45000);
new Thread(server).start();
System.out.println("Server is waiting to connect");
}
}
Client Side:
import java.io.*;
import java.net.*;
public class SimpleClient {
public static void main(String[] args) throws IOException {
Socket socket = null;
PrintWriter out = null;
try {
socket = new Socket("127.0.0.1", 45000);
out = new PrintWriter(socket.getOutputStream(), true);
System.out.println("output stream created");
out.write(9);
System.out.println("message was sent to output with no listener");
} catch (UnknownHostException e) {
// do nothing
} catch (IOException e) {
// do nothing
}
}
}
the example is an implementation of a very basic client server connection in which a socket is created and a stream is defined only on the client side, followed by a write to the stream that will eventually be read by the server (if at all).
therefore, to answer you questions:
1) yes, it's possible to open a one-way connection stream without a "listener"
2) edit: according to #EJP: It will be saved within the socket's buffer until it is read or the socket is closed.

Socket server, I don't receive the message sent by my Server

I Have a client-Server connection..
Whem my server is connected to the client it must send a message through the outputstream and then print it when it receive the message from the inputStream. But when the client is connected I receive back the "Connected" message but I don't see the "this is a Text message\n" sent my the Server
This is my Server:
public class Server1 extends JFrame{
static JTextArea testoarea;
static Socket socket;
static ServerSocket server;
public Server1(){
testoarea = new JTextArea();
add(new JScrollPane(testoarea));
setSize(600, 700);
setVisible(true);
}
public static void main(String[] args) {
Server1 server1 = new Server1();
server1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
inizzializza();
connetti();
}
private static void inizzializza(){
try {
server = new ServerSocket(7100);
showMessage("Server Iniziato\n");
} catch (IOException e) {
System.out.println(e);
}
}
private static void connetti() {
try {
socket = server.accept();
showMessage("Connected \n");
PrintWriter output = new PrintWriter(socket.getOutputStream());
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
output.println("this is a Test message\n");
showMessage(input.readLine().toString());
output.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
private static void showMessage(final String text) {
// TODO Auto-generated method stub
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
testoarea.append(text);
}
}
);
}
}
this is what I get back:
Your input.readLine() is on your server side client input stream. That means it tries to read an income message from the client.
If you wan't read the message send by the server to the client from the client side (what I think you want, but I maybe misunderstood). You have to get the client socket input stream.
The socket you get where you have probably call somewhere:
Socket clientSocket = new Socket("localhost", 7100);

testing a client server

I wrote a server that listens for client messages, it's a variation of http://docs.oracle.com/javase/tutorial/networking/sockets/clientServer.html. I wrote them both in eclipse as java classes in the same project. To test it I have a client class with a main that starts the server and then sends messages to it. When I run it the program just hangs at serverSocket.accept(); according to the javadoc for ServerSocket accept is not asynchronous? That would explain the hanging, but then how does the tutorial code work then?
UPDATE - here is my working code:
Here is the working code:
MyServer.java
/*imports neglected for brevity */
public class MyServer {
public static final String hostname = "localhost";
public static final int portNum = 4444;
ServerSocket serverSocket;
BufferedReader serverReader;
File serverLog;
FileWriter fw;
BufferedWriter serverWriter;
Socket clientSocket;
public static void main(String[] args) {
MyServer server = new MyServer(portNum);
// start the server so it can listen to client messages
server.start();
}
public MyServer(int portNum) {
try {
// endpt for server side, used to listen for client socket
serverSocket = new ServerSocket(portNum);
/* have server socket listen for connection, return client socket.
* serverSocket can now talk to clientSocket
*/
clientSocket = serverSocket.accept();
// server writes messages to this log
serverLog = new File("ServerLog.txt");
if(!serverLog.exists())
serverLog.createNewFile();
fw = new FileWriter(serverLog.getAbsoluteFile());
serverWriter = serverWriter = new BufferedWriter(fw);
/* server reads from this stream that is populated by the client's
* OUTPUT stream/client socket's INPUT stream
*/
serverReader = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream())
);
}
catch (Exception e) {
e.printStackTrace();
}
}
public void start() {
String clientMsg;
try {
while((clientMsg = serverReader.readLine()) != null) {
if(clientMsg.startsWith("exit")) {
break;
}
serverWriter.append(clientMsg);
}
serverWriter.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
MyClient.java
public class MyClient {
public static final String hostname = "localhost";
public static final int portNum = 4444;
public static void main(String[] args) {
String msg = "message 1";
try {
// server is listening on http://localhost:4444
Socket serversSocket = new Socket(hostname, portNum);
PrintWriter clientOut = new PrintWriter(serversSocket.getOutputStream(), true);
// send first message
clientOut.println(msg);
msg = "message 2";
// send second message
clientOut.println(msg);
msg = "exit";
// this will stop the server
clientOut.println(msg);
}
catch (Exception e) {
e.printStackTrace();
}
}
}
If you go through the tutorial it creates two applications one with client one with server.
You cannot create a variation like this as, when you call the constructor, your whole application blocks in clientSocket = serverSocket.accept();.
If you insist on creating a single application for whatever reason, you can do multithreading. But I do not see any reason why you would want to do that.
The tutorial assumes you are not running them in the same program. If you must run them in the same program, then start your server in a separate thread.
if you have an android phone you can test this with the app TCP socket
make sure you PortForward the port the server is listening to.
some isp also block ports so make sure with your isp that all ports are open
trust me broke my head on this one :)
http://docs.oracle.com/javase/6/docs/api/java/net/ServerSocket.html
also make sure your server has the public ip and not local ip
if you test this localy then the code above is fine if not you will need to add
bind(SocketAddress endpoint)
/*Binds the ServerSocket to a specific address (IP address and port number).*/
you can find your ip by typeing in google: whats my ip

Categories

Resources