java.lang.NumberFormatException: null in Integer.parseInt - java

Okay, the following are 2 classes that I am using in creating a simple TFTP (Trivial File Transfer Protocol) program. I am running a server instance and a client instance of this program. What I am trying to accomplish is this:
The client connects to the server and sends a message of a specific file that it wants. The server locates the file and sends a response (either a 1 or 0... 1 meaning the file is there, and 0 meaning that it is not). Then the server will send the content of the file to the client application. The files I am trying to send are just simple text files.
Right now, I am able to receive the name of the text file that the client wants, but then when I go to send back the response, I am not getting anything returned. Also below are the methods that the server and the client both run.
This is the server instance
SwingUtilities.invokeLater(new Runnable(){
public void run(){
String fileRequest = UDPReceiver(SERVER_PORT_NUMBER);
outputArea.append("\n" + "File Requested: " + fileRequest + "\n");
outputArea.append("Determining if file exists...\n");
String checkFile = SHARED_DIR + "\\" + fileRequest;
outputArea.append("Checking location: " + checkFile + "\n");
boolean check = fileCheck(checkFile);
if(check == true){
outputArea.append("File location verified..." + "\n");
outputArea.append("Initiating transfer...." + "\n\n");
UDPSender(CLIENT_HOSTNAME, CLIENT_PORT_NUMBER, "1");
}
else{
outputArea.append("File does not exist..." + "\n");
outputArea.append("Exiting run..." + "\n");
}
}
});
The client instance.
SwingUtilities.invokeLater(new Runnable(){
public void run(){
UDPSender(SERVER_HOSTNAME, SERVER_PORT_NUMBER, FILE_REQUEST);
String message = UDPReceiver(CLIENT_PORT_NUMBER);
outputArea.append("\n\n" + message + "\n");
if(message == "1"){
// File exists
outputArea.append("\n");
outputArea.append("File verified..." + "\n");
outputArea.append("Transfer initiated..." + "\n");
}
else{
// File doesn't exist
outputArea.append("\n");
outputArea.append("File does not exist..." + "\n");
outputArea.append("Terminating connection...");
}
}
});
Here are the Sender and Receiver methods.
private void UDPSender(String hostname, String port, String message){
DatagramSocket socket = null;
try{
// Create a datagram socket, look for the first available port
socket = new DatagramSocket();
outputArea.append("Using local port: " + socket.getLocalPort() + "\n");
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
PrintStream pOut = new PrintStream(bOut);
pOut.print(message);
// Convert printstream to byte array
byte[] bArray = bOut.toByteArray();
// Create a DatagramPacket, containing a maximum buffer of 256 bytes
DatagramPacket packet = new DatagramPacket(bArray, bArray.length);
outputArea.append("Looking for hostname " + hostname + "\n");
// Get the InetAddress object
InetAddress remote_addr = InetAddress.getByName(hostname);
// Check its IP Number
outputArea.append("Hostname has IP Address = " + remote_addr.getHostAddress() + "\n");
// Configure the DatagramPacket
packet.setAddress(remote_addr);
packet.setPort(Integer.parseInt(port));
// Send the packet
socket.send(packet);
outputArea.append("Packet sent at: " + new Date() + "\n");
// Display packet information
outputArea.append("Sent by: " + remote_addr.getHostAddress() + "\n");
outputArea.append("Sent from: " + packet.getPort() + "\n");
socket.close();
}
catch(UnknownHostException ue){
outputArea.append("Unknown host: " + hostname + "\n");
outputArea.append("Unknown host: " + ue + "\n");
}
catch(IOException e){
outputArea.append("Error: " + e + "\n");
}
}
private String UDPReceiver(String portNum){
String message = "";
DatagramSocket socket = null;
try{
// Create a DatagramSocket
socket = new DatagramSocket(Integer.parseInt(portNum));
outputArea.append("Listening on local port " + socket.getLocalPort() + "\n");
// Create a DatagramPacket, containing a maximum buffer of 256 bytes
DatagramPacket packet = new DatagramPacket(new byte[256], 256);
// Receive a packet - remember by default this is a blocking operation
socket.receive(packet);
outputArea.append("Packet received at " + new Date() + "\n");
// Display packet information
InetAddress remote_addr = packet.getAddress();
outputArea.append("Sender: " + remote_addr.getHostAddress() + "\n");
outputArea.append("From Port: " + packet.getPort() + "\n");
CLIENT_HOSTNAME = remote_addr.getHostAddress();
//CLIENT_PORT_NUMBER = Integer.toString(packet.getPort());
// Display packet contents, by reading from byte array
ByteArrayInputStream bin = new ByteArrayInputStream(packet.getData());
// Display only up to the length of the original UDP packet
for(int i = 0; i < packet.getLength(); i++){
int data = bin.read();
if(data == -1){
break;
}
else{
message = message + (char)data;
//outputArea.append(Character.toString((char)data));
}
}
socket.close();
return message;
}
catch(IOException e){
outputArea.append("Error: " + e + "\n");
message = "Error: " + e;
return message;
}
}
Any help that you folks can offer would be greatly appreciated. The main thing I am trying to figure out is how to be able to get the server and client to be able to send messages back and forth. Thanks in advance guys.
EDIT:
I am also getting an error now in Netbeans when I run this project. I think it has something to do with this line of code in the UDPReceiver method:
socket = new DatagramSocket(Integer.parseInt(portNum));
But I can't figure out what is wrong with that.
Exception in thread "AWT-EventQueue-0" java.lang.NumberFormatException: null
at java.lang.Integer.parseInt(Integer.java:454)
at java.lang.Integer.parseInt(Integer.java:527)
at tftp_gui.main.UDPReceiver(main.java:508)
at tftp_gui.main.access$800(main.java:20)
at tftp_gui.main$10.run(main.java:374)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:251)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:721)
at java.awt.EventQueue.access$200(EventQueue.java:103)
at java.awt.EventQueue$3.run(EventQueue.java:682)
at java.awt.EventQueue$3.run(EventQueue.java:680)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:691)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:244)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:163)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:151)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:147)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:139)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:97)

