I've wrote simple client (using SocketChannel):
User friend = database.getUserByName("jonh");
SocketChannel friendSkt = SocketChannel.open(new InetSocketAddress(InetAddress.getByName(friend.getHost()), friend.getPort()));
System.out.println("Local: " + friendSkt.socket().getLocalSocketAddress()
+ " |Remote: "+ friendSkt.socket().getRemoteSocketAddress());
and server (using simple Socket):
ServerSocket skt = new ServerSocket(0);
Socket server = skt.accept();
InputStream x = server.getInputStream();
System.out.println("Local: " + server.getLocalSocketAddress() + " |Remote: "+ server.getRemoteSocketAddress());
Even if connect returns no exception and client write on socket (simple getOutputStream.write(...)), server not read and returns -1. So I've printed the address of each socket and found this:
CLIENT: Local: /192.168.0.2:58981 |Remote: /192.168.0.2:58968
SERVER: Local: /192.168.0.2:58968 |Remote: /192.168.0.2:58980
It is normal that client local port is server remote port+1 instead to being the same value?
Related
This question already has an answer here:
java.net.ConnectException: Connection refused TCP
(1 answer)
Closed 6 years ago.
I have to establish a TCP connection to a server, which requires that I send the credential to logon in the format:
<STX>username=fred&password=123456<ETX>
Let's say host: qstage.thetcphost.com and port:8999
I am new to socket programming and using the same to implement this. I have used java.net.Socket at the client side but I dont know how do I send the above string for authentication to the TCP Server in Java.
I am able to telnet the server now.
But how do I pass the credential string in the < STX >...< ETX > format after (or during):
Socket socket = new Socket("mshxml.morningstar.com", 8999);
I mean what is the piece of code that I have to write to authenticate myself to the TCP server?
I have searched this site for this info but could not find any.
Help would be greatly appreciated.
Establish the socket connection is the first step before you can send any creds information.
If this step is failing, consider the specs from your target server. Is the correct port provided? Any consideration on protocol?
Usually, the authentication will be happen after you have already established successfully the connection.
Editted: Add source code for writing to socket from a socket client.
Now, in this context, you're a socket client, try to send creds to server.
public class GreetingClient
{
public static void main(String [] args)
{
String serverName = args[0];
int port = Integer.parseInt(args[1]);
try
{
System.out.println("Connecting to " + serverName +
" on port " + port);
Socket client = new Socket(serverName, port);
System.out.println("Just connected to "
+ client.getRemoteSocketAddress());
OutputStream outToServer = client.getOutputStream();
DataOutputStream out = new DataOutputStream(outToServer);
out.writeUTF("Hello from "
+ client.getLocalSocketAddress());
InputStream inFromServer = client.getInputStream();
DataInputStream in =
new DataInputStream(inFromServer);
System.out.println("Server says " + in.readUTF());
client.close();
}catch(IOException e)
{
e.printStackTrace();
}
}
}
Sample found here: http://www.tutorialspoint.com/java/java_networking.htm
I want to do UDP Hole Punching with two clients with the help of a server with a static IP. The server waits for the two clients on port 7070 and 7071. After that it sends the IP address and port to each other. This part is working fine. But I'm not able to establish a communication between the two clients. I tried the code in different Wifi networks and in 3G mobile network. The client program throws the IO-Exception "No route to host".
The client code is used for both clients. Once executed with port 7070 and once with 7071.
Do you think I've implemented the UDP hole punching concept correctly? Any ideas to make it work?
Here's the server code first, followed by the client code.
Thank you for help.
Code of server:
public class UDPHolePunchingServer {
public static void main(String args[]) throws Exception {
// Waiting for Connection of Client1 on Port 7070
// ////////////////////////////////////////////////
// open serverSocket on Port 7070
DatagramSocket serverSocket1 = new DatagramSocket(7070);
System.out.println("Waiting for Client 1 on Port "
+ serverSocket1.getLocalPort());
// receive Data
DatagramPacket receivePacket = new DatagramPacket(new byte[1024], 1024);
serverSocket1.receive(receivePacket);
// Get IP-Address and Port of Client1
InetAddress IPAddress1 = receivePacket.getAddress();
int port1 = receivePacket.getPort();
String msgInfoOfClient1 = IPAddress1 + "-" + port1 + "-";
System.out.println("Client1: " + msgInfoOfClient1);
// Waiting for Connection of Client2 on Port 7071
// ////////////////////////////////////////////////
// open serverSocket on Port 7071
DatagramSocket serverSocket2 = new DatagramSocket(7071);
System.out.println("Waiting for Client 2 on Port "
+ serverSocket2.getLocalPort());
// receive Data
receivePacket = new DatagramPacket(new byte[1024], 1024);
serverSocket2.receive(receivePacket);
// GetIP-Address and Port of Client1
InetAddress IPAddress2 = receivePacket.getAddress();
int port2 = receivePacket.getPort();
String msgInfoOfClient2 = IPAddress2 + "-" + port2 + "-";
System.out.println("Client2:" + msgInfoOfClient2);
// Send the Information to the other Client
// /////////////////////////////////////////////////
// Send Information of Client2 to Client1
serverSocket1.send(new DatagramPacket(msgInfoOfClient2.getBytes(),
msgInfoOfClient2.getBytes().length, IPAddress1, port1));
// Send Infos of Client1 to Client2
serverSocket2.send(new DatagramPacket(msgInfoOfClient1.getBytes(),
msgInfoOfClient1.getBytes().length, IPAddress2, port2));
//close Sockets
serverSocket1.close();
serverSocket2.close();
}
Code of client
public class UDPHolePunchingClient {
public static void main(String[] args) throws Exception {
// prepare Socket
DatagramSocket clientSocket = new DatagramSocket();
// prepare Data
byte[] sendData = "Hello".getBytes();
// send Data to Server with fix IP (X.X.X.X)
// Client1 uses port 7070, Client2 uses port 7071
DatagramPacket sendPacket = new DatagramPacket(sendData,
sendData.length, InetAddress.getByName("X.X.X.X"), 7070);
clientSocket.send(sendPacket);
// receive Data ==> Format:"<IP of other Client>-<Port of other Client>"
DatagramPacket receivePacket = new DatagramPacket(new byte[1024], 1024);
clientSocket.receive(receivePacket);
// Convert Response to IP and Port
String response = new String(receivePacket.getData());
String[] splitResponse = response.split("-");
InetAddress ip = InetAddress.getByName(splitResponse[0].substring(1));
int port = Integer.parseInt(splitResponse[1]);
// output converted Data for check
System.out.println("IP: " + ip + " PORT: " + port);
// close socket and open new socket with SAME localport
int localPort = clientSocket.getLocalPort();
clientSocket.close();
clientSocket = new DatagramSocket(localPort);
// set Timeout for receiving Data
clientSocket.setSoTimeout(1000);
// send 5000 Messages for testing
for (int i = 0; i < 5000; i++) {
// send Message to other client
sendData = ("Datapacket(" + i + ")").getBytes();
sendPacket = new DatagramPacket(sendData, sendData.length, ip, port);
clientSocket.send(sendPacket);
// receive Message from other client
try {
receivePacket.setData(new byte[1024]);
clientSocket.receive(receivePacket);
System.out.println("REC: "
+ new String(receivePacket.getData()));
} catch (Exception e) {
System.out.println("SERVER TIMED OUT");
}
}
// close connection
clientSocket.close();
}
UPDATE
The code is generally working. I've tried it in two different home networks now and it's working. But it isn't working in my 3G or university network. In 3G, I verified that the NAT is mapping the two ports (the client port and by the router assigned port) together again, even after closing and opening the clientSocket. Has anyone an idea why it isn't working then?
UDP hole punching can't be achieved with all types of NAT. There is no universal or reliable way defined for all types of NAT. It is even very difficult for symmetric NAT.
Depending on the NAT behaviour, the port mapping could be different for different devices sending the UDP packets.
Like, If A sends a UDP packet to B, it may get some port like 50000. But if A sends a UDP packet to C, then it may get a different mapping like 50002. So, in your case sending a packet to server may give a client some port but sending a packet to other client may give some other port.
You shall read more about NAT behaviour here:
https://www.rfc-editor.org/rfc/rfc4787
https://www.rfc-editor.org/rfc/rfc5128
UDP hole punching not going through on 3G
For symmetric NAT (3G network connecting to a different mobile network), you need to do Multi-UDP hole punching.
See:
https://drive.google.com/file/d/0B1IimJ20gG0SY2NvaE4wRVVMbG8/view?usp=sharing
http://tools.ietf.org/id/draft-takeda-symmetric-nat-traversal-00.txt
https://www.goto.info.waseda.ac.jp/~wei/file/wei-apan-v10.pdf
http://journals.sfu.ca/apan/index.php/apan/article/view/75/pdf_31
Either that or relay all the data through a TURN server.
You rightly use a rendezvous server to inform each node of the others IP / port based on the UDP connection. However using the public IP and port which is the combination which will is obtained by the connection as you have, means that in scenarios where both hosts exist on the same private network hairpin translation is required by the NAT which is sometimes not supported.
To remedy this you can send the IP and port your node believes itself to have in the message to the server (private ip / port) and include this in the information each node receives on the other. Then attempt a connection on both the public combination (the one you are using) and the one I just mentioned and just use the first one which is successfully established.
How can broadcast a message from single server to multiple clients and listen for a reply from one of the clients.
I used Multicast Programming to broadcast the message to the clients. And If i send the message from one of my clients back to the server either through TCP or UDP, I am getting a "java.net.ConnectException: Connection refused: connect" exception.
Please help me out.
Thanks in Advance.
Sender Code :
// Broadcasting the message
msg = "This is multicast! " + counter;
counter++;
outBuf = msg.getBytes();
// Send to multicast IP address and port
InetAddress address = InetAddress.getByName("224.2.2.3");
outPacket = new DatagramPacket(outBuf, outBuf.length, address,
PORT);
socket.send(outPacket);
System.out.println("Server sends : " + msg);
socket.close();
// Receiving TCP
apSock = new Socket("131.151.88.165", 6161);
apBuffReader = new BufferedReader(new InputStreamReader(
apSock.getInputStream()));
while ((ap2Toap1 = apBuffReader.readLine()) != null) {
System.out.println(ap2Toap1);
}
Receiver Code :
count++;
inPacket = new DatagramPacket(inBuf, inBuf.length);
socket.receive(inPacket);
String msg = new String(inBuf, 0, inPacket.getLength());
System.out.println("From " + inPacket.getAddress() + " Msg : "
+ msg);
socket.close();
// Sending TCP
apSock = new Socket("131.151.88.165", 6161);
System.out.println("Hello2");
respWriter = new PrintWriter(apSock.getOutputStream());
System.out.println("Writing back to the server");
respWriter.println(outBuf);
if (respWriter != null)
respWriter.close();
There is no listening in your code. TCP listening in Java is accomplished via a ServerSocket. You aren't using one. Instead you're using Sockets at both ends. So what you have is two clients and no server. No communication is possible between two TCP clients.
I am working on a program which needs to figure out if remote SIP UDP port 5060 is reachable from client machine.
As there is no direct method to check the availability of UDP port. I want to create a simple java class which will send the OPTIONS message to SIP UDP server and then the server will reply back to client in java.
Any help/ direction will be great help!
Thanks,
Anupam
Thanks for your response, I tried below piece of code but it did not get any reply from server:
String message = "OPTIONS sip:opensips#host;transport=udp SIP/2.0\r\nCall-ID: 7df5e96c6b1b98af25ad6c7845d48f5d#49.249.132.30\r\nCSeq: 1 OPTIONS\r\nFrom: \"Anupam\" <sip:Anupam#localhost:5080>;tag=textclientv1.0\r\nTo: \"opensips\" <sip:opensips#host>\r\nVia: SIP/2.0/UDP 49.249.132.30:5080;branch=z9hG4bK-3938-f66aaa8dda2fe3b863b4acde5fbcab67\r\nMax-Forwards: 70\r\nContact: \"Anupam\" <sip:Anupam#localhost:5080>\r\nContent-Length: 0\r\n\r\n";
System.out.println("Message is "+ message);
byte [] data = message.getBytes();
DatagramPacket packet = new DatagramPacket( data, data.length, host, port ) ;
But it didn't work.
To do this by the book (compliant with RFC 3261), you will either need to create quite a bit of machinery to handle retransmissions, etc., or to use a library like JAIN-SIP.
However, you may be able to get most of the way there by simply opening a UDP socket, sending a String containing an appropriately-formatted OPTIONS message over the socket, and then waiting a while to see if you get a SIP response on that socket. Any old SIP response (success or error) will verify that the server is reachable.
Here is an example OPTIONS message from the RFC:
OPTIONS sip:carol#chicago.com SIP/2.0
Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKhjhs8ass877
Max-Forwards: 70
To: <sip:carol#chicago.com>
From: Alice <sip:alice#atlanta.com>;tag=1928301774
Call-ID: a84b4c76e66710
CSeq: 63104 OPTIONS
Contact: <sip:alice#pc33.atlanta.com>
Accept: application/sdp
Content-Length: 0
In order to check remote side UDP sip service availability using REGISTER method you can use the following code.
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Random;
public class CheckSipUdp{
//Check remote SIP service availability
public void checkSipUdp(String ipAddress, int outPort)throws Exception{
DatagramSocket sipSocket = new DatagramSocket(0);
sipSocket.setSoTimeout(1000);
InetAddress inetIpAddress = InetAddress.getByName(ipAddress);
byte [] sendData = new byte[1024];
byte [] receiveData = new byte[1024];
//Message/Method which will be used for checking remote server availability.
String method = "REGISTER sip:" + ipAddress + ":" + outPort + " SIP/2.0\r\nCall-ID: " + generateCallId() + "#" + InetAddress.getLocalHost().getHostAddress() +"\r\nCSeq: 1 REGISTER\r\nFrom: <sip:" + InetAddress.getLocalHost().getHostAddress() + ":" + sipSocket.getLocalPort() + ">;tag=" + new Random().nextInt() + "\r\nTo: <sip:alice#" + ipAddress + ":" + outPort + ">\r\nVia: SIP/2.0/UDP " + InetAddress.getLocalHost().getHostAddress() + ":" + sipSocket.getLocalPort() + ";branch=z9hG4bK-323032-" + generateCallId() + "\r\nMax-Forwards: 70\r\nContact: <sip:" + InetAddress.getLocalHost().getHostAddress()+ ":" + sipSocket.getLocalPort() + ">\r\nContent-Length: 0\r\n\r\n";
sendData = method.getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, inetIpAddress, 5060);
sipSocket.send(sendPacket);
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
sipSocket.receive(receivePacket);
String response = new String(receivePacket.getData());
System.out.println(ipAddress + "\n" + response);
sipSocket.close();
}
//Generating unique callID
public static String generateCallId(){
Random r = new Random();
long l1 = r.nextLong() * r.nextLong();
long l2 = r.nextLong() * r.nextLong();
return Long.toHexString(l1) + Long.toHexString(l2);
}
public static void main(String [] args) throws Exception{
CheckSipUdp sip = new CheckSipUdp();
sip.checkSipUdp(args[0], Integer.parseInt(args[1]));
}
}
alI created a simple text based RPG and after alot of work managed to put it on a website (www.worldofthedrakon.com). I just created a server and client but I am having problems with users accessing the server from their computer. I have my socket set up as:
Socket socket = new Socket("localhost", 8800);
Now i have tested changing localhost out for my IP, to no avail. The errors I'm getting are connection timed out, and connection refused. Could someone point me in the right direction? I apologize if my problem seems vague, more code can be provided. Theres alot of it so I didnt want to bombard you :) Thank you.
ServerSide:
public Server() {
setLayout(new BorderLayout());
add(new JScrollPane(jta), BorderLayout.CENTER);
setTitle("Multi-Thread Server");
setSize(500, 300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
try {
ServerSocket serverSocket = new ServerSocket(8800);
jta.append("MultiThreadServer started at " + new Date() + '\n');
int clientNo = 1;
while(true) {
Socket socket = serverSocket.accept();
jta.append("Server Thread for client " + clientNo + " at " + new Date() + '\n');
InetAddress inetAdress = socket.getInetAddress();
jta.append("Client " + clientNo + "'s host name is " + inetAdress.getHostName() + "\n");
jta.append("Client " + clientNo + "'s IP Address is " + inetAdress.getHostAddress() + "\n");
HandleAClient task = new HandleAClient(socket);
new Thread(task).start();
clientNo++;
}
} catch(IOException ex) {
System.err.println(ex);
}
Client Side:
try {
Socket socket = new Socket("localhost", 8800);
fromServer = new DataInputStream(socket.getInputStream());
toServer = new DataOutputStream(socket.getOutputStream());
} catch (IOException ex) {
jta_TextArea.setText(ex.toString() + '\n');
}
Your socket is bound to localhost this means in can only serve the local client. If you want others to see your server the first step is to bind to the IP address that is visible to those others!
I think you want to be using a ServerSocket and not a regular socket.
"localhost" is exactly that; it is your local host or your machine. If you are trying to connect your socket to some other host (like whatever resolves to www.worldofthedrakon.com), you need to get that hostname or its IP address in there.
Socket socket = new Socket("worldofthedrakon.com", 8800);
Then you get to fight the firewall issues. Connection Refused is usually an indication that there is a firewall or two in the way. Do you know that port 8800 is open on your new host?