I've very new to networking and using networks to send messages through programming. Anyways, I have a client and server java command line application (server is running in a VM on the same machine with a bridged network adapter, and host to guest pinging works and vice versa), and it would appear on the server side that each message it receives is coming from a different port. Is this normal behavior? What happens when the machine runs out of ports to use? Does Java's libraries intelligently close the ports after it's done with them?
So basically, is this even a problem? If it is, how do I go about fixing it? Output from the server and then code for the client listed below.
SERVER OUTPUT AFTER SENDING SOME MESSAGES:
Received (/192.168.1.122:59628): shsfh
Received (/192.168.1.122:59629): dfsh
Received (/192.168.1.122:59631): dfh
Received (/192.168.1.122:59632): fdshdf
Received (/192.168.1.122:59633): shf
Received (/192.168.1.122:59637): fgfggsdfhsfdh
Received (/192.168.1.122:59638): fdshf
Received (/192.168.1.122:59639): hs
Received (/192.168.1.122:59640): hfh
CODE FOR THE CLIENT THAT SENT THOSE MESSAGES:
import java.io.*;
import java.util.*;
import java.net.*;
class TCPClient
{
public static void main(String argv[]) throws Exception
{ Scanner scan = new Scanner(System.in);
while (true)
{
String msgcont = scan.nextLine();
System.out.println(tcpSend("192.168.1.153", 6789, 5000, msgcont));
}
}
public static String tcpSend(String ip, int port, int timeout, String content)
{
String ipaddress = ip;
int portnumber = port;
String sentence;
String modifiedSentence;
Socket clientSocket;
try
{
clientSocket = new Socket(ipaddress, portnumber);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
outToServer.writeBytes(content + '\n');
clientSocket.setSoTimeout(timeout);
modifiedSentence = inFromServer.readLine();
clientSocket.close();
outToServer.close();
inFromServer.close();
}
catch (Exception exc)
{
modifiedSentence = "";
}
return modifiedSentence;
}
}
Yes, everytime you open a socket to other host, the connection can be initiated from any of the remaining port on your machine. The OS chooses the next available port and makes the connection.
There are 65536 open ports available from which first 1-1024 ports are reserved by the system.
Related
I have a very basic understanding of clients, servers, sockets, input and output streams, etc. related to having servers. However, my socket that I created does not seem to work. I used many unused ip and ports, and even tried my own computer's ip. The Socket I created does not throw an IOException, or break anything. Anything past the creation of my socket object never happens.
public class ClientHello {
public static void main(String [] args) {
String ip = "91.202.240.208";
int port = 51678;
try {
System.out.println("1");
Socket sock = new Socket(ip, port);
System.out.println("2");
DataOutputStream stream1 = (DataOutputStream) sock.getOutputStream();
stream1.writeUTF("Hi server!");
DataInputStream stream2 = (DataInputStream) sock.getInputStream();
System.out.println(stream2.readUTF());
sock.close();
}catch(IOException e) {
e.printStackTrace();
}
}
}
Additionally, the ip and port is from a random Ukrainian thingy.
For the IP and port in Socket, you need to put the server socket's IP address and port so it can connect to server. Not just some random IP address.
You need to make a ServerSocket for your server first, and then with the Server's IP and port (you can specify the port when you make sever socket, and ip will be your IP)
and then you that code to connect to server.
I'm tring to implement a java - python client/server socket. The client is in java and the server is write in python
Java Client
import java.io.*;
import java.net.*;
import java.lang.*;
public class client {
public static void main(String[] args) {
try{
Socket socket=new Socket("localhost",2004);
DataOutputStream dout=new DataOutputStream(socket.getOutputStream());
DataInputStream din=new DataInputStream(socket.getInputStream());
dout.writeUTF("Hello");
dout.flush();
System.out.println("send first mess");
String str = din.readUTF();//in.readLine();
System.out.println("Message"+str);
dout.close();
din.close();
socket.close();
}
catch(Exception e){
e.printStackTrace();}
}
}
Python server
import socket
soc = socket.socket()
host = "localhost"
port = 2004
soc.bind((host, port))
soc.listen(5)
while True:
conn, addr = soc.accept()
print ("Got connection from",addr)
msg = conn.recv(1024)
print (msg)
print(len(msg))
if "Hello"in msg:
conn.send("bye".encode('UTF-8'))
else:
print("no message")
The first message from client to server was delivery correctly but the second from server to client no. Using telnet I check that sever send the message but the client goes in deadlock and don't receive message.
I don't understand why.
Thanks
It seems that your indentation is off in the Python server, as the code to send
the message back to the client is unreachable.
Even after fixing the indentation, your server implementation is not correct, as msg is not a String. You need to decode msg as seen below. Also, you need to send the length of the message as a short since you're using DataInputStream#readUTF in your client:
import socket
soc = socket.socket()
host = "localhost"
port = 2004
soc.bind((host, port))
soc.listen(5)
while True:
conn, addr = soc.accept()
print("Got connection from",addr)
length_of_message = int.from_bytes(conn.recv(2), byteorder='big')
msg = conn.recv(length_of_message).decode("UTF-8")
print(msg)
print(length_of_message)
# Note the corrected indentation below
if "Hello"in msg:
message_to_send = "bye".encode("UTF-8")
conn.send(len(message_to_send).to_bytes(2, byteorder='big'))
conn.send(message_to_send)
else:
print("no message")
I have written a simple Client-Server program in java. when i create a socket like
Socket socket = new Socket("localhost",7000);
I am able to connect to the server and transfer the data(any console input) to the Server but when i pass localhost Ip(127.0.0.1) in the Socket like
Socket socket = new Socket("127.0.0.1",7000);
I get the following error Error:
java.net.ConnectException: Connection refused: connect
Why i am getting this.
Here is my server side Code
public class SocketServer {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
new SocketServer();
// TODO code application logic here
}
public SocketServer(){
try {
ServerSocket sSocket = new ServerSocket(7000);
System.out.println("Server started at: " + new Date());
//Wait for a client to connect
Socket socket = sSocket.accept();
//Create the streams
PrintWriter output = new PrintWriter(socket.getOutputStream(), true);
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//Tell the client that he/she has connected
output.println("You have connected at: " + new Date());
//Loop that runs server functions
while(true) {
//This will wait until a line of text has been sent
String chatInput = input.readLine();
System.out.println(chatInput);
}
} catch(IOException exception) {
System.out.println("Error: " + exception);
}
}
Here is my client side Code
public class ClientSocket {
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws UnknownHostException {
// TODO code application logic here
new ClientSocket();
}
public ClientSocket() throws UnknownHostException
{
//We set up the scanner to receive user input
Scanner scanner = new Scanner(System.in);
try {
//Socket socket = new Socket("localHost",7000);//works Fine
Socket socket = new Socket("127.0.0.1",7000);//Gives error
PrintWriter output = new PrintWriter(socket.getOutputStream(), true);
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//This will wait for the server to send the string to the client saying a connection
//has been made.
String inputString = input.readLine();
System.out.println(inputString);
//Again, here is the code that will run the client, this will continue looking for
//input from the user then it will send that info to the server.
while(true) {
//Here we look for input from the user
String userInput = scanner.nextLine();
//Now we write it to the server
output.println(userInput);
}
} catch (IOException exception) {
System.out.println("Error: " + exception);
}
}
}
Here is my /etc/hosts file
# Copyright (c) 1993-2009 Microsoft Corp.
#
# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.
#
# This file contains the mappings of IP addresses to host names. Each
# entry should be kept on an individual line. The IP address should
# be placed in the first column followed by the corresponding host name.
# The IP address and the host name should be separated by at least one
# space.
#
# Additionally, comments (such as these) may be inserted on individual
# lines or following the machine name denoted by a '#' symbol.
#
# For example:
#
# 102.54.94.97 rhino.acme.com # source server
# 38.25.63.10 x.acme.com # x client host
# localhost name resolution is handled within DNS itself.
# 127.0.0.1 localhost
# ::1 localhost
127.0.0.1 localhost
127.0.0.1 localhost
When you create a Socket, you bind it to a certain address. In your case, you bound it to localhost, which is the same as 127.0.0.1 but not the same address (while localhost should always resolve to 127.0.0.1). Your application sees the connection attempt, but it also sees that it should not listen on that address so it refuses the connection.
Try binding your server socket to 127.0.0.1 or even 0.0.0.0 (with 0.0.0.0, you're telling it to listen to all incoming connections (127.0.0.1, localhost and your LAN IP address/hostname)).
Here's some more information about this.
After seeing your server and client, you could try the following on the server side:
ServerSocket serverSocket = new ServerSocket();
serverSocket.bind(new InetSocketAddress("127.0.0.1", 7000));
I faced Similar problem. Make following Changes in your Code
At Client Side
InetAddress addr = InetAddress.getByName("127.0.0.1");
Socket socket = new Socket(addr,7000);
At Server Side
ServerSocket sSocket = new ServerSocket();
sSocket.bind(new InetSocketAddress("0.0.0.0", 7000));
#Stefan has also answered right,binding to 0.0.0.0 will allow it to listen to all interfaces
You're using the wrong constructor to create the Socket in the client.
This code:
Socket socket = new Socket("127.0.0.1", 7000);
Is trying to resolve the name "127.0.0.1" as a DNS name. This constructor is internally doing this:
InetAddress.getByName(hostname);
If you want to connect to an IP address you have to use this constructor:
InetAddress address = InetAddress.getByAddress(new byte[]{127,0,0,1});
Socket socket = new Socket(address, 7000)
probably a noobish Q:
So i made a very simple single-threaded server/client model. Now when i execute the program in the eclipse IDE it shows me System.out's of the server and not the ones from the client.
When i press terminate, the System.out.println lines that were supposed to be generated by Client show up.
I'm struggling with this for days now.. Hopefully someone can help me out.
Thanks in advance!
SERVER:
import java.net.*;
import java.io.*;
public class Server {
public static void main(String[] args)
{
new Server();
}
public Server()
{
try
{
ServerSocket serverSocket = new ServerSocket(8000); //nieuw instantie van een ServerSocket
System.out.println("Waiting for clients..");
Socket socket = serverSocket.accept(); // lister for socket requests
while(true)
{
BufferedReader inputClient = new BufferedReader(new InputStreamReader(socket.getInputStream()));
DataOutputStream clientOutput = new DataOutputStream(socket.getOutputStream());
String clientInput = inputClient.readLine();
System.out.println("Server: clientInput= : " + clientInput);
InetAddress hostAddress = InetAddress.getByName(clientInput);
String iPaddress = hostAddress.getHostAddress();
System.out.println("Server: IP = : " + iPaddress);
clientOutput.writeBytes(iPaddress);
clientOutput.flush();
}
}
catch(IOException ex)
{
System.err.println(ex);
}
}
}
CLIENT:
import java.io.*;
import java.net.*;
public class Client {
public static void main(String[] args) {
new Client();
}
public Client()
{
try
{
Socket socket = new Socket("localhost", 8000);
DataOutputStream toServer = new DataOutputStream(socket.getOutputStream());
BufferedReader fromServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
toServer.writeBytes("google.com" + '\n');
String ip = fromServer.readLine();
System.out.println("Client: "+ ip);
}
catch(IOException ex)
{
System.err.println(ex);
}
}
}
When you start a client and a server program, they will have 2 separate consoles. Only one is visible at a time in the "Console" view of Eclipse. That is why you only see the server's.
You can switch between the active consoles with the "Display Selected Console" icon (it's a monitor icon) and also see the active console list.
Also you have a full-duplex connection. Both the client and the server can read/write. You use a DataOutputStream - BufferedReader representation for a one-way communication which is WRONG.
DataOutputStream writes binary data, BufferedReader reads text (character) data.
You should use one of the following pairings:
DataOutputStream - DataInputStream and use writeUTF() and readUTF() methods
OR
PrintWriter - BufferedReader and use println() and readLine() methods
clientOutput.writeBytes(iPaddress);
clientOutput.write("\n".getBytes());
clientOutput.flush();
Just add these lines (second line) in your Server class.
Reason
In your Client class you are reading a line from buffer reader but you have not send any character from server indicating end of line. So in the second line we are writing new line character indicating end of line.
When you close the server, connection get reset and available input are read. Thats why your Client prints if you close the server.
Optionally if you only want to modify your Client class you can write these lines
char [] a = new char[100];
int length = fromServer.read(a);
System.out.println("Client: "+(new String(a)).substring(0,length));
Instead of these
String ip = fromServer.readLine();
System.out.println("Client: "+ ip);
Ok so after indexing the line with an '\n' and putting the line :
Socket socket = serverSocket.accept();
inside the while loop in stead of inside try{} i got rid of all my problems.
Thanks, now i'll try to multithread this thing!
I am trying to create a p2p connection. This is a just test app that i have check but seems like it does not work over internet.
This is the java code that I am using on my pc to send a datagram to my friend:
'
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.*;
import javax.net.ssl.SSLServerSocket;
public class j2{
public static void main(String[] args) throws Exception {
InetAddress IPAddress = InetAddress.getByName("my friend's public IP");
DatagramSocket clientSocket = new DatagramSocket(3456);
System.out.println("Sending data");
String datamsg = "hello ";
byte[] sendData = datamsg.getBytes("UTF-8");
byte [] receiveData = new byte[10];
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, 7890);
int i = 500;
//incase if some packets are lost
while(i-->1)
{
clientSocket.send(sendPacket);
}
System.out.println("Data sent");
System.out.println(clientSocket.isClosed());
clientSocket.close();
}
}
'
//My friend uses this app to receive a data gram:
// port 7890 is used to send data gram and create a hole. The same is used to receice data.
'
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.*;
import javax.net.ssl.SSLServerSocket;
public class j1{
public static void main(String[] args) throws Exception {
InetAddress IPAddress = InetAddress.getByName("any ip"); //does not matter as it is used to open a hole
DatagramSocket clientSocket = new DatagramSocket(7890);
System.out.println("Sending data");
String datamsg = "hello ";
byte[] sendData = datamsg.getBytes("UTF-8");
byte [] receiveData = new byte[10];
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, 5000);
int i = 500;
while(i-->1)
{
clientSocket.send(sendPacket);
}
System.out.println("Data sent");
System.out.println(clientSocket.isClosed());
DatagramPacket receivePacket = new DatagramPacket(sendData, sendData.length);
clientSocket.receive(receivePacket);
System.out.println("Packet received");
String msg = new String(receivePacket.getData());
clientSocket.close();
}
}'
// I am not using a stun server as i already know my friends public ip address. We both have disabled our firewall as well.
Your approach is not the most reliable way to do NAT hole punching. At best it will "sometimes work".
Here's some suggestions:
Don't hardcode port numbers. Let your UDP socket code pick a random port number (i.e. port=0) and use a STUN server (or equivalent) to ascertain your public IP address and public port mapping for this local socket.
Use a reliable service to exchange the IP/port. Since you are just trying to get a single packet to go through, start with using a phone to verbally exchange this information could suffice.
You don't need to send 500 packets all at once. The firewall code on
the remote NAT might see this as a DOS attack and block everything.
Try sending like 1 a second.
You should be simultaneously listening and sending periodic packets at the same time
when trying to do the connectivity check that your code is doing.
(e.g. two seperate threads or periodic polling).
Don't close the socket until after connectivity is confirmed by both endpoints. As you have it now, your first program closes the socket immediately after it sends the packet burst.
Read my full answer here: https://stackoverflow.com/a/8524609/104458