you approach is wrong, as it is requires opened client port, anyway your particular problem is because you're not sending back result when file is not found:
check:
if(check == true){
outputArea.append("File location verified..." + "\n");
outputArea.append("Initiating transfer...." + "\n\n");
UDPSender(CLIENT_HOSTNAME, CLIENT_PORT_NUMBER, "1");
}
else {
outputArea.append("File does not exist..." + "\n");
outputArea.append("Exiting run..." + "\n");
UDPSender(CLIENT_HOSTNAME, CLIENT_PORT_NUMBER, "0"); // here you should send 0
}
also, you have small problem here: if(message == "1") it should look like if ("1".equals(message))
Your error is self explainable - you're haven't declared proper CLIENT_PORT_NUMBER or SERVER_PORT_NUMBER, here is what I've used for testing:
private final static String SERVER_PORT_NUMBER = "1234";
private static String CLIENT_HOSTNAME;
private static final String CLIENT_PORT_NUMBER = "2345";
private static final String FILE_REQUEST = "a.txt";
private static final String SHARED_DIR = "d:/";
private static final String SERVER_HOSTNAME = "localhost";

Related

Send emails with SMTP protocol using socket class - Java

I'm trying to develop a class that sends email using the SMTP protocol, without using any libraries that facilitate sending mail, such as MimeMessage or MailUtility.
This is what I've done so far:
public class MailSender {
protected String localMachine;
protected String localSMTPServer;
private String textMail;
private String mailFrom;
public MailSender(String localSMTPServer, String mailFrom) {
try {
this.textMail = "null";
this.localSMTPServer = localSMTPServer;
this.mailFrom = mailFrom;
InetAddress localIP = InetAddress.getLocalHost();
this.localMachine = localIP.getHostAddress();
} catch (UnknownHostException ex) {
Logger.getLogger(MailSender.class.getName()).log(Level.SEVERE, null, ex);
}
}
//getter and setter
public void smtp(String command) {
try {
System.out.println(sIn.readLine());
os.write((command + "\n").getBytes());
System.out.println("end");
} catch (IOException ex) {
System.out.println(ex);
Logger.getLogger(MailSender.class.getName()).log(Level.SEVERE, null, ex);
}
}
BufferedReader sIn;
OutputStream os;
public Boolean trySend(String destUser, String subject, String message) {
Socket socket;
try {
socket = new Socket(localSMTPServer, 587);
OutputStreamWriter sOutW = new OutputStreamWriter(socket.getOutputStream(), "ASCII");
PrintWriter sOut = new PrintWriter(sOutW, true);
InputStreamReader sInR = new InputStreamReader(socket.getInputStream(), "ASCII");
sIn = new BufferedReader(sInR);
os = socket.getOutputStream();
this.nextSMTPCode(sIn, 220);
sOut.println("EHLO");
this.nextSMTPCode(sIn, 250);
sOut.println("AUTH LOGIN");
this.nextSMTPCode(sIn, 250);
sOut.println("xxxxxxxxxxxxxxx=="); //username
sOut.println("xxxxxxxxxxxxxx="); //password
this.nextSMTPCode(sIn, 250);
sOut.println("MAIL FROM: <" + this.mailFrom + ">");
this.nextSMTPCode(sIn, 250);
sOut.println("RCPT TO: <" + destUser + ">");
this.nextSMTPCode(sIn, 250);
sOut.println("DATA");
this.nextSMTPCode(sIn, 250);
sOut.println("From: " + this.mailFrom);
sOut.println("To: " + destUser);
sOut.println("Subject: " + subject);
sOut.println(message);
sOut.println(".");
this.nextSMTPCode(sIn, 250);
sOut.println("QUIT");
this.nextSMTPCode(sIn, 250);
sIn.close();
textMail = "From " + this.mailFrom + " To " + destUser + "\n" + "Subject: " + subject + "\nMessage: " + message;
return true;
} catch (IOException ex) {
Logger.getLogger(MailSender.class.getName()).log(Level.SEVERE, null, ex);
}
return false;
}
public String getMail() {
return textMail;
}
private void nextSMTPCode(BufferedReader sIn, int expectedCode) throws IOException {
int code;
String str = sIn.readLine();
System.out.println(str);
String sCode = str.substring(0, 3);
code = Integer.parseInt(sCode);
if (code != expectedCode) {
sIn.close();
System.out.println("Code: " + code + " expected code was: " + expectedCode);
throw new IOException();
}
}
}
I am having problem with communication with the SMTP server (I am using smtp2go as the server).
The problem is that I keep getting the 250 code even when this shouldn't show up, finally the email isn't sent.
This is a sample communication:
220 mail.smtp2go.com ESMTP Exim 4.96-S2G Tue, 10 Jan 2023 14:42:02+0000
250-mail.smtp2go.com Hello [xxxxx]
250-SIZE 52428800
250-8BITMIME
250-DSN
250-PIPELINING
250-PIPECONNECT
250-AUTH CRAM-MD5 PLAIN LOGIN
250-CHUNKING
I then get 250-SIZE 52428800 and the other responses (always with the code 250) for every command I send. I tried to telnet and everything seems to work, the problem is in my code, but I can't figure out what I'm doing wrong.
Does anyone know the cause of this problem?
SMTP can have multiline responses, but you only expect singleline responses. Multiline responses are typical for EHLO. To cite from RFC 5231:
The format for multiline replies requires that every line, except the last, begin with the reply code, followed immediately by a hyphen, "-" (also known as minus), followed by text. The last line will begin with the reply code, followed immediately by <SP>, optionally some text, and <CRLF>. As noted above, servers SHOULD send the <SP> if subsequent text is not sent, but clients MUST be prepared for it to be omitted.
For example:
250-First line
250-Second line
250-234 Text beginning with numbers
250 The last line

