I am using C# to create a client socket that should connect with a Java socket server. But no matter what I try the code always manages to send some sort of message, but for the Java server it's completely empty.
This is the C# client code:
using Godot;
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
public class Scanning: Control
{
// Called when the node enters the scene tree for the first time.
public override void _Ready()
{
string toSend = "Handshake:Interface";
IPEndPoint serverAddress = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 429);
Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
clientSocket.Connect(serverAddress);
// Sending
int toSendLen = System.Text.Encoding.ASCII.GetByteCount(toSend);
byte[] toSendBytes = System.Text.Encoding.ASCII.GetBytes(toSend);
byte[] toSendLenBytes = System.BitConverter.GetBytes(toSendLen);
clientSocket.Send(toSendLenBytes);
clientSocket.Send(toSendBytes);
Console.WriteLine("Client received: " + rcv);*/
clientSocket.Close();
}
}
Java code that is responsible for working with the client:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.ArrayList;
public class ClientHandler {
public PrintWriter out;
public BufferedReader in;
public Socket clientSocket;
public Thread thread;
public ClientHandler(Socket client) {
clientSocket = client;
System.out.println("Processing connection from " + clientSocket.getInetAddress());
thread = new Thread(new Runnable() {
#Override
public void run() {
try {
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream(), "UTF-8"));
ArrayList<String> cmdBuffer = new ArrayList<String>();
while (!Main.test.get()) {
String msg = in.readLine();
if(msg.startsWith("Handshake")) {
System.out.println("LOG: " + msg);
String[] work = msg.split(":");
if (!MessageChannel.clients.contains(work[1])) {
respond("1/I/Handshake successful for/" + work[1]);
respond("Connected: " + MessageChannel.clients);
MessageChannel.buffer.put(work[1], cmdBuffer);
MessageChannel.clients.add(work[1]);
}
} else if (msg.startsWith("Disconnect")) {
System.out.println("LOG: " + msg);
String[] work = msg.split(":");
MessageChannel.clients.remove(work[1]);
MessageChannel.buffer.remove(work[1]);
out.println("I/Disconnected/" + work[1]);
} else if(msg.startsWith("List")) {
System.out.println("LOG: " + msg);
respond("0/Connected: " + MessageChannel.clients);
} else {
String[] work = msg.split(":");
if (MessageChannel.clients.contains(work[0])){
if (work[1].equals("Lookup")) {
out.println(MessageChannel.buffer.get(work[0]).size() +"/Lookup:");
for (String e : MessageChannel.buffer.get(work[0])) {
out.println(e);
}
MessageChannel.buffer.replace(work[0], new ArrayList<String>());
} else {
System.out.println("LOG: " + msg);
MessageChannel.buffer.get(work[1]).add(work[2]);
respond("0/I/Success");
}
}
}
}
} catch (IOException e1) {
e1.printStackTrace();
}
}
});
thread.start();
}
public void respond(String msg) {
out.println(msg);
System.out.println("LOGR: " + msg);
}
}
How can I fix that? Thanks in advance!
Related
So I have a client written in Java that i want to use to test out sending email but instead of using an already existing SMTP like google, i want to have my own local server to test out sending mock emails between two mock emails.
I've been trying to look all over the internet for good sources on how to code a simple SMTP Server but i've had zero luck.
I do have a basic server code that when i run it, i can connect my Client to it but at the moment it won't handle any email functionality.
TCPServer.java
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.io.*;
import java.net.*;
public class TCPServer{
private ServerSocket server;
/**
* The TCPServer constructor initiate the socket
* #param ipAddress
* #param port
* #throws Exception
*/
public TCPServer(String ipAddress, int port) throws Exception {
if (ipAddress != null && !ipAddress.isEmpty())
this.server = new ServerSocket(port, 1, InetAddress.getByName(ipAddress));
else
this.server = new ServerSocket(0, 1, InetAddress.getLocalHost());
}
/**
* The listen method listen to incoming client's datagrams and requests
* #throws Exception
*/
private void listen() throws Exception {
// listen to incoming client's requests via the ServerSocket
//add your code here
String data = null;
Socket client = this.server.accept();
String clientAddress = client.getInetAddress().getHostAddress();
System.out.println("\r\nNew client connection from " + clientAddress);
// print received datagrams from client
//add your code here
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
while ( (data = in.readLine()) != null ) {
System.out.println("\r\nMessage from " + clientAddress + ": " + data);
client.sendUrgentData(1);
}
}
public InetAddress getSocketAddress() {
return this.server.getInetAddress();
}
public int getPort() {
return this.server.getLocalPort();
}
public static void main(String[] args) throws Exception {
// set the server address (IP) and port number
//add your code here
String serverIP = "192.168.1.235"; // local IP address
int port = 8088;
if (args.length > 0) {
serverIP = args[0];
port = Integer.parseInt(args[1]);
}
// call the constructor and pass the IP and port
//add your code here
TCPServer server = new TCPServer(serverIP, port);
System.out.println("\r\nRunning Server: " +
"Host=" + server.getSocketAddress().getHostAddress() +
" Port=" + server.getPort());
server.listen();
}
}
What can i add to my existing server code to make it handle email for my Client. I'll also post my email client as well.
ClientTester.java
import java.io.*;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Scanner;
/**
* This program demonstrates a TCP client
* #author jl922223
* #version 1.0
* #since 2020-12-12
*/
public class ClientTester{
private Socket tcpSocket;
private InetAddress serverAddress;
private int serverPort;
private Scanner scanner;
/**
* #param serverAddress
* #param serverPort
* #throws Exception
*/
private ClientTester(InetAddress serverAddress, int serverPort) throws Exception {
this.serverAddress = serverAddress;
this.serverPort = serverPort;
//Initiate the connection with the server using Socket.
//For this, creates a stream socket and connects it to the specified port number at the specified IP address.
//add your code here
this.tcpSocket = new Socket(this.serverAddress, this.serverPort);
this.scanner = new Scanner(System.in);
}
/**
* The start method connect to the server and datagrams
* #throws IOException
*/
/* private void start() throws IOException {
String input;
//create a new PrintWriter from an existing OutputStream (i.e., tcpSocket).
//This convenience constructor creates the necessary intermediateOutputStreamWriter, which will convert characters into bytes using the default character encoding
//You may add your code in a loop so that client can keep send datagrams to server
//add your code here
while (true) {
System.out.print ("C:");
input = scanner.nextLine();
PrintWriter output = new PrintWriter(this.tcpSocket.getOutputStream(), true);
output.println(input);
output.flush();
}
}*/
public static void main(String[] args) throws Exception {
// set the server address (IP) and port number
//add your code here
//IP: 192.168.1.235
//Port: 8088
InetAddress serverIP = InetAddress.getByName("smtp.google.com"); // local IP address
int port = 25;
if (args.length > 0) {
serverIP = InetAddress.getByName(args[0]);
port = Integer.parseInt(args[1]);
}
// call the constructor and pass the IP and port
//add your code here
ClientTester client = new ClientTester(serverIP, port);
// client.start();
try{
client = new ClientTester(serverIP, port);
System.out.println("\r\n Connected to Server: " + client.tcpSocket.getInetAddress());
BufferedReader stdin;
stdin = new BufferedReader (new InputStreamReader (System.in));
InputStream is = client.tcpSocket.getInputStream ();
BufferedReader sockin;
sockin = new BufferedReader (new InputStreamReader (is));
OutputStream os = client.tcpSocket.getOutputStream();
PrintWriter sockout;
sockout = new PrintWriter (os, true);
System.out.println ("S:" + sockin.readLine ());
while (true){
System.out.print ("C:");
String cmd = stdin.readLine ();
sockout.println (cmd);
String reply = sockin.readLine ();
System.out.println ("S:" + reply);
if (cmd.toLowerCase ().startsWith ("data") &&
reply.substring (0, 3).equals ("354"))
{
do
{
cmd = stdin.readLine ();
if (cmd != null && cmd.length () > 1 &&
cmd.charAt (0) == '.')
cmd = "."; // Must be no chars after . char.
sockout.println (cmd);
if (cmd.equals ("."))
break;
}
while (true);
// Read a reply string from the SMTP server program.
reply = sockin.readLine ();
// Display the first line of this reply string.
System.out.println ("S:" + reply);
continue;
}
// If the QUIT command was entered, quit.
if (cmd.toLowerCase ().startsWith ("quit"))
break;
}
}
catch (IOException e)
{
System.out.println (e.toString ());
}
finally
{
try
{
// Attempt to close the client socket.
if (client != null)
client.tcpSocket.close();
}
catch (IOException e)
{
}
}
}
}
The good news is that the ClientTester works when i connect it to smtp.google.com but i don't want to use Googles, i want to have my own basic Email server in java.
Okay, found this early-development standalone version.
Use this INSTEAD of your code; does everything your code does an more.
Single-threaded ServerSocket handling, so only one connection at a time.
package jc.lib.io.net.email.smtp.test1;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.Date;
import jc.lib.io.net.email.JcEMailBasics;
public class Test_SMTP_Server {
static public boolean DEBUG = true;
public static void main(final String s[]) throws UnknownHostException, IOException {
final Test_SMTP_Server server = new Test_SMTP_Server(JcEMailBasics.SMTP_PORTS);
server.start();
try {
Thread.sleep(1 * 60 * 60 * 1000);
} catch (final InterruptedException e) { /* */ }
}
/*
* OBJECT
*/
private final ServerSocket[] mSockets;
private volatile boolean mStopRequested;
private static boolean mReceivingData;
public Test_SMTP_Server(final int[] pPorts) throws IOException {
mSockets = new ServerSocket[pPorts.length];
for (int i = 0; i < pPorts.length; i++) {
final int port = pPorts[i];
try {
mSockets[i] = new ServerSocket(port);
} catch (final java.net.BindException e) {
new java.net.BindException("When mountin port " + port + ": " + e.getMessage()).printStackTrace();
}
System.out.println("Created server socket on port " + port);
}
}
public void start() {
mStopRequested = false;
for (final ServerSocket ss : mSockets) {
if (ss == null) continue;
final Thread t = new Thread(() -> handleServerSocket(ss), "handleServerSocket(" + ss.getLocalPort() + ")");
t.setDaemon(true);
t.start();
}
}
private void handleServerSocket(final ServerSocket pSS) {
final String name = "handleServerSocket(" + pSS.getLocalPort() + ")";
while (!mStopRequested) {
System.out.println(name + "\tListening for connection...");
try (final Socket socket = pSS.accept();
final BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream(), JcEMailBasics.DEFAULT_CHARSET_SMTP_POP3));
final BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), JcEMailBasics.DEFAULT_CHARSET_SMTP_POP3));) {
System.out.println(name + "\tGot new Socket.");
handle(socket, in, out);
System.out.println(name + "\tClosing Socket.");
} catch (final IOException e) {
System.err.println("In " + name + ":");
e.printStackTrace();
}
System.out.println(name + "\tComm Done.");
}
}
public void stop() {
mStopRequested = true;
for (final ServerSocket ss : mSockets) {
try {
ss.close();
} catch (final Exception e) { /* */ }
}
}
static private void handle(final Socket pSocket, final BufferedReader pBR, final BufferedWriter pBW) throws IOException {
// send("+OK POP3 server ready <" + Test_EMails.SERVICE_ADDRESS + ">", out);
send("220 cbsoft.dev SMTP " + JcEMailBasics.NAME, pBW);
final StringBuilder sb = new StringBuilder();
mainLoop: while (!pSocket.isClosed()) {
final String read = read(pBR);
if (read == null) break;
switch (read) {
case JcEMailBasics.COMMAND_DATA: {
send("354 End data with <CR><LF>.<CR><LF>", pBW);
mReceivingData = true;
break;
}
case JcEMailBasics.COMMAND_END_OF_DATA: {
send("250 OK", pBW);
mReceivingData = false;
break;
}
case JcEMailBasics.COMMAND_QUIT: {
send("221 " + JcEMailBasics.NAME + " signing off", pBW);
break mainLoop;
}
default: {
final String correctedRead = read.startsWith(".") ? read.substring(1) : read;
sb.append(correctedRead + "\n");
if (!mReceivingData) send("250 Ok", pBW);
}
}
}
final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
final File file = new File("mails/inc_" + sdf.format(new Date()) + ".email.txt");
file.getParentFile().mkdirs();
final String msg = sb.toString();
try (FileOutputStream fos = new FileOutputStream(file)) {
fos.write(msg.getBytes());
}
System.out.println("File saved as " + file.getCanonicalPath());
}
static private void send(final String pMessage, final BufferedWriter pBW) {
try {
pBW.write(pMessage + "\n");
pBW.flush();
if (DEBUG) System.out.println("SENT:\t" + pMessage);
} catch (final Exception e) {
e.printStackTrace();
}
}
static private String read(final BufferedReader pBR) throws IOException {
try {
final String reply = pBR.readLine();
if (DEBUG) System.out.println("RECV:\t" + reply);
return reply;
} catch (final SocketTimeoutException e) {
System.err.println("SERVER TIMEOUT");
}
return null;
}
}
the only additional file you will need (also included in my previous answer; edited a bit):
package jc.lib.io.net.email;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
public class JcEMailBasics {
static public final int SMTP_PORT_1 = 25;
static public final int SMTP_PORT_2 = 587;
static public final int SMTP_PORT_3 = 465;
static public final int[] SMTP_PORTS = { SMTP_PORT_1, SMTP_PORT_2, SMTP_PORT_3 };
static public final int POP_PORT_1 = 110;
static public final int POP_PORT_SSL = 995;
static public final int POP_PORT_KERBEROS = 1109;
static public final int[] POP_PORTS = { POP_PORT_1, POP_PORT_SSL, POP_PORT_KERBEROS };
// netstat -aon | findstr '587'
static public final String DEFAULT_CHARSET_SMTP_POP3 = "8859_1";
static public final String NAME = "JC Oblivionat0r POP3 Server";
static public final String SERVICE_ADDRESS = "oblivionat0r#cbsoft.dev";
static public final String CONNECTION_CLOSED = "CONNECTION_CLOSED_dtnt495n3479r5zb3tr47c3b49c3";
static public final String COMMAND_QUIT = "QUIT";
static public final String COMMAND_DATA = "DATA";
static public final String COMMAND_END_OF_DATA = ".";
static public void send(final BufferedWriter pBufferedWriter, final String pMessage) throws IOException {
pBufferedWriter.write(pMessage + "\n");
pBufferedWriter.flush();
System.out.println("SENT:\t" + pMessage);
}
static public String sendExpect(final BufferedWriter pBufferedWriter, final String pMessage, final BufferedReader pBufferedReader, final String... pExpectedResponsePrefixes) throws IOException {
send(pBufferedWriter, pMessage);
final String read = read(pBufferedReader);
for (final String erp : pExpectedResponsePrefixes) {
if (read.startsWith(erp)) return read;
}
throw new IllegalStateException("Bad response: Expected [" + toString(", ", pExpectedResponsePrefixes) + "] got [" + read + "] instead!");
}
static public String read(final BufferedReader pBufferedReader) throws IOException {
final String reply = pBufferedReader.readLine();
System.out.println("RECV:\t" + reply);
return reply;
}
#SafeVarargs public static <T> String toString(final String pSeparator, final T... pObjects) {
if (pObjects == null) return null;
final StringBuilder ret = new StringBuilder();
for (final T o : pObjects) {
ret.append(o + pSeparator);
}
if (ret.length() > 0) ret.setLength(ret.length() - pSeparator.length());
return ret.toString();
}
}
Basically like my code.
It is just a proof of concept, and quite unsafe and inefficient
I'm using lombok. The read() method is basically a BufferedReader.readLine() call on the socket's InputStream.
send() is a writeLine
My entry point handleSocket() is when the Socket connection is established.
The String.toNLine() method is a Lombok extension, you can replace it with string.replace("\r\n" , "\n");
Be aware that this is simply a stupid implementation that can be fooled easily, but it enables basic email receiving. You get ALL the communication in the StringBuilder. You could take that final whole text apart with MIME classes (Header / newline / newline body method that is used by HTTP, SMTP etc).
This approach collects the whole comunication first, then later (outside given code) handles the actual MIME part. You could also implement it differently, as in the code knows the current state of transmission and details of the MIME object it's currently receiving, and updates its status/workflow with each line. That would be much more efficient, but the code would be a bit more complex.
package jc.lib.io.net.email.smtp.server.receiver;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
import jc.lib.aop.lombok.java.lang.JcAString;
import jc.lib.collection.tuples.JcTriple;
import jc.lib.io.net.email.JcEMailBasics;
import jc.lib.io.net.email.util.JcAServerSocketHandlerBase;
import jc.lib.lang.thread.event.JcEvent;
import lombok.experimental.ExtensionMethod;
#ExtensionMethod({ JcAString.class })
public class JcSmtpReceiverSocketHandler extends JcAServerSocketHandlerBase {
public final JcEvent<JcTriple<JcSmtpReceiver, JcSmtpReceiverSocketHandler, File>> EVENT_EMAIL_RECEIVED = new JcEvent<>();
private final JcSmtpReceiver mJcAServerBase;
private boolean mReceivingData;
public JcSmtpReceiverSocketHandler(final JcSmtpReceiver pJcAServerBase, final ServerSocket pServerSocket, final Socket pSocket) throws IOException {
super(pServerSocket, pSocket);
mJcAServerBase = pJcAServerBase;
}
#Override protected void handleSocket() throws IOException {
send("220 cbsoft.dev SMTP " + JcEMailBasics.NAME);
final StringBuilder sb = new StringBuilder();
mainLoop: while (!mSocket.isClosed()) {
final String read = read();
if (read == null) break;
switch (read) {
case JcEMailBasics.COMMAND_DATA: {
send("354 End data with <CR><LF>.<CR><LF>");
mReceivingData = true;
break;
}
case JcEMailBasics.COMMAND_END_OF_DATA: {
send("250 OK");
mReceivingData = false;
break;
}
case JcEMailBasics.COMMAND_QUIT: {
send("221 " + JcEMailBasics.NAME + " signing off");
break mainLoop;
}
default: {
final String correctedRead = read.startsWith(".") ? read.substring(1) : read;
sb.append(correctedRead + "\n");
if (!mReceivingData) send("250 Ok");
}
}
}
final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
final File file = new File("mails/inc_" + sdf.format(new Date()) + ".email.txt");
file.getParentFile().mkdirs();
String msg = sb.toString();
msg = msg.toNLineBreak();
final String header = msg.subStringBefore("\n\n");
System.out.println("header:");
try (FileOutputStream fos = new FileOutputStream(file)) {
fos.write(msg.getBytes());
}
System.out.println("File saved as " + file.getCanonicalPath());
EVENT_EMAIL_RECEIVED.trigger(new JcTriple<>(mJcAServerBase, this, file));
}
}
Check out this file for some ports and other info.
package jc.lib.io.net.email;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import jc.lib.io.net.email.util.JcAServerBase;
import jc.lib.lang.JcUArray;
public class JcEMailBasics {
static public final int SMTP_PORT_1 = 25;
static public final int SMTP_PORT_2 = 587;
static public final int SMTP_PORT_3 = 465;
static public final int[] SMTP_PORTS = { SMTP_PORT_1, SMTP_PORT_2, SMTP_PORT_3 };
static public final int POP_PORT_1 = 110;
static public final int POP_PORT_SSL = 995;
static public final int POP_PORT_KERBEROS = 1109;
static public final int[] POP_PORTS = { POP_PORT_1, POP_PORT_SSL, POP_PORT_KERBEROS };
// netstat -aon | findstr '587'
static public final String DEFAULT_CHARSET_SMTP_POP3 = "8859_1";
static public final String NAME = "JC Oblivionat0r POP3 Server";
static public final String SERVICE_ADDRESS = "oblivionat0r#cbsoft.dev";
static public final String CONNECTION_CLOSED = "CONNECTION_CLOSED_dtnt495n3479r5zb3tr47c3b49c3";
static public final String COMMAND_QUIT = "QUIT";
static public final String COMMAND_DATA = "DATA";
static public final String COMMAND_END_OF_DATA = ".";
static public void send(final BufferedWriter pBufferedWriter, final String pMessage) throws IOException {
pBufferedWriter.write(pMessage + "\n");
pBufferedWriter.flush();
if (JcAServerBase.DEBUG) System.out.println("SENT:\t" + pMessage);
}
static public String sendExpect(final BufferedWriter pBufferedWriter, final String pMessage, final BufferedReader pBufferedReader, final String... pExpectedResponsePrefixes) throws IOException {
send(pBufferedWriter, pMessage);
final String read = read(pBufferedReader);
for (final String erp : pExpectedResponsePrefixes) {
if (read.startsWith(erp)) return read;
}
throw new IllegalStateException("Bad response: Expected [" + JcUArray.toString(", ", pExpectedResponsePrefixes) + "] got [" + read + "] instead!");
}
static public String read(final BufferedReader pBufferedReader) throws IOException {
final String reply = pBufferedReader.readLine();
if (JcAServerBase.DEBUG) System.out.println("RECV:\t" + reply);
return reply;
}
}
You need to communicate with the client.
First let the server send something like "220 Smtp server" (only 220 matters) to the client.
I used PrintWriter:
PrintWriter out = new PrintWriter(client.getOutputStream(), true);
out.println("220 Smtp server");
Then you will receive an EHLO from the client while getting lines from the inputStream.
Here you can find an example of the communication between server an client (without the starting message from the server (220)):
https://postmarkapp.com/guides/everything-you-need-to-know-about-smtp#basic-smtp-commands
Code below works and sends message at scheduled time but I think it isn't a good solution to open new socket every time timer executes scheduled task. What I would like is to open socket in run method only once and access it in SendMessage class whenever new instance of class is made in timer. That way it doesn't work, it only sends one message and then stops sending. Also I would be happy for some critics about code or tips for making it thread safe.
public class Client implements Runnable{
// Client Constructor here
#Override
public void run(){
//SENDS ONLY ONE MESSAGE
pitcherSocket = new Socket(InetAddress.getByName(hostname), port);
Timer timer = new Timer();
timer.schedule(new SendMessage(), 0, 1000/mps);
}
private class SendMessage extends TimerTask{
private int id;
#Override
public void run() {
try
{ // THIS WORKS FINE, SENDS MESSAGES AT SCHEDULED TIME
pitcherSocket = new Socket(InetAddress.getByName(hostname), port);
OutputStream outToServer = pitcherSocket.getOutputStream();
DataOutputStream out = new DataOutputStream(outToServer);
out.writeInt(id);
out.flush();
}catch(IOException e)
{
e.printStackTrace();
}
}
}
}
EDIT: WHOLE CODE
CLIENT
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
public class Pitcher implements Runnable{
private int port;
private int mps;
private int size;
private String hostname;
private List<Integer> messageIds = Collections.synchronizedList(new ArrayList<Integer>());
private Socket pitcherSocket;
//constatns, integer is 4 bytes, long is 8 bytes
private static final int INT_SIZE = 4;
private static final int LONG_SIZE = 8;
public Pitcher(int port, int mps, int size, String hostname) {
this.port = port;
this.mps = mps;
this.size = size;
this.hostname = hostname;
}
#Override
public void run(){
System.out.println("Pitcher running...");
System.out.println();
Timer timer = new Timer();
timer.schedule(new SendMessage(), 0, 1000/mps);
timer.schedule(new DisplayStatistics(), 0, 1000/mps);
}
//Nested class that sends messages
private class SendMessage extends TimerTask{
private int numberOfSentMessages = 0;
private int id;
#Override
public void run() {
try {
pitcherSocket = new Socket(InetAddress.getByName(hostname), port);
OutputStream outToServer = pitcherSocket.getOutputStream();
DataOutputStream out = new DataOutputStream(outToServer);
//send message size
out.writeInt(size);
//message id is same as number of the sent message
id = numberOfSentMessages + 1;
out.writeInt(id);
messageIds.add(id);
//get system timestamp
long currentTimestamp = System.currentTimeMillis();
out.writeLong(currentTimestamp);
//fill in the rest-
byte[] rest = new byte[size - 2 * INT_SIZE - LONG_SIZE]; //message size(default 300 bytes) - size(4 bytes) - message id(4 bytse) - timestamp(8 bytes)
out.write(rest);
out.flush();
numberOfSentMessages++;
InputStream inFromServer = pitcherSocket.getInputStream();
DataInputStream in = new DataInputStream(inFromServer);
Integer catcherMessageSize = in.readInt();
Integer catcherId = in.readInt();
long catcherTimestamp = in.readLong();
System.out.println("Sent message: " + size + " " + id + " " + currentTimestamp + "...");
System.out.println("Received message: " + catcherMessageSize + " " + catcherId + " " + catcherTimestamp + "...");
System.out.println();
}catch(IOException e)
{
e.printStackTrace();
}
}
}
}
SERVER
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
public class Catcher implements Runnable{
private int port;
private String bind;
private ServerSocket serverSocket;
//constatns, integer is 4 bytes, long is 8 bytes
private static final int INT_SIZE = 4;
private static final int LONG_SIZE = 8;
public Catcher(int port, String bind) {
this.port = port;
this.bind = bind;
}
#Override
public void run() {
System.out.println("Catcher running...");
System.out.println();
try {
serverSocket = new ServerSocket(port, 100, InetAddress.getByName(bind));
}
catch (IOException e1) {
e1.printStackTrace();
}
while(true){
try
{
Socket server = serverSocket.accept();
DataInputStream in = new DataInputStream(server.getInputStream());
Integer pitcherMessageSize = in.readInt();
Integer pitcherId = in.readInt();
long pitcherTimestamp = in.readLong();
DataOutputStream out = new DataOutputStream(server.getOutputStream());
//message id and size are sent back
out.writeInt(pitcherMessageSize);
out.writeInt(pitcherId);
//send back current time
long currentTimestamp = System.currentTimeMillis();
out.writeLong(currentTimestamp);
//fill in the rest
byte[] rest = new byte[pitcherMessageSize - 2 * INT_SIZE - LONG_SIZE]; //message size(default 300 bytes) - size(4 bytes) - message id(4 bytes) - timestamp(8 bytes)
out.write(rest);
out.flush();
System.out.println("Received message: " + pitcherMessageSize + " " + pitcherId + " " + pitcherTimestamp + "...");
System.out.println("Sent message: " + pitcherMessageSize + " " + pitcherId + " " + currentTimestamp + "...");
System.out.println();
//server.close();
}
catch(SocketTimeoutException s){
System.out.println("Socket timed out!");
break;
}
catch(IOException e){
e.printStackTrace();
break;
}
}
}
}
Have you thought about making both socket and the DataOutputStream member variables of SendMessage. This is some code to give you a rough start. You will probably want to put some enhancements like checking whether the socket is open and being able to create a new one if the current one is closed...
private class SendMessage extends TimerTask {
private int id = 10;
private Socket pitchSocket;
private DataOutputStream out;
public SendMessage(Socket socket) {
this.pitchSocket = socket;
try{
out = new DataOutputStream(pitchSocket.getOutputStream());
} catch(IOException e) {
e.printStackTrace();
}
}
#Override
public void run() {
try {
out.writeInt(id);
out.flush();
} catch(IOException e) {
e.printStackTrace();
}
}
}
After being able to view the whole code I think that you definitely have some threading issues, though I think they are more heavily on the server side rather than the client side. Your server is single threaded. That means that you can only deal with one request at a time. You want a multithreaded server. I've refactored your code to create an example of Catcher which is multithreaded. I'm using the Thead class to do all of this which may be a little old fashioned. You might want to take a look at java.util.concurrent, they will probably have a more up to date.
package clientserver;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
public class Catcher implements Runnable{
private int port;
private String bind;
private ServerSocket serverSocket;
public Catcher(int port, String bind) {
this.port = port;
this.bind = bind;
}
#Override
public void run() {
System.out.println("Catcher running...");
System.out.println();
try {
serverSocket = new ServerSocket(port, 100, InetAddress.getByName(bind));
}
catch (IOException e1) {
e1.printStackTrace();
}
while(true){
try
{
new Thread(new CatcherHandler(serverSocket.accept())).start();
Thread.sleep(1000);
}
catch(SocketTimeoutException s){
System.out.println("Socket timed out!");
break;
}
catch(IOException e){
e.printStackTrace();
break;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void main(String[] argv){
new Thread( new Catcher(8093, "localhost")).start();;
}
}
class CatcherHandler implements Runnable{
Socket server;
DataOutputStream out;
DataInputStream in;
private static final int INT_SIZE = 4;
private static final int LONG_SIZE = 8;
public CatcherHandler(Socket server) {
super();
this.server = server;
try {
in = new DataInputStream(server.getInputStream());
out = new DataOutputStream(server.getOutputStream());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void run() {
try{
if(in.available() > 0){
Integer pitcherMessageSize = in.readInt();
Integer pitcherId = in.readInt();
long pitcherTimestamp = in.readLong();
//message id and size are sent back
out.writeInt(pitcherMessageSize);
out.writeInt(pitcherId);
//send back current time
long currentTimestamp = System.currentTimeMillis();
out.writeLong(currentTimestamp);
//fill in the rest
byte[] rest = new byte[pitcherMessageSize - 2 * INT_SIZE - LONG_SIZE]; //message size(default 300 bytes) - size(4 bytes) - message id(4 bytes) - timestamp(8 bytes)
out.write(rest);
out.flush();
System.out.println("Received message: " + pitcherMessageSize + " " + pitcherId + " " + pitcherTimestamp + "...");
System.out.println("Sent message: " + pitcherMessageSize + " " + pitcherId + " " + currentTimestamp + "...");
System.out.println();
Thread.sleep(1000);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{}
//server.close();
}
}
Additionally I refactored your client to be able to use one socket and be tread safe. Now SendMessage takes in a DataInputStream and a DataOutputSteam as it's arguments.
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
public class Pitcher implements Runnable{
private int port;
private int mps;
private int size;
private String hostname;
private List<Integer> messageIds = Collections.synchronizedList(new ArrayList<Integer>());
private Socket pitcherSocket;
private DataOutputStream out;
private DataInputStream in;
//constatns, integer is 4 bytes, long is 8 bytes
private static final int INT_SIZE = 4;
private static final int LONG_SIZE = 8;
public Pitcher(int port, int mps, int size, String hostname) {
this.port = port;
this.mps = mps;
this.size = size;
this.hostname = hostname;
try {
this.pitcherSocket = new Socket(InetAddress.getByName(hostname), port);
out = new DataOutputStream(pitcherSocket.getOutputStream());
in = new DataInputStream(pitcherSocket.getInputStream());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] argv) throws Exception{
for(int i = 0; i < 10; i++){
new Thread(new Pitcher(8093, 1, 200, "localhost")).start();
Thread.sleep(1000);
}
Thread.sleep(10000);
}
#Override
public void run(){
System.out.println("Pitcher running...");
System.out.println();
Timer timer = new Timer();
timer.schedule(new SendMessage(out, in), 0, 1000);
//timer.schedule(new DisplayStatistics(), 0, 1000);
}
//Nested class that sends messages
private class SendMessage extends TimerTask{
private int numberOfSentMessages = 0;
private int id;
private DataOutputStream out;
private DataInputStream in;
public SendMessage(DataOutputStream out, DataInputStream in){
this.out = out;
this.in = in;
}
#Override
public void run() {
try {
long currentTimestamp = 0L;
synchronized(out){
//send message size
out.writeInt(size);
//message id is same as number of the sent message
id = numberOfSentMessages + 1;
out.writeInt(id);
messageIds.add(id);
//get system timestamp
currentTimestamp = System.currentTimeMillis();
out.writeLong(currentTimestamp);
//fill in the rest-
byte[] rest = new byte[size - 2 * INT_SIZE - LONG_SIZE]; //message size(default 300 bytes) - size(4 bytes) - message id(4 bytse) - timestamp(8 bytes)
out.write(rest);
out.flush();
}
numberOfSentMessages++;
long catcherTimestamp = 0L;
Integer catcherMessageSize;
Integer catcherId;
synchronized(in){
catcherMessageSize = in.readInt();
catcherId = in.readInt();
catcherTimestamp = in.readLong();
}
System.out.println("Sent message: " + size + " " + id + " " + currentTimestamp + "...");
System.out.println("Received message: " + catcherMessageSize + " " + catcherId + " " + catcherTimestamp + "...");
System.out.println();
Thread.sleep(1000);
}catch(IOException e)
{
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
The Java Socket class is not thread safe. To have multiple threads access the same Socket object you would need to synchronize their actions. This could be done by providing all your SendMessage-threads with a common object that would then act as a lock. You would need an object for each socket operation you are planning to use (e.g. read and write). Then, refactor every action that does a call to the Socket object into separate methods and synchronize them around that object. E.g. for the read operation you could have a method called read() inside SendMessage that calls Socket.read and synchronize this method around the lock-object for read.
private class SendMessage extends TimerTask{
private Object readLock;
private Socket socket;
public SendMessage(Object readLock, Socket socket) {
this.readLock = readLock;
this.socket = socket;
}
public void readFromSocket() {
synchronized(readLock) {
socket.read();
}
}
#Override
public void run() {
readFromSocket();
// do other stuff
}
}
I am attempting to send a BufferedImage over a socket sever to another client. Ill post my code below. When I run the server and the connect to the server with the sending client, and receiving client, everything just sits there. The server shouldn't even be receiving anything unless it has already printed "name is attempting to connect to: " which it doesn't it just sits there. I don't know why it doesn't do anything at all.
Client that sends: http://pastebin.com/X4z55Hdp
Client that receives: http://pastebin.com/MB9qEyGy
Server Source that sends and recieves:
package core;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import utilities.Tools;
public class Node implements Runnable {
private String name;
private Socket socket;
private boolean isApp;
public Node(Socket s, String name) {
this.setName(name);
this.setSocket(s);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Socket getSocket() {
return socket;
}
public void setSocket(Socket socket) {
this.socket = socket;
}
public void run() {
while (true) {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(),
true);
if (in.readLine() != null) {
// Tools.log("[INPUT] " + in.readLine());
String i = in.readLine();
if (i.contains("set name ")) {
String n = i.replace("set name ", "");
Tools.log("Changing " + name + " to " + n);
this.name = n;
if (n.contains("_app")) {
this.isApp = true;
}
} else {
String toFind = name + "_app";
if (isApp)
toFind = name.replace("_app", "");
Tools.log(name + " is attempting to connect to: "
+ toFind);
for (Node n : Server.nodes) {
if (n.getName().equals(toFind)) {
Tools.log(n.getName() + " found, sending data");
ObjectOutputStream outToNode = new ObjectOutputStream(
n.getSocket().getOutputStream());
ObjectInputStream inFromClient = new ObjectInputStream(
socket.getInputStream());
BufferedImage img = (BufferedImage) inFromClient
.readObject();
if (img != null) {
outToNode.writeObject(img);
}
}
}
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
The BufferedImage must be serialized. You can convert the image in to a byte array and once it reads the byte array, convert it back in to an image.
The sender is undoubtedly getting a NotSerializableException when calling writeObject() with a BufferedImage, because BufferedImage doesn't implement Serializable. Therefore you can't get one from a readObject() call either. You'll have to turn the BufferedImage into bytes for sending, and back again when receiving. Have a look at javax.imageio for one way to do this.
I want to create a server that can accept multiple connections and then bind 2 clients as a pair and forward the data between these 2 clients. But it is about multiple pairs of clients. I already have multithread server that can create a new thread for each new connected client. The problem for me is that these threads dont know of each other and somehow I have to connect 2 clients to a connection pair.
For now I just create these pair connection as this: I wait for the first client, then I wait for the second client and then open a thread for the input of client 1 that gets forwarded to client 2 and the other way around. This is not usable for multiple clients.
How can I do this decent?
The way I see it, a client would need to
establish a TCP(?) connection with your server,
identify itself
give the ID of the other client it wishes to talk to
The first that connects would have to be kept on hold (in some global table in your server) until the second client connects.
Once a pair of clients would have been recognized as interlocutors, you would create a pair of threads to forward the data sent by each client to the other one.
UPDATE: Example
ClientSocket.java
package matchmaker;
import java.io.Closeable;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class ClientSocket implements Closeable {
private final Socket socket;
private final InputStream in;
private final OutputStream out;
private final String ownId;
private final String peerId;
public ClientSocket(Socket socket) throws IOException {
this.socket = socket;
this.in = socket.getInputStream();
this.out = socket.getOutputStream();
DataInputStream din = new DataInputStream(in);
this.ownId = din.readUTF();
this.peerId = din.readUTF();
}
public ClientSocket(String server, int port, String ownId, String peerId)
throws IOException {
this.socket = new Socket(server, port);
this.socket.setTcpNoDelay(true);
this.in = socket.getInputStream();
this.out = socket.getOutputStream();
this.ownId = ownId;
this.peerId = peerId;
DataOutputStream dout = new DataOutputStream(out);
dout.writeUTF(ownId);
dout.writeUTF(peerId);
}
public String getOwnId() {
return ownId;
}
public String getPeerId() {
return peerId;
}
public InputStream getInputStream() {
return in;
}
public OutputStream getOutputStream() {
return out;
}
#Override
public void close() throws IOException {
socket.close();
}
}
Matchmaker.java: the server
package matchmaker;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Matchmaker extends Thread {
private static final Logger LOG
= Logger.getLogger(Matchmaker.class.getName());
private final int port;
private final Map<ClientPair,ClientSocket> waiting = new HashMap<>();
public static void main(String[] args) {
try {
int port = 1234;
int st = 0;
for (String arg: args) {
switch (st) {
case 0:
switch (arg) {
case "-p":
st = 1;
break;
default:
System.out.println("Unknown option: " + arg);
return;
}
break;
case 1:
port = Integer.parseInt(arg);
st = 0;
break;
}
}
Matchmaker server = new Matchmaker(port);
server.start();
server.join();
} catch (InterruptedException ex) {
LOG.log(Level.SEVERE, null, ex);
}
}
private Matchmaker(int port) {
this.port = port;
setDaemon(true);
}
#Override
public void run() {
try {
ServerSocket server = new ServerSocket(port);
while (true) {
ClientSocket socket = new ClientSocket(server.accept());
ClientPair pair = new ClientPair(
socket.getOwnId(), socket.getPeerId());
ClientSocket other;
synchronized(this) {
other = waiting.remove(pair.opposite());
if (other == null) {
waiting.put(pair, socket);
}
}
if (other != null) {
LOG.log(Level.INFO, "Establishing connection for {0}",
pair);
establishConnection(socket, other);
} else {
LOG.log(Level.INFO, "Waiting for counterpart {0}", pair);
}
}
} catch (IOException ex) {
LOG.log(Level.SEVERE, null, ex);
}
}
private void establishConnection(ClientSocket socket, ClientSocket other)
throws IOException {
Thread thread = new StreamCopier(
socket.getInputStream(), other.getOutputStream());
thread.start();
thread = new StreamCopier(
other.getInputStream(), socket.getOutputStream());
thread.start();
}
}
StreamCopier.java: a thread that reads from an InputStream and writes to an OutputStream
package matchmaker;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
public class StreamCopier extends Thread {
private static final Logger LOG
= Logger.getLogger(StreamCopier.class.getName());
private final InputStream in;
private final OutputStream out;
public StreamCopier(InputStream in, OutputStream out) {
this.in = in;
this.out = out;
setDaemon(true);
}
#Override
public void run() {
LOG.info("Start stream copier");
try {
for (int b = in.read(); b != -1; b = in.read()) {
out.write(b);
}
} catch (IOException ex) {
LOG.log(Level.SEVERE, null, ex);
} finally {
LOG.info("End stream copier");
try {
out.close();
} catch (IOException ex) {
LOG.log(Level.SEVERE, null, ex);
}
}
}
}
ClientPair.java: a pair of client IDs
package matchmaker;
public class ClientPair {
private final String client1;
private final String client2;
public ClientPair(String client1, String client2) {
this.client1 = client1;
this.client2 = client2;
}
public String getClient1() {
return client1;
}
public String getClient2() {
return client2;
}
public ClientPair opposite() {
return new ClientPair(client2, client1);
}
#Override
public int hashCode() {
int hash = 5;
hash = 73 * hash + client1.hashCode();
hash = 73 * hash + client2.hashCode();
return hash;
}
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final ClientPair other = (ClientPair) obj;
return client1.equals(other.client1) && client2.equals(other.client2);
}
#Override
public String toString() {
return "[" + client1 + "," + client2 + "]";
}
}
ReaderClient.java: a sample client that reads from the socket and writes to standard output
package matchmaker;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.logging.Level;
import java.util.logging.Logger;
public class ReaderClient {
private static final Logger LOG = Logger.getLogger(ReaderClient.class.getName());
public static void main(String[] args) {
try (ClientSocket client
= new ClientSocket("localhost", 1234, "reader", "writer")) {
Reader reader
= new InputStreamReader(client.getInputStream(), "UTF-8");
BufferedReader in = new BufferedReader(reader);
for (String s = in.readLine(); s != null; s = in.readLine()) {
System.out.println(s);
}
} catch (IOException ex) {
LOG.log(Level.SEVERE, null, ex);
}
}
}
WriterClient.java: a sample client that writes to the socket
package matchmaker;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.logging.Level;
import java.util.logging.Logger;
public class WriterClient {
private static final Logger LOG = Logger.getLogger(ReaderClient.class.getName());
public static void main(String[] args) {
try (ClientSocket client
= new ClientSocket("localhost", 1234, "writer", "reader")) {
Writer writer
= new OutputStreamWriter(client.getOutputStream(), "UTF-8");
PrintWriter out = new PrintWriter(writer);
for (int i = 0; i < 30; ++i) {
out.println("Message line " + i);
}
out.flush();
} catch (IOException ex) {
LOG.log(Level.SEVERE, null, ex);
}
}
}
I am planning to do a java onvif application. I have created a new project and generated sources from devicemgmt.wsdl.Also generated the classes from remote discovery.wsdl.
How can I discover a device in a network using theses generated classes?
Thanks for any help.
devicemgmt.wsdl is not related to discovery process, the ONVIF discovery process is based on http://specs.xmlsoap.org/ws/2005/04/discovery it use SOAP over UDP.
If you are using apache-cxf, this can be achieve using
org.apache.cxf.ws.discovery.WSDiscoveryClient
A simple sample code could be :
import java.util.List;
import javax.xml.ws.EndpointReference;
import org.apache.cxf.ws.discovery.WSDiscoveryClient;
public class Main
{
public static void main(String[] args)
{
WSDiscoveryClient client = new WSDiscoveryClient();
client.setVersion10(); // use WS-discovery 1.0
client.setDefaultProbeTimeout(1000); // timeout 1s
System.out.println("Probe:" + client.getAddress());
List<EndpointReference> references = client.probe();
System.out.println("Nb answsers:" + references.size());
for (EndpointReference ref : references)
{
System.out.println(ref.toString());
}
}
}
I had the same problem, CXF is simply to big, please check my approach: JavaWsDiscovery at https://github.com/thhart/javaWsDiscovery.
It uses a simple network probe as suggested by Onvif standards to be able to identify any devices on your local network, following line will return you all available devices:
final Collection urls = DeviceDiscovery.discoverWsDevicesAsUrls("^http$", ".onvif.");
Simple and complete example pure Java
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
/**
*
* #author Ronald
*/
public class TestDiscoveryPureJava {
public static void main(String cor[]) throws SocketException{
discoverWsDevices();
}
public static void discoverWsDevices() throws SocketException {
final int WS_DISCOVERY_PORT = 3702;
final String WS_DISCOVERY_ADDRESS_IPv4 = "239.255.255.250";
Thread thread = new Thread() {
#Override
public void run() {
final String probe = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:a=\"http://schemas.xmlsoap.org/ws/2004/08/addressing\">\n" +
" <s:Header>\n" +
" <a:Action s:mustUnderstand=\"1\">http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe</a:Action>\n" +
" <a:MessageID>uuid:f0ded492-301a-4891-882b-cb2d7cac2e45</a:MessageID>\n" +
" <a:ReplyTo>\n" +
" <a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address>\n" +
" </a:ReplyTo>\n" +
" <a:To s:mustUnderstand=\"1\">urn:schemas-xmlsoap-org:ws:2005:04:discovery</a:To>\n" +
" </s:Header>\n" +
" <s:Body>\n" +
" <Probe xmlns=\"http://schemas.xmlsoap.org/ws/2005/04/discovery\">\n" +
" <d:Types xmlns:d=\"http://schemas.xmlsoap.org/ws/2005/04/discovery\" xmlns:dp0=\"http://www.onvif.org/ver10/network/wsdl\">dp0:Device</d:Types>\n" +
" </Probe>\n" +
" </s:Body>\n" +
"</s:Envelope>";
DatagramSocket datagramSocket = null;
try {
datagramSocket = new DatagramSocket();
datagramSocket.setBroadcast(true);
datagramSocket.setSoTimeout(9000);
} catch (SocketException e) {
System.out.println( "In discoverWsDevices datagram socket exception" + datagramSocket);
e.printStackTrace();
}
byte[] soapMessageByteArray = probe.getBytes();
DatagramPacket datagramPacketSend = null;
try {
datagramPacketSend = new DatagramPacket(
soapMessageByteArray,
soapMessageByteArray.length,
InetAddress.getByName(WS_DISCOVERY_ADDRESS_IPv4),
WS_DISCOVERY_PORT);
} catch (UnknownHostException e) {
System.out.println("Unknown host in send packet");
e.printStackTrace();
}
try {
System.out.println("Send package");
datagramSocket.send(datagramPacketSend);
System.out.println("package sent");
} catch (IOException e) {
System.out.println("In discoverWsDevices datagram socket IOException send " + datagramSocket);
e.printStackTrace();
}
System.out.println("Sending data");
System.out.println(datagramPacketSend.getAddress().getHostName()+":"+WS_DISCOVERY_PORT);
List<ByteArrayInputStream> probeMatches = new ArrayList<>();
while (true) {
byte[] responseMessageByteArray = new byte[9000];
DatagramPacket datagramPacketRecieve = new DatagramPacket(responseMessageByteArray,responseMessageByteArray.length);
try {
System.out.println("Waiting response...");
datagramSocket.receive(datagramPacketRecieve);
} catch (SocketTimeoutException e) {
datagramSocket.close();
System.out.println("In discoverWsDevices datagram socket timeout exception");
break;
} catch (IOException e) {
System.out.println("In discoverWsDevices datagram socket ioexception");
e.printStackTrace();
break;
}
probeMatches.add(new ByteArrayInputStream(datagramPacketRecieve.getData(), 0, datagramPacketRecieve.getLength()));
}
for (ByteArrayInputStream input : probeMatches) {
byte[] bytes = new byte[input.available()];
input.read(bytes, 0, input.available());
String stream = new String(bytes);
System.out.println("stream" + stream);
}
}
};
thread.start();
}
}