i have written a client - server programm, where different clients and server communicate via request/reply using xml and tcp sockets. Later i want to add udp sockets. This is the current code:
Client:
package network.client;
import java.io.BufferedReader;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
public class Client implements Closeable {
private Socket socket;
public Client(String host, int port) throws IOException {
this(new Socket(host, port));
}
public Client(Socket s) {
this.socket = s;
}
#Override
public void close() throws IOException {
this.socket.close();
}
public void send(String msg) throws IOException {
OutputStream out=this.socket.getOutputStream();
out.write(msg.getBytes());
out.flush();
socket.shutdownOutput();
}
public void recv() {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String request="";
String temp=in.readLine();
while(temp!=null) {
request+=temp;
temp=in.readLine();
}
socket.shutdownInput();
System.out.println("Client: " + request);
System.out.println(request.toString().length());
} catch (IOException ex) {
System.err.println("Error: Unable to read server response\n\t" + ex);
}
}
public static void main(String[] args) {
// Make sure command line arguments are valid
String ip="127.0.0.1";
int port=5000;
StringBuilder sb = new StringBuilder();
sb.append("stuff");
System.out.println(sb.toString().length());
try (Client c = new Client(ip, port)) {
c.send(sb.toString());
c.recv();
c.close();
} catch (IOException ex) {
System.err.println("Error: " + ex);
}
}
}
Server:
package network.server;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Server {
private static ServerSocket serversocket;
private static ExecutorService threadpool;
private String ip;
private int port;
public static void main(final String[] args) {
Server2 server;
String ip = "127.0.0.1";
int port = 5000;
try {
server = new Server(ip, port);
while (true) {
Runnable requestHandler = null;
try {
requestHandler = new TCPRequestHandler(serversocket.accept());
} catch (IOException io) {
System.out.println("Accepting client connection failed");
io.printStackTrace();
}
threadpool.submit(requestHandler);
}
} catch (IOException io) {
System.out.println(io.getMessage());
io.printStackTrace();
}
System.out.println("end");
}
public Server(String ip, int port) throws IOException {
this.ip = ip;
this.port = port;
try {
this.serversocket = new ServerSocket();
serversocket.bind(new InetSocketAddress(ip, port));
} catch (IOException io) {
throw new IOException("Creating the ServerSocket failed");
}
System.out.println("Binding the server succeeded");
this.threadpool = Executors.newCachedThreadPool();
}
}
RequestHandler:
public class TCPRequestHandler extends Thread{
private Socket clientSocket=null;
public TCPRequestHandler(Socket clientSocket) {
this.clientSocket=clientSocket;
}
public void run(){
System.out.println("Accepted client connection (" + clientSocket.getInetAddress().getHostAddress() + ", " + clientSocket.getPort() + ")");
byte[] buffer = new byte[1024];
int count;
try {
BufferedReader in =new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
OutputStream out = clientSocket.getOutputStream();
String request="";
String temp=in.readLine();
while(temp!=null) {
request+=temp;
temp=in.readLine();
}
System.out.println("Server:" + request);
System.out.println(request.toString().length());
// do stuff with xml request
out.write(request.getBytes());
out.flush();
clientSocket.shutdownInput();
clientSocket.shutdownOutput();
} catch (IOException io) {
System.err.println("IO initialization failed");
}
}
}
XML Request:
<Request>
<Info Attribute1="" Attribute2=""></Info>
<Info Attribute1="" Attribute2=""></Info>
</Request>
XML Reply (the overhead sending back the attributes will be necessary for the client, so i have to send it twice):
<Reply>
<Info Attribute1="" Attribute2="">GoodReply</Info>
<Info Attribute1="" Attribute2="">GoodReply</Info>
</Reply>
My question is 2-folded:
1.) Maybe I did something unusual at the client-server programming (forgetting to close something, unusual stream reading/handling). Reading every line of the client/server message seems to be e.g. weird for me, because i'd rather read the xml message until it is finished independently of its line). Feel free to provide me "good coding style" advice :-)
2.) At the moment i would assemble the XML by a StringBuilder and send just the bytes of the whole String and without special characters like \r \n. I'm not sure how to do it with a common api like Stax (this seemed to be complicated). Parsing the Attributes and their content will be necessary for the application. Is there an easier/more common way to solve this?
If not: how to do it with e.g Stax?
Good question!
Since TCP is a streaming protocol, you don't really know where the message begins and where it ends, unless you specify that each connect/disconnect contains exactly one message, or that you specify some delimiting mechanism (a framing protocol). Actually, it might be easier to start with UDP, since a datagram could contain the entire message in itself.
As for the framing protocol, an example is the Using the NETCONF Protocol over Secure Shell specification. You can of course devise your own framing.
Related
I'm running a client and server on my local machine and trying to send text messages between the two. Both sides are able to read and write. I'm using ObjectInputStream and ObjectOutputStream because I need to serialize objects. Github repo
My issue is when I try to send messages from both sides, they don't get through to the other side and the listeners hang.
Host.java
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Host {
private ServerSocket serverSocket;
private Socket clientSocket;
private ObjectOutputStream out;
private ObjectInputStream in;
private int portNumber = Settings.PORT;
public Host() {
acceptConnection();
CommandListener commandListener = new CommandListener(in);
}
private void acceptConnection() {
try {
serverSocket = new ServerSocket(portNumber);
clientSocket = serverSocket.accept();
out = new ObjectOutputStream(clientSocket.getOutputStream());
in = new ObjectInputStream(clientSocket.getInputStream());
} catch (IOException e) {
System.out.println("Exception caught when trying to listen on port "
+ portNumber + " or listening for a connection");
System.out.println(e.getMessage());
}
}
public ObjectOutputStream getOut() {
return out;
}
public ObjectInputStream getIn() {
return in;
}
}
Client.java
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client {
private int portNumber = Settings.PORT;
private ObjectOutputStream out;
private ObjectInputStream in;
private Socket clientSocket;
public Client(String ip) {
connectToHost(ip);
CommandListener commandListener = new CommandListener(in);
}
public ObjectOutputStream getOut() {
return out;
}
public ObjectInputStream getIn() {
return in;
}
private void connectToHost(String ip) {
try {
clientSocket = new Socket(ip, portNumber);
out = new ObjectOutputStream(clientSocket.getOutputStream());
in = new ObjectInputStream(clientSocket.getInputStream());
} catch (UnknownHostException e) {
System.err.println("Don't know about host " + ip);
e.printStackTrace();
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to " + ip);
e.printStackTrace();
}
}
}
The CommandListener.java class is a thread which is started independently by both the client and the server.
import java.io.IOException;
import java.io.ObjectInputStream;
public class CommandListener implements Runnable{
private ObjectInputStream in;
public CommandListener(ObjectInputStream in) {
this.in = in;
run();
}
public void run() {
String inboundCmd;
try {
System.out.println("listener running, waiting for inbound command");
inboundCmd = (String) in.readObject();
System.out.println("listener read inbound command" + inboundCmd);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
Both hang after printing out listener running, waiting for inbound command.
Here's how I start the client and the server:
RunHost.java
import java.io.IOException;
import java.io.ObjectOutputStream;
public class RunHost {
public static void main(String[] args) throws IOException {
Host host = new Host();
ObjectOutputStream out = host.getOut();
out.writeObject("host sending");
out.flush();
}
}
RunClient.java
import java.io.IOException;
import java.io.ObjectOutputStream;
public class RunClient {
public static void main(String[] args) throws IOException {
Client client = new Client("localhost");
ObjectOutputStream out = client.getOut();
out.writeObject("client sending");
out.flush();
}
}
Any idea how to fix this?
The reason why it seems like both the host and the client are "hanging" is simply because nobody managed to write anything before listening to the other party.
You should be running RunHost.java before RunClient.java. Starting from there, you can trace the program:
Construct a new Host (i.e. RunHost.java is ran)
Blocks and wait for a client socket to connect
Construct a new Client (i.e. RunClient.java is ran)
Both ServerSocket's and ClientSocket's input and output streams are initialised
Both ServerSocket and ClientSocket start constructing CommandListener
Both ServerSocket and ClientSocket start listening for an input
See the problem yet? The main issue is because you call the method run() within the CommandListener constructor, so both Server and Client side start to block on listening without anyone having sent anything.
A quick fix would be to take out the run() call from the CommandListener constructor function, and then call it separately when you are ready for it.
For example:
Change the constructor in CommandListener.java to:
public CommandListener(ObjectInputStream in) {
this.in = in;
}
Add a way to get the CommandListener for the client in Client.java (note that this means you should store the CommandListener by doing cl = new CommandListener(in); in the Client constructor):
public CommandListener getCL() {
return cl;
}
Change RunClient.java to something like:
public static void main(String[] args) throws IOException {
Client client = new Client("localhost");
ObjectOutputStream out = client.getOut();
out.writeObject("client sending");
out.flush();
CommandListener cl = client.getCL();
cl.run();
}
And lastly, call CommandListener's run() method in Host's constructor:
public Host() {
acceptConnection();
CommandListener commandListener = new CommandListener(in);
commandListener.run();
}
And it should work as per expected.
But to be honest, given the mess that CommandListener is causing, you may want to reconsider having that class in the first place. I mean, over here it doesn't seem to be necessary, so...
P/S Feel free to let me know if anything is unclear/ it still does not work
I want to know about my socket code and how will it affect my server hardware and other software
I have a linux server with static IP address.
I want to send data from lot of clients to this server using sockets
This is my server side code for the socket
import java.io.DataInputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerSocketExample implements Runnable {
public static void main(String[] args) {
ServerSocketExample start = new ServerSocketExample();
start.run();
}
#Override
public void run() {
try {
ServerSocket ss = new ServerSocket(6664);
Socket s = ss.accept();
DataInputStream dis = new DataInputStream(s.getInputStream());
String str = (String) dis.readUTF();
System.out.println("This: 1: "+str);
if (str != null && !str.trim().equals("")) {
processData(str);
}
s.close();
ss.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
run();
}
}
private void processData(String data) {
System.out.println("This: 3: " + data);
}
}
I want to know how this code may backfire me. Will this affects the server in any way?
Is there any better alternative?
Is this a better option?
Class 1.
import java.io.IOException;
import java.net.ServerSocket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class NetworkService implements Runnable {
private final ServerSocket serverSocket;
private final ExecutorService pool;
public NetworkService(int port, int poolSize) throws IOException {
serverSocket = new ServerSocket(port);
pool = Executors.newFixedThreadPool(poolSize);
}
public void run() {
try {
while (true) {
pool.execute(new Handler(serverSocket.accept()));
}
} catch (IOException ex) {
pool.shutdown();
}
}
}
Class 2.
import java.io.DataInputStream;
import java.net.Socket;
class Handler implements Runnable {
private final Socket socket;
Handler(Socket socket) {
this.socket = socket;
}
public void run() {
try {
DataInputStream dis = new DataInputStream(socket.getInputStream());
String str = (String) dis.readUTF();
System.out.println("This: 1: "+str);
processData(str);
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
private void processData(String data) {
System.out.println("This: " + data);
}
}
If you are trying to make a server that takes in multiple clients you have 2 choices. Learn about multi threaded applications or learn about using a selector in the java.nio library.
How to use a selector for multiple users
Multiple thread application
I personally recommend the selector, it is more advanced but it takes less resources which will make it easier for your server.
Hope this helps.
Your class 1 is an issue, your class 2 is mostly correct.
Your issues in class 1 include:
You only need 1 ServerSocket to receive all the client Sockets
public class NetworkService{
static final int PORT = 1978;
public static void main(String args[]) {
ServerSocket serverSocket = null;
Socket socket = null;
try {
serverSocket = new ServerSocket(PORT);
} catch (IOException e) {
e.printStackTrace();
}
while (true) {
try {
socket = serverSocket.accept();
} catch (IOException e) {
System.out.println("I/O error: " + e);
}
// new thread for a client
new Handler(socket).start();
}
}
}
If you want to make it a separate class by all means, that implements Runnable I don't suggest it but by all means.
I have never worked with DataInputStream for reading and writing to using a socket I use BufferedReader for reading & PrintWriter for writing. For use on how to do this oracle gave a tutorial on sockets. This is an example of a server with BufferedReader and PrintWriter
I am new to java and network programming for the most part. I want to write a program that automatically backs up my texts to my computer whenever my phone connects to my home wifi.
I am working on creating java classes that will handle sending data over the network. Using some questions found here, I came up with this implementation but I have some questions regarding some of the methods used in what I learned from.
Two Questions Regarding this code
I totally used a question from SO for the send methods in my client. The sendText uses a new thread, but the sendFile doesn't. Any particular reason why?
2. At which point in the code does the server actually know when there has been a message sent to the port? Is it at the method accept() call or is it when the BufferStream readLine() is checked? Does accept just grab data and throw it into the buffer? null implying the data grabbed was not a signal sent from a client?
Does the accept() method block execution of the code until a connection attempt is made from a client?
Thanks!
KServ
//Used to launch the server
public class KServ {
public static void main(String[] args) {
if (args.length != 1) {
System.err.println("Usage: java KServ <port number>");
System.exit(1);
}
int port = Integer.parseInt(args[0]);
KServer server = new KServer(port);
while (true) { //added this to keep the server polling for new data
server.run();
}
}
}
KServer
//Server class. Should handle data incoming
import java.net.*;
import java.io.*;
public class KServer {
private int port;
public KServer(int PORT) {
port = PORT;
}
public void run() {
try (
ServerSocket sSocket = new ServerSocket(port);
Socket cSocket = sSocket.accept();
PrintWriter out = new PrintWriter(cSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(cSocket.getInputStream()));
) {
String input;
while ((input = in.readLine()) != null) {
System.out.println(input);
}
} catch (IOException e) {
System.out.println("Exception caught when trying to listen on port " + port + " or listening for a connection");
System.out.println(e.getMessage());
}
}
}
Client
//launches KClient object and uses it to send input from console to the server
import java.util.Scanner;
public class Client {
public static void main(String[] args) {
if (args.length != 2) {
System.err.println("Usage: java Client <ip number> <port number>");
System.exit(1);
}
String ip = args[0];
int port = Integer.parseInt(args[1]);
KClient client = new KClient(ip,port);
String msg;
Scanner inStream = new Scanner(System.in);
while((msg = inStream.nextLine()).length() > 0) {
client.sendText(msg);
}
}
}
KClient
//Will be used to establish connection with server and send data from phone
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class KClient {
private String server;
private int port;
public KClient(String Server,int Port) {
server = Server;
port = Port;
}
public void sendFile(String fileName) {
File file = new File(fileName);
FileInputStream fileInputStream;
BufferedInputStream bufferedInputStream;
OutputStream outputStream;
try {
client = new Socket(server,port);
byte[] bytes = new byte[(int) file.length()];
fileInputStream = new FileInputStream(file);
bufferedInputStream = new BufferedInputStream(fileInputStream);
bufferedInputStream.read(bytes, 0, bytes.length);
outputStream = client.getOutputStream();
outputStream.write(bytes,0,bytes.length);
outputStream.flush();
bufferedInputStream.close();
outputStream.close();
client.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private Socket client;
private OutputStreamWriter outputStreamWriter;
public void sendText(String msg) {
System.out.println("Send Message!");
new Thread(new Runnable() {
#Override
public void run() {
try {
client = new Socket(server,port);
outputStreamWriter = new OutputStreamWriter(client.getOutputStream(), "ISO-8859-1");
outputStreamWriter.write(msg);
outputStreamWriter.flush();
outputStreamWriter.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
BufferedReader inStream;
public boolean Shake() {
try {
client = new Socket(server,port);
inStream = new BufferedReader(new InputStreamReader(client.getInputStream()));
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return true;
}
}
I totally used a question from SO for the send methods in my client. The sendText uses a new thread, but the sendFile doesn't. Any particular reason why?
Unanswerable. Ask the author. Both sends can block. As the file is presumably longer than the text, it would have made more sense to do it the other way round.
2. At which point in the code does the server actually know when there has been a message sent to the port? Is it at the method accept() call
No.
or is it when the BufferStream readLine() is checked?
Yes.
Does accept just grab data and throw it into the buffer?
No. It grabs a connection and returns it as a socket. Nothing to do with data whatsoever.
null implying the data grabbed was not a signal sent from a client?
You seem to be actually asking about BufferedReader.readLine() here, not ServerSocket.accept(), which doesn't return null. readLine() returns null when there is no pending data to be read and the peer has closed the connection.
Does the accept() method block execution of the code until a connection attempt is made from a client?
More or less. It blocks until there is a complete connection waiting to be accepted, which isn't quite the same thing, as there is a queue.
I will add that you have copied, or written, some truly terrible code here. There are much better examples.
I know this question has been asked before, and I've tried the different solutions, but I got stuck in the implementation part.. :(
Currently multiple clients can connect to the server, I used the multithreaded KnockKnock server/client example from javadocs, and edited it slightly so that you can just send messages to the server, and it will echo them back to you, but I want to be able to make it so that if client 1 sends a message, then the server will broadcast them back to all the clients connected to the server.
I've tried looking around and saw people in the same position as I am in now, and they were told to make a list to keep track of all the connections, and then iterate through the list and send the message, but I really don't know in which class to put it or how to handle it.
If someone could show me or just give me hints to where I should start, it would be greatly appreciated, as I'm really just stuck at the moment :(
Here's where I'm at so far:
Server:
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
public class Server {
public static void main(String[] args) throws IOException {
boolean listening = true;
try (ServerSocket serverSocket = new ServerSocket(4444)) {
while (listening) {
ServerThread thread = new ServerThread(serverSocket.accept());
thread.start();
}
} catch (IOException e) {
System.err.println("Could not listen on port " );
System.exit(-1);
}
}
}
ServerThread
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
public class ServerThread extends Thread{
private Socket socket = null;
public ServerThread(Socket socket) {
super("MultiServerThread");
this.socket = socket;
}
public void run() {
try (
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(
socket.getInputStream()));
) {
while (true) {
String input = in.readLine();
System.out.println(input);
out.println("ecco " + input);
if (input.equals("Bye"))
break;
}
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Client (not sure if necessary, but here is it anyways)
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client {
public static void main(String[] args) throws IOException {
try (
Socket kkSocket = new Socket("172.30.242.51", 4444);
PrintWriter out = new PrintWriter(kkSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(kkSocket.getInputStream()));
) {
BufferedReader stdIn =
new BufferedReader(new InputStreamReader(System.in));
while (true) {
if(in != null) {
String input = stdIn.readLine();
out.println("Client: " + input);
System.out.println(in.readLine());
out.flush();
}
}
} catch (UnknownHostException e) {
System.err.println("Don't know about host " );
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to " );
System.exit(1);
}
}
}
Have a nice weekend =)
Operation 'write' is blocking in your example. So iterating by all connections can lead to delays and blocking your push thread. Also always set SO_TIMEOUT for socket if you do not want to have memory leaks.
I suggest using netty server
It has very nice functionality for pushing data to all connected clients - look for ChannelGroup
Why don't you use NIO to solve this problem?
A simple example:
public class EchoServer {
public static void main(String[] args) throws Exception {
//Create TCP server channel
ServerSocketChannel serv = ServerSocketChannel.open();
ServerSocket sock = serv.socket();
//Create a socket on your IP and port (i.e: localhost:12345)
SocketAddress addr = new InetSocketAddress(12345);
//Bind server socket and socket address
sock.bind(addr);
//Configure socket so all its methods won't be blocking
serv.configureBlocking(false);
//Create a selector to attend all the incoming requests
Selector selector = Selector.open();
//Register into the selector the accept request type
serv.register(selector,SelectionKey.OP_ACCEPT);
//Create a common buffer
ByteBuffer commonBuffer = ByteBuffer.allocate(10000);
commonBuffer.clear();
Iterator<SelectionKey> it = null;
ByteBuffer channelBuffer = null;
for (;;){ //Infinite loop
System.out.println("Waiting for events......");
selector.select(); // This call do is blocking
System.out.println("New event received");
it = selector.selectedKeys().iterator();
while(it.hasNext()) {
SelectionKey key = (SelectionKey) it.next();
System.out.println(String.format("Processing %s", key));
it.remove(); // Remove it to avoid duplications
try{
if (key.isAcceptable()) {
System.out.println("Received new connection request");
processConnectionRequest(serv, selector);
}else if (key.isReadable()) {
System.out.println("Received new reading request");
processReadingRequest(selector, commonBuffer, key);
}else if (key.isWritable()) {
System.out.println("Received new writing request");
processWritingRequest(key);
}
}catch(Exception e){
key.cancel();
try {
key.channel().close();
} catch (Exception ce) {}
}//end catch
}//end while
}//end for
}//end main
private static void processWritingRequest(SelectionKey key) throws IOException {
SocketChannel cli = (SocketChannel) key.channel();
ByteBuffer buf = (ByteBuffer) key.attachment();
System.out.println(String.format("Wrinting into the channel %s", cli));
buf.flip();//prepare the buffer
buf.rewind();
cli.write(buf);
if (buf.hasRemaining()) {
//If there is more content remaining, compact the buffer
buf.compact();
} else {
buf.clear();
key.interestOps(SelectionKey.OP_READ);
}
}
private static void processReadingRequest(Selector selector, ByteBuffer commonBuffer, SelectionKey key)
throws IOException {
SocketChannel cli = (SocketChannel) key.channel();
if (cli.read(commonBuffer) == -1) {
System.out.println(String.format("Closing channel %s", cli));
cli.close(); // internally calls key.cancel()
}
else {//Send the data to all the channels
commonBuffer.flip();//prepare the buffer
Iterator<SelectionKey> it2 = selector.keys().iterator();
System.out.println("Writing data to all the channels");
SelectionKey keys = null;
while(it2.hasNext()) {
keys = it2.next();
System.out.println(String.format("Writing in %s", keys));
ByteBuffer buf = (ByteBuffer) keys.attachment();
if(buf!=null)
{
buf.put(commonBuffer);
keys.interestOps(SelectionKey.OP_WRITE|SelectionKey.OP_READ);
commonBuffer.rewind();
}
}
commonBuffer.clear();
}
}
private static void processConnectionRequest(ServerSocketChannel serv, Selector selector)
throws IOException, ClosedChannelException {
ByteBuffer channelBuffer;
SocketChannel cli = serv.accept();
cli.configureBlocking(false);
channelBuffer = ByteBuffer.allocate(10000);
System.out.println(String.format("Registering new reading channel: %s", cli));
cli.register(selector, SelectionKey.OP_READ, channelBuffer);
}
}
I am creating a multi client chat server and i am pretty confident that it will work (Correct me if i'm wrong), I have the issue that on the socket that the client connects to is null so the connections can't be created because i use if(Socket != null) so i don't get errors but i will explain my layout real fast. The server starts with a starter class called (LaunchServer) that uses the class object ClientConnector as Minecraft and then starts the method runServer(). Here is the code for this class:
public class LaunchServer
{
public static void main(String[] args)
{
System.out.println("[Info] Running");
ClientConnector Minecraft = new ClientConnector();
Minecraft.runServer();
}
}
It's fairly simple. This brings us to the ClientConnector class. Here we start at the method runServer(). Right away we have a try catch block. in that block we print a message that the server is trying to connect to the port 1337. we then create a new ServerSocket called serversocket. We then send a message to the console saying that we have bound to port and that we are awaiting a connection. While true, we create a new Socket socket that equals ServerSocket.accept(); OMG fuck it. Heres the code. you know what it does...
import java.util.ArrayList;
import java.net.*;
import java.io.*;
public class ClientConnector
{
public static ArrayList<Socket> Connections = new ArrayList<Socket>();
public static void runServer()
{
try
{
System.out.println("[Info] Attempting to bind to port 1337.");
#SuppressWarnings("resource")
ServerSocket serversocket = new ServerSocket(1337);
System.out.println("[Info] Bound to port 1337.");
System.out.println("[Info] Waiting for client connections...");
while(true)
{
Socket socket = serversocket.accept();
new ClientHandler(socket).start();
Connections.add(socket);
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
This takes us to the handler class:
import java.io.*;
import java.net.*;
public class ClientHandler extends Thread
{
Socket Socket;
public ClientHandler(Socket socket)
{
socket = Socket;
System.out.println("[Info] Client connected on port 1337.");
}
public void run()
{
while(true)
{
for(int i = 0; i < ClientConnector.Connections.size(); i++)
{
try
{
if(Socket != null)//This stays null...
{
ObjectOutputStream Output = new //These can't be created...
ObjectOutputStream(Socket.getOutputStream());
ObjectInputStream Input = new ObjectInputStream(Socket.getInputStream());
whileChatting(Input, Output);
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
public static void sendMessage(String message, String returnedMessage, ObjectOutputStream out)
{
try
{
if(!message.isEmpty())
{
out.writeObject("\247c[Server]\247d " + message);
out.flush();
System.out.println("[Chat] Sent: " + message);
}
else
{
out.writeObject(returnedMessage);
System.out.println("[Chat] Sent: " + returnedMessage);
}
out.flush();
System.out.println("[Info] Fluching remaining data to stream.");
System.out.println("\n[Server] " + message);
}
catch(IOException ioException)
{
System.out.println("[Warning] Error: ioException # sendMessage line 76.");
}
}
public static void whileChatting(ObjectInputStream input, ObjectOutputStream output) throws IOException
{
String message = "";
do
{
try
{
message = (String) input.readObject();
System.out.println("\n" + message);
sendMessage("", message, output);
}
catch(ClassNotFoundException classNotFoundException)
{
System.out.println("[Warning] Error: ClassNotFoundException # whileChatting line 1-7.");
System.out.println("\n idk wtf that user sent!");
}
}while(!message.equals("/stop"));
}
}
Read the run method. There you will see the null problem
Would the connection get accepted then passed to the hander class? How can a null connection get accepted? My question is how can i fix this problem?
The problem is you've got a logic error due to un-recommended naming conventions. You shouldn't name variables with keywords, like your Socket variable, and each variable should have a distinguishable name. e.g. not socket1, socket2 but serverSocket, clientSocket because that will make it easier for you and anyone else to read and fix your code.
Change
Socket Socket;
to
Socket connectedSocket;
and in your constructor
socket = Socket;
to
connectedSocket = socket;
then finally, in your run() method change
if(Socket != null)
to
if(connectedSocket != null)