UDP Packet content changes while transmitting

I'm programming an Server-Client Software, where the client connects to the server with an port request, the server opens a new port and sends back the new port number. Then the client communicates with an RSA shared AES key encryption and the port from the port request.
Well, it should be like that.
I had the program already running, only one client could connect to the server, and everything worked fine. But now I'm sending an "portreq" String to the server which should give a port reply. But when i check, if the incoming request is a "portreq" it gives me false. If i do same with .contains it gives me true. That's the first problem, and secondly:
When the server converts the port-Integer into an String and sends it, i can't transform it into a int again on the client-side:
java.lang.NumberFormatException: For input string: "6002������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:580)
at java.lang.Integer.parseInt(Integer.java:615)
at application.PowerPanelController.addDataToCpu(PowerPanelController.java:360)
at application.PowerPanelController.lambda$0(PowerPanelController.java:143)
at application.PowerPanelController$$Lambda$200/357277047.handle(Unknown Source)
at com.sun.scenario.animation.shared.TimelineClipCore.visitKeyFrame(TimelineClipCore.java:226)
at com.sun.scenario.animation.shared.TimelineClipCore.playTo(TimelineClipCore.java:167)
at javafx.animation.Timeline.impl_playTo(Timeline.java:176)
at javafx.animation.AnimationAccessorImpl.playTo(AnimationAccessorImpl.java:39)
at com.sun.scenario.animation.shared.InfiniteClipEnvelope.timePulse(InfiniteClipEnvelope.java:110)
at javafx.animation.Animation.impl_timePulse(Animation.java:1102)
at javafx.animation.Animation$1.lambda$timePulse$25(Animation.java:186)
at javafx.animation.Animation$1$$Lambda$186/1977464318.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at javafx.animation.Animation$1.timePulse(Animation.java:185)
at com.sun.scenario.animation.AbstractMasterTimer.timePulseImpl(AbstractMasterTimer.java:344)
at com.sun.scenario.animation.AbstractMasterTimer$MainLoop.run(AbstractMasterTimer.java:267)
at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:447)
at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:431)
at com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$363(QuantumToolkit.java:298)
at com.sun.javafx.tk.quantum.QuantumToolkit$$Lambda$42/317723766.run(Unknown Source)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
Which i don't get because the String looks pretty much the same as i send it.
Here's my client side send and receive function
private String sendCommandNoAES(String command)
{
byte[] outData = new byte[1024];
byte[] inD = new byte[1024];
String message = "";
try
{
// create Socket
DatagramSocket socket = new DatagramSocket();
// build Packet
InetAddress serverIP = InetAddress.getByName(PowerPanelMain.ip);
outData = command.getBytes();
DatagramPacket out = new DatagramPacket(outData,outData.length, serverIP, PowerPanelMain.port); // send packet
socket.send(out);
logger.info("Sent an " + command + " Request non encrypted to " + PowerPanelMain.ip + ":" + PowerPanelMain.port);
// Receive answer
byte[] inData = new byte[1024];
DatagramPacket in = new DatagramPacket(inData,inData.length);
socket.receive(in);
inD = in.getData();
message = new String(inD,0,inD.length);
// Close Socket
socket.close();
logger.info("Go answer " + message + " from " + in.getAddress().toString() + ":" + in.getPort());
}
catch(Exception ee)
{
logger.error("Error while requesting data from server \n" + getStackTrace(ee));
return "offline";
}
return message;
}
This is where i send the portreq:
String portString = sendCommandNoAES("portreq");
int port = Integer.parseInt(portString);
Thats the server code:
byte[] inData = new byte[1024];
byte[] outData = new byte[1024];
String message;
DatagramSocket socket = null;
try
{
socket = new DatagramSocket(port);
System.out.println("Bound to " + port);
//JOptionPane.showMessageDialog(null, "Bound to " + String.valueOf(port), "Yeay", JOptionPane.OK_CANCEL_OPTION);
}
catch(Exception ee)
{
JOptionPane.showMessageDialog(null, "Error occured! \n#002", "Error #002", JOptionPane.OK_CANCEL_OPTION);
}
...
DatagramPacket in = new DatagramPacket(inData,inData.length);
socket.receive(in);
InetAddress senderIP = in.getAddress();
int senderPort = in.getPort();
byte[] inc = in.getData();
message = new String(inc,0,inc.length);
System.out.println("Got " + message + " from " + senderIP + ":" + senderPort + " (byte array: " + inc.toString());
...
if(message.contains("portreq"))
{
System.out.println("Creatinfg answer");
outData = String.valueOf(portcount).getBytes();
DatagramPacket out = new DatagramPacket(outData,outData.length, senderIP, senderPort);
socket.send(out);
System.out.println("Sent " + String.valueOf(portcount));
UDPTraffic udpt = new UDPTraffic(portcount, this.mode);
udpt.start();
portcount++;
}
I'm really thankful to anyone who can solve/explain me why this is happening :D
inD = in.getData();
This merely reasserts the same value. Remove.
message = new String(inD,0,inD.length);
Wrong. You're ignoring the actual length of the received datagram. Change to:
message = new String(in.getData(), in.getOffset(), in.getLength());
You are sending a string of one size, yet on the other side you are reading the string of 1024 bytes - which you never sent. This will not do. You should either serialize string using serialize() method, or, if you want to send raw string bytes, send string length as a separate part of the message.

