What could be causing this socket not to find a port? - java

I am trying to create a server that receives UDP packets and responds with UDP messages. However, I can't seem to get it to bind to a port. Here's my constructor for the class:
public UDPServer() throws IOException {
myGUI = new ServerGUI();
myClientList = new ArrayList<ClientInfo>();
DatagramChannel channel = DatagramChannel.open();
mySocket = channel.socket();
//mySocket = new DatagramSocket(null);
//mySocket.setReuseAddress(true);
//mySocket.bind(new InetSocketAddress("localhost", Constants.SERVER_PORT_NUM));
myPortNum = mySocket.getPort();
myIP = mySocket.getInetAddress();
System.out.println(myPortNum + " " + myIP.toString());
}
I have tried both the channel method and the commented out method, and I even used this method to try and find an open port:
private DatagramSocket createNewSocket() throws IOException {
for (int i = Constants.MIN_PORT_NUM; i < Constants.MAX_PORT_NUM; i++){
try {
System.out.println(i);
return new DatagramSocket(i);
} catch (IOException e){
continue; // try next port
}
}
throw new IOException("No free port found");
}
But I've had no luck so far. The portNum keeps coming up as -1 and the IP is null. Any ideas what could be going on here?
EDIT: When I run the following in debug mode and scroll over mySocket to see what values it contains, it says that:
bound = true
closed = false
connectedAddress = null
connectedPort = -1
But when I run mySocket.getLocalPort(), it returns a valid port number. What's going on here?
Here's the code:
public UDPServer() throws IOException {
myGUI = new ServerGUI();
myClientList = new ArrayList<ClientInfo>();
mySocket = new DatagramSocket(Constants.SERVER_PORT_NUM);
mySocket.setReuseAddress(true);
myPortNum = mySocket.getLocalPort();
myIP = mySocket.getInetAddress();
System.out.println(mySocket);
}

You don't need to do this. Just create it with the non-args constructor, or specify port zero. The system will allocate a free port for you.

Related

Bitcoin protocol using socket (java)