Help with sockets and Blackberry

i'm trying to convert a simple irc client written on java to blackberry, it uses sockets, here it is:
package seinao;
import java.io.*;
import java.net.*;
public class Client {
public static void main(String[] args) throws Exception {
// The server to connect to and our details.
String server = "127.0.0.1";
String nick = "nickname";
String login = "nickname";
// The channel which the bot will join.
String channel = "#oi";
// Connect directly to the IRC server.
Socket socket = new Socket(server, 6667);
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream( )));
BufferedReader reader = new BufferedReader(
new InputStreamReader(socket.getInputStream( )));
// Log on to the server.
writer.write("NICK " + nick + "\r\n");
writer.write("USER " + login + " 8 * : Java IRC Hacks Bot\r\n");
writer.write("Hello World!");
writer.write("PRIVMSG " + channel + "Hello!\r\n");
writer.flush( );
// Read lines from the server until it tells us we have connected.
String line = null;
while ((line = reader.readLine( )) != null) {
if (line.indexOf("004") >= 0) {
// We are now logged in.
break;
}
else if (line.indexOf("433") >= 0) {
System.out.println("Nickname is already in use.");
return;
}
}
// Join the channel.
writer.write("JOIN " + channel + "\r\n");
writer.flush( );
// Keep reading lines from the server.
while ((line = reader.readLine( )) != null) {
if (line.toLowerCase( ).startsWith("PING ")) {
// We must respond to PINGs to avoid being disconnected.
writer.write("PONG " + line.substring(5) + "\r\n");
writer.write("PRIVMSG " + channel + " :I got pinged!\r\n");
writer.flush( );
}
else if(line.toLowerCase( ).contains("funciona")){
writer.write("PRIVMSG " + channel + " Olaz!\r\n");
writer.flush();
System.out.println("mermao ta foda");
}
else {
// Print the raw line received by the client.
System.out.println(line);
}
}
}
}
but i noticed there is no java.net.* on blackberry eclipse plugin soo, what should I do ? can someone help me ? what should I use for sockets ? I'm new to java and blackberry programming but i'm learning it quite fast, thanks alot
If I remember correctly, it's SocketConnection that you use. Search through the Blackberry API for what you'll need, it'll be way more helpful.