I develop bitcoin protocol using socket, but met some issues. Firstly, when my code connects to bitcoin node, it doesn't give any response. I send version message, but another side node doesn't re-send anything. I think that problem could be that I implement protocol wrong, but I checked and think that it's fine. (2) Secondly, I think that could be impossible connect to bitcoin node using socket, but it's stupid idea. Yea?
One important thing, I coded only socket connection, version sending to bitcoin node, which I found on https://bitnodes.earn.com/nodes/ , and message receiving from node, but it always responses -1.
One more thing, I don't give response from node, but also don't give connection error. (I just say)
Please help me :)
What is wrong that I send version message, but then doesn't give another one from node?
Also, I attach output (connection phases and protocol structure) of console when try to connect to socket.
Connected
f9beb4d976657273696f6e0000000000000000660a75c8397f1101000100000000000000820b905c00000000010000000000000000000000000000000000ffff340e5966208d010000000000000000000000000000000000ffff7f000001208db910e81a17a5dd79102f417572696d61733a302e31362e332f0000000001
Magic:f9beb4d9
Command:76657273696f6e0000000000
Length:00000066
Checksum:0a75c839
Payload:7f1101000100000000000000820b905c00000000010000000000000000000000000000000000ffff340e5966208d010000000000000000000000000000000000ffff7f000001208db910e81a17a5dd79102f417572696d61733a302e31362e332f0000000001
Version:7f110100
Services:0100000000000000
timestamp:820b905c00000000
addr_recv:010000000000000000000000000000000000ffff340e5966208d
addr_from:010000000000000000000000000000000000ffff7f000001208d
nonce:b910e81a17a5dd79
user_agent:102f417572696d61733a302e31362e332f
start_height:00000000
relay:01
Connection end
Main class:
private static String address = "52.14.89.102";
private static int port = 8333;
public static void main(String [] args) throws IOException {
String line = "";
try {
socket = new Socket(address, port);
System.out.println("Connected");
input = new DataInputStream(socket.getInputStream());
out = new DataOutputStream(socket.getOutputStream());
VersionMessage message = new VersionMessage();
line = Hex.encodeHexString(message.getMessage());
System.out.println(line);
structure(message.getMessage());
out.writeBytes(line);;
} catch(UnknownHostException u) {
System.out.println(u);
} catch (IOException e) {
e.printStackTrace();
}
...
The part of VersionMessage class:
public VersionMessage() {
super();
this.version = 70015;
this.services = 1; // NODE_NETWORK
this.timestamp = System.currentTimeMillis() / 1000;
this.nonce = new Random().nextLong();
this.userAgent = "/Satoshi:0.16.3/";
this.startHeight = 0;
this.relay = true;
contructPayload();
contructMessage();
}
#Override
public void contructPayload() {
addByteArray(dataParser.toInt32(version));
addByteArray(dataParser.toInt64(services));
addByteArray(dataParser.toInt64(timestamp));
addAddr("52.14.89.102", 8333);
addAddr("127.0.0.1", 8333);
addByteArray(dataParser.toInt64(nonce));
addStr(userAgent);
addByteArray(dataParser.toInt32(startHeight));
addByteArray(dataParser.toInt8(relay ? (byte) 1 : (byte) 0));
payload = new byte[payloadBytes.size()];
IntStream.range(0, payloadBytes.size()).forEach(i -> payload[i] = payloadBytes.get(i).byteValue());
}
BitcoinMessage (parent of VersionMessage):
public BitcoinMessage() {
magic = 0xf9beb4d9;;
payloadBytes = new ArrayList<Integer>();
dataParser = new DataParser();
}
public void contructMessage() {
message = new byte[MAGIC_LENGTH + COMMAND_LENGTH + PAYLOAD_LENGTH_SIZE + CHECKSUM_LENGTH + payload.length];
length = payload.length;
byte[] doubleHashedPayload = MessageUtils.doubleHashWithSha256(payload);
MessageUtils.addToByteArray(MessageUtils.intToBytes(magic, MAGIC_LENGTH), 0, MAGIC_LENGTH, message);
MessageUtils.addToByteArray(getCommandName().getBytes(), MAGIC_LENGTH, COMMAND_LENGTH, message);
MessageUtils.addToByteArray(MessageUtils.intToBytes(length, PAYLOAD_LENGTH_SIZE), MAGIC_LENGTH + COMMAND_LENGTH, PAYLOAD_LENGTH_SIZE, message);
MessageUtils.addToByteArray(doubleHashedPayload, MAGIC_LENGTH + COMMAND_LENGTH + PAYLOAD_LENGTH_SIZE, CHECKSUM_LENGTH, message);
MessageUtils.addToByteArray(payload, MAGIC_LENGTH + COMMAND_LENGTH + PAYLOAD_LENGTH_SIZE + CHECKSUM_LENGTH, payload.length, message);
}

How to check if server is running a method in Java HttpServer; getting java.net.UnknownHostException

I am scheduling tasks on servers but I have no idea how to know if any server is currently doing the task. I am looping over servers like this:
for(int i = 0; i < tasksList.size(); i++){
for(URL url : serverURLsList){
if(InetAddress.getByName(url.toString()).isReachable(0)){ //this gives me exception
HttpURLConnection availableServer = (HttpURLConnection) url.openConnection();
availableServer.setDoOutput(true);
ObjectOutputStream oos = new ObjectOutputStream(availableServer.getOutputStream());
oos.writeObject(tasksList.get(i));
oos.close();
tasksList.remove(i);
break;
}
}
}
This is my server for task handling:
public class Serv{
public static void main(String[] args) throws IOException {
int port = 8080;
String host = "192.168.1.116";
System.out.println("Server 1 is up. Host: " + host + " port: " + port);
HttpServer s= HttpServer.create(new InetSocketAddress(host, port), 0);
s.createContext("/", new RootHandler());
s.setExecutor(null);
s.start();
}
}
class RootHandler implements HttpHandler{
private static int clientCounter = 1;
#Override
public void handle(HttpExchange exchange) throws IOException {
System.out.println("\nRoot handler; \n\tclient no. " + clientCounter++);
Task t;
ObjectInputStream ois = new ObjectInputStream(exchange.getRequestBody());
try {
System.out.println("Recieved object:");
t = (Task) ois.readObject();
ois.close();
System.out.println("Array not sorted:");
int[] arr = (int[]) t.getData();
for (int anArr : arr) {
System.out.print(anArr + " ");
}
TaskSolver.solve(t); // need to check if this is runned on the server or server is doing nothing
System.out.println("\nArray sorted!");
for (int anArr : (int[])t.getData()) {
System.out.print(anArr + " ");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
String response = "<h1>Server up!</h1>";
exchange.sendResponseHeaders(200, response.getBytes().length);
OutputStream os = exchange.getResponseBody();
os.write(response.getBytes());
os.close();
}
}
What I really want to achieve is have the information if any server in the list is currently solving the task (the comment in the snippet above shows that place). No idea why getting the exception mentioned in the title because I can reach the server from the web browser. I suppose the method isReachable() is not good for that purpose (because it should tell if the host given is up or not while I want to know if the proper method on the server is currently running). Does somebody know a good solution to do so?
#Edit
According to the comment I need to say that each of my servers (I will have plenty of them) should be doing only one task, that is the purpose of my simulation.
InetAddress.getByName(url.toString()).isReachable(0)){ //this gives me exception
Of course it does. The argument to InetAddress.getByName() is not a URL. Check the Javadoc. It is a hostname.

How to release a port from the state LISTEN at the server side

I am new to sockets in JAVA. Recently, I am trying to build a server-client program that clients can search a word from the dictionary in server side and the server will return the defintion of the word to the clients. The code in server side is as the following:
public class DictionaryServer {
private static int port;
private static String dicFile;
static Map<String, String> dictionary = new HashMap<String, String>();
int userCounter = 0;
public static void main(String[] args) {
//check if starting the server in valid format
if (args.length != 2) {
System.err.println("Invalid format to start DictionaryServer");
System.err.println("Usage: java DictionaryServer <port number> <the name of dictionary>");
System.exit(1);
}
port = Integer.parseInt(args[0]);
dicFile = args[1];
try{
System.out.println("IP: " + InetAddress.getLocalHost());
System.out.println("port: " + port);
}
catch(UnknownHostException e){
e.printStackTrace();
}
DictionaryServer s = new DictionaryServer();
s.server(port, dicFile);
}
public void server(int port, String dicFile) {
ServerSocketFactory serverSocket = ServerSocketFactory.getDefault();
try(ServerSocket server = serverSocket.createServerSocket(port)){
System.out.println("Server IP: " + server.getInetAddress());
System.out.println("Listening for client connections...");
while(true){
Socket client = server.accept();
System.out.println("Client \"" + client.getRemoteSocketAddress().toString()
+ "\""+ " is connecting.");
Thread t = new Thread(() -> service(client, dicFile));
t.start();
}
}
catch (UnknownHostException e) {
e.printStackTrace();
}
catch(IOException e) {
e.printStackTrace();
}
}
public void service(Socket client, String dicFile){
try(Socket clientSocket = client){
// Input and Output stream of the client
DataInputStream input = new DataInputStream(
clientSocket.getInputStream());
DataOutputStream output = new DataOutputStream(
clientSocket.getOutputStream());
//check request
int action = input.readInt(); //1:add, 2:remove, 3:query
String word = input.readUTF();
//choose action
Dic d = new Dic(dicFile);
switch(action){
case 1: //add
String definition = input.readUTF();
output.writeUTF(d.add(word, definition, dicFile));
break;
case 2: //remove
output.writeUTF(d.remove(word, dicFile));
break;
case 3: //query
output.writeUTF(d.query(word, dicFile));
break;
}
}
catch(IOException e){
String message=e.getMessage();
System.out.println(message);
System.out.println();
}
}
I am got stucked in an error when I try to restart the serverprogram: java.net.BindException: Address already in use (Bind failed)
For example, last time I execute the server program with the port 4000 and it worked, but if I want to execute the server program with the same port again, the exception will show up. I checked what the port 4000 is doing by "lsof -i:4000" in terminal which told me:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
java 19683 Andy 7u IPv6 0x43e8f876eb74b731 0t0 TCP *:terabase (LISTEN)
Does anyone know how I can fix this problem? Thank you!
You need make sure your program has really exited, and you also need to set reuseAddress. To do that you have to create the server socket without binding, set the option, and then bind it, in three different steps:
ServerSocket server = serverSocketFactory.createServerSocket();
server.setReuseAddress(true);
server.bind(new InetSocketAddress(port));

serversocket.accept() method blocks even after connection is established

server
public class Server {
class ServerHelper implements Runnable
{
InputStream is;
private InputStreamReader isr;
private BufferedReader br;
public ServerHelper(InputStream is) {
this.is = is;
isr = new InputStreamReader(is);
br = new BufferedReader(isr);
}
private void display() throws IOException {
String s = "";
System.out.print("client says : ");
while ( ( s = br.readLine() ) != null ) {
System.out.print(s + " ");
}
}
#Override
public void run() {
try {
display( );
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
}
void start( ) throws Exception{
ServerSocket ss = new ServerSocket(5555);
while (true) {
System.out.println("waiting for conn..");
Socket accept = ss.accept();//code hangs over here and doesn't proceed ahead
if( accept == null )
System.out.println("got null...");
System.out.println("got the client req...");
ServerHelper sh = new ServerHelper(accept.getInputStream());
Thread t = new Thread(sh);
t.start();
}
}
public static void main(String[] args) {
try {
// TODO code application logic here
new Server().start();
} catch (Exception ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
}
client
public class Client {
void start( ) throws Exception{
System.out.println("enter window size ");
Scanner sc = new Scanner(System.in);
int wsize = sc.nextInt();
Socket s = new Socket("127.0.0.1", 5555);
System.out.println("is connected .." + s.isConnected());
OutputStream outputStream = s.getOutputStream();
PrintWriter pw = new PrintWriter(outputStream);
String c = "y";
int j = 0;
do{
String se = "";
for (int i = 0; i < wsize; i++) {
j++;
se = se + String.valueOf(j);
}
pw.println(se);
pw.flush();
System.out.println("do u wanna send more....?(y|n)");
c = sc.next();
}while( c.equalsIgnoreCase("y") );
}
public static void main(String[] args) {
try {
// TODO code application logic here
new Client().start();
} catch (Exception ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Socket accept = ss.accept();
here my code hangs up i know it is blocking io, but at the client side i did verify that whether client is connected or not but it is showing connected...whats the matter with accept() ? I code in similar manner for all my TCP applications but this is weird ..can any one help
I have also added the ServerHelper code for those who want take a look at that class please..
If the call to accept is really blocking, then you have another program running that is listening on 5555 and is bound to "127.0.0.1". Your client is connecting to this other program, so ss.accept still blocks.
The solution is to find and kill this other process
Additional information:
Since you did not specify the bind address in your server socket, it is bound to "0.0.0.0" (all interfaces).
It is possible to have one process bind to 127.0.01 and another to bind to 0.0.0.0 (at least on Windows). I copied some data from tcpview. The second column is process id.
java.exe 5944 TCP 0.0.0.0 5555 0.0.0.0 0 LISTENING
java.exe 5944 TCPV6 [0:0:0:0:0:0:0:0] 5555 [0:0:0:0:0:0:0:0] 0 LISTENING
java.exe 5608 TCP 127.0.0.1 5555 0.0.0.0 0 LISTENING
I can connect to the process 5944 using telnet 10.101.16.28 5555 (my local IP address) or connect to process 5608 using telnet 127.0.0.1 5555
Take a look on your code:
while (true) {
System.out.println("waiting for conn..");
Socket accept = ss.accept();
.................
}
You call ss.accept() into infinite loop. Once your client is connected accept() returns the Socket instance. Then you pass this socket to server helper running in its own thread and return to ss.accept(), so your server is ready to accept other clients. Your code looks OK. Unfortunately you have not sent code of your ServerHelper and did not explain whether your client successfully sends data to server, however so far everything looks fine.
Of course it blocks. It is waiting for a connection. That's what it's supposed to do. BTW checking the result of accept() for null is pointless. It won't be null. Possibly this is your misconception: are you expecting it to return null if there is no incoming connection? It doesn't do that. See the Javadoc.

cannot get server socket to close

I'm making a simple chat server and just made it so each connection runs on a new thread.
The old version started a single thread for the server, it did a while loop, which would stop when a stop message was sent then close the socket.
The new version loops forever and create a new thread for each new connection. Now I cannot close the socket connection.
If you press a key and the main thread stops, the socket stays open. Thus when I run the program again I need to change the socket number.
code of server
while(true)
{
///////////////////////////////////////////////////
// get a new connection
///////////////////////////////////////////////////
System.out.println("Aceepting connections on port 1030 \r");
try{
// Get New Connection
// wait for ever on accepting new connections
server.setSoTimeout(0);
connection=server.accept();
cConnection thread = new cConnection("thread3", connection);
} catch(IOException ec)
{
System.out.println(ec.getMessage());
}
}
code that starts server
Now each message comes in on a new thread, so I cannot tell it to stop and close the socket.
You need to provide a flag that must be globally accesible, so when some client wants to stop the server then change the variable ans stops the bucle. By example:
class YourServer {
private static boolean execute = true;
public static synchronized void stop() {
execute = false;
}
public void yourMethod() {
while(execute) {
// implement your server here
}
}
}
When a client send the command STOP you must be do
YourServer.stop();
If you want a stop command to stop the server you can call System.exit() to force the program to store or just closing server is likely to be all you need.
Looking into your problem, I understood one thing, that since you are putting
while (true), so your control always gets stuck at connection=server.accept(); listening for a new connection. So in order to stop the sockets you need to first find a way to stop looping in that while loop. Either you can set a Variable, like (int clientsConnected) to check the number of Clients, when that comes to zero stop that while loop. So you can stop your sockets.
Below is my sample code for clients which is doing the same thing for closing the Sockets.
Hopefully this solves your problem.
class GetNamesFromServer implements Runnable
{
private Socket sForName, sForId;
private BufferedReader in, inForName, inForId;
private PrintWriter outForName, outForId;
private static String clientNames;
public GetNamesFromServer(Socket s1, Socket s2)
{
sForName = s1;
sForId = s2;
}
public void run()
{
try
{
outForName = new PrintWriter(sForName.getOutputStream(), true);
outForName.println(Client.clientName);
System.out.println("Send Name : " + Client.clientName);
outForName.flush();
}
catch(IOException e)
{
System.err.println("Error sending Name to the Server.");
}
try
{
inForId = new BufferedReader(new InputStreamReader(sForId.getInputStream()));
Client.clientId = (inForId.readLine()).trim();
System.out.println("Client ID is : " + Client.clientId);
}
catch(IOException e)
{
System.err.println("Error Receiving ID from Server.");
}
try
{
inForName = new BufferedReader(new InputStreamReader(sForName.getInputStream()));
while (true)
{
clientNames = inForName.readLine();
if (clientNames != null && clientNames != "")
{
clientNames = clientNames.substring(1, clientNames.length() - 1);
System.out.println("Names Received : " + clientNames);
String[] names = clientNames.split(", ");
Client.nameClients.clear();
for (String element: names)
Client.nameClients.add(element);
Client.nPane.setText("");
int size = Client.nameClients.size();
System.out.println("Size of list : " + size);
for (int i = 0; i < size; i++)
{
String name = Client.nameClients.get(i);
String colour = Character.toString(name.charAt(0));
name = name.substring(1, name.length()) + "\n";
appendToNamePane(name, ReceiveMessages.getColour(Integer.parseInt(colour)), "Lucida Console");
}
System.out.println("Clients Online : " + Client.nameClients);
}
int index = Client.nameClients.indexOf(Client.clientId + Client.clientName);
**if (index == -1)
{
sForName.close();
break;
}**
}
}
catch(IOException e)
{
System.err.println("Error Receiving Names of Clients from Server");
}
}
NEW EDITION :
You can add a cap to maximum number of clients that can connect, once that reaches your while loop will not go to connection = server.accept(); and hence when they are done chatting (after some time) i.e. totalClients = 0, you can stop your sockets as well, to stop the program.
if (totalClients == 0)
{
socket.close();
serverSocket.close();
}
Regards

Categories

Resources