sending a SOAP message via HTTP in java

I have the following code:
String xmldata = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>" +
"<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://www.w3.org/2003/05/soap-envelope\" " +
"xmlns:wsdl=\"http://schemas.xmlsoap.org/wsdl/\" " +
"xmlns:ns1=\"http://org.apache.axis2/xsd\" " +
"xmlns:ns=\"http://tfc\" " +
"xmlns:wsaw=\"http://www.w3.org/2006/05/addressing/wsdl\" " +
"xmlns:http=\"http://schemas.xmlsoap.org/wsdl/http/\" " +
"xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"" +
"xmlns:mime=\"http://schemas.xmlsoap.org/wsdl/mime/\" " +
"xmlns:soap=\"http://schemas.xmlsoap.org/wsdl/soap/\" " +
"xmlns:soap12=\"http://schemas.xmlsoap.org/wsdl/soap12/\" " +
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" > " +
"<SOAP-ENV:Body>" +
"<ns:CalFare xmlns:ns=\"http://tfc\">" +
"<ns:nonairport>1</ns:nonairport>" +
"<ns:distance>20</ns:distance>" +
"</ns:CalFare>" +
"</SOAP-ENV:Body>" +
"</SOAP-ENV:Envelope>";
//Create socket
String hostname = "128.196.239.112";
int port = 8080;
InetAddress addr = InetAddress.getByName(hostname);
Socket sock = new Socket(addr, port);
//Send header
String path = "/LocatorzTaxiFare/services/Calculator.CalculatorHttpSoap11Endpoint/";
BufferedWriter wr = new BufferedWriter(new OutputStreamWriter(sock.getOutputStream(),"UTF-8"));
// You can use "UTF8" for compatibility with the Microsoft virtual machine.
wr.write("POST " + path + " HTTP/1.0\r\n");
wr.write("Host: 128.196.239.112\r\n");
wr.write("Content-Length: " + xmldata.length() + "\r\n");
wr.write("Content-Type: text/xml; charset=\"utf-8\"\r\n");
wr.write("\r\n");
//Send data
wr.write(xmldata);
wr.flush();
// Response
BufferedReader rd = new BufferedReader(new InputStreamReader(sock.getInputStream()));
String line;
while((line = rd.readLine()) != null)
System.out.println(line);
} catch (Exception e) {
e.printStackTrace();
}
Now it's giving me an internal server error with the following response:
<?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Header xmlns:wsa="http://www.w3.org/2005/08/addressing"><wsa:Action>http://www.w3.org/2005/08/addressing/soap/fault</wsa:Action></soapenv:Header><soapenv:Body><soapenv:Fault><faultcode></faultcode><faultstring>com.ctc.wstx.exc.WstxUnexpectedCharException: Unexpected character 'x' (code 120) excepted space, or '>' or "/>"
at [row,col {unknown-source}]: [1,390]</faultstring><detail /></soapenv:Fault></soapenv:Body></soapenv:Envelope>
Here's a link to the WSDL
At a glance, it looks like the XML that you're sending it is invalid. The XML processor found an 'x' when it was looking for a space, a '>' or a '/>'. So, fix your payload.
Yup...here it is:
"xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"" +
"xmlns:mime=\"http://schemas.xmlsoap.org/wsdl/mime/\" " +
That first line is wrong, you need to add the trailing space (like in the second line).
Mind, it helps to read the error messages. This is exactly what it said was wrong. No real magic here.

UDP Broadcast in Java

Morning.
I'm pretty new in Java and socket connections but I'm trying to send out a UDP packet/broadcast on 255.255.255.255 on port 8001 to a device. I can get the data to send just fine, however when it comes time to receive the data the connection times out. I have a packet sniffer and I can see the packet send and then the device respond.
I'm pretty sure it is a rookie mistake that I'm missing in my code but I've been stuck on it for awhile and any help would be appreciated.
m_Socket = new DatagramSocket(m_SERVERPORT);
InetAddress address = InetAddress.getByName(m_SERVERIP);
m_DataPack = new DatagramPacket(m_SERVERCMD.getBytes(), m_SERVERCMD.getBytes().length,
address, m_SERVERPORT);
m_Socket.setBroadcast(true);
m_Socket.connect(address, m_SERVERPORT);
m_Socket.send(m_DataPack);
m_DataPack = new DatagramPacket(data, data.length,
address, m_SERVERPORT);
m_Socket.receive(m_DataPack); // This is where it times out
data = m_DataPack.getData();
String received = data.toString();
System.out.println("Received: " + received);
m_Socket.close();
Thanks and Gig'Em.
EDIT:
I'm not sure if this helps but when I watch the m_Socket object I can see the following right before it sends:
bound = true;
close = false;
connectedAddress = Inet4Address (id = 32) (-1,-1,-1,-1);
connectedPort = 8001;
connectState = 1;
created = true;
impl = PlainDatagramSocketImpl;
oldImpl = false;
and the m_DataPack object is the following:
address = Inet4Address (id = 32) (-1,-1,-1,-1);
bufLength = 6 (size of packet I'm sending is 6 char long);
offset = 0;
port = 8001;
This doesn't make sense. You are broadcasting, which is 1-to-many, and you are also connecting, which is 1-to-1. Which is it?
Lose the connect. And lose the 255.255.255.255. This has been heavily deprecated for about 20 years. Use a subnet-local broadcast address, e.g. 192.168.1.255.
You can also take a look at MulticastSocket described at Broadcasting to Multiple Recipients. Hope this helps.
If you want to receive a datagram you need to bind() to the local endpoint (address + port).
You are sending and receiving the packet on same device. You could separate send and receive ports (e.g send on 8001, receive on 8002). And run send and receive codes as separate threads. If both device must find each other (or one device find itself).
import java.io.IOException;
import java.net.*;
Receiving:
private DatagramSocket getReceiveSocket() throws UnknownHostException, SocketException {
if (receiveSocket == null) {
receiveSocket = new DatagramSocket(8002, InetAddress.getByName("0.0.0.0")); // 0.0.0.0 for listen to all ips
receiveSocket.setBroadcast(true);
}
return receiveSocket;
}
public void receive() throws IOException {
// Discovery request command
byte[] buffer = "__DISCOVERY_REQUEST__".getBytes();
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
getReceiveSocket().receive(packet);
System.out.println("Discovery package received! -> " + packet.getAddress() + ":" + packet.getPort());
// Get received data
String data = new String(packet.getData()).trim();
if (data.equals("__DISCOVERY_REQUEST__")) { // validate command
// Send response
byte[] response = new byte["__DISCOVERY_RESPONSE".length()];
DatagramPacket responsePacket = new DatagramPacket(response, response.length, packet.getAddress(), packet.getPort());
getReceiveSocket().send(responsePacket);
System.out.println("Response sent to: " + packet.getAddress() + ":" + packet.getPort());
} else {
System.err.println("Error, not valid package!" + packet.getAddress() + ":" + packet.getPort());
}
}
Sending:
private DatagramSocket getSendSocket() throws UnknownHostException, SocketException {
if (sendSocket == null) {
sendSocket = new DatagramSocket(8001, InetAddress.getLocalHost());
sendSocket.setBroadcast(true);
}
return sendSocket;
}
public void send() throws IOException {
// Discovery request command
byte[] data = "__DISCOVERY_REQUEST__".getBytes();
DatagramPacket packet = new DatagramPacket(data, data.length, InetAddress.getByName("255.255.255.255"), 8002);
getSendSocket().send(packet);
System.out.println("Discovery package sent!" + packet.getAddress() + ":" + packet.getPort());
// Discovery response command
byte[] response = new byte["__DISCOVERY_RESPONSE__".length()];
DatagramPacket responsePacket = new DatagramPacket(response, response.length);
getSendSocket().receive(responsePacket);
System.out.println("Discovery response received!" + responsePacket.getAddress() + ":" + responsePacket.getPort());
String responseData = new String(responsePacket.getData()).trim();
if (responseData.equals("__DISCOVERY_RESPONSE__")) { // Check valid command
System.out.println("Found buddy!" + responsePacket.getAddress() + ":" + responsePacket.getPort());
}
}
Of course should put this code in a loop in a thread.
Based on this example: https://demey.io/network-discovery-using-udp-broadcast/
UPDATE
The link above is dead. But same method described here also: https://www.baeldung.com/java-broadcast-multicast

Categories