message skip in local wifi chat without internet - java

I want to chat on two or more device using wifi without internet. I am sending message using socket from first android mobile to second mobile. I have faced issue that some massage is received and some massage skip and not received on second mobile. I have tried Multicastsoket and Datagramsoket but text message skipped. following is my send side and receiver side code.
**- Sender side**
public static void sender(final String ipAddress, final String message) {
// Creates the thread for capturing and transmitting audio
/* AsyncTaskExample asyncTask = new AsyncTaskExample();
asyncTask.execute(message);*/
Thread replyThread = new Thread(new Runnable() {
#Override
public void run() {
try {
InetAddress address = InetAddress.getByName(ipAddress);
byte[] data = message.getBytes();
DatagramSocket socket = new DatagramSocket();
DatagramPacket packet = new DatagramPacket(data, data.length, address, BROADCAST_PORT);
socket.setReuseAddress(true);
socket.send(packet);
Log.i(LOG_TAG, "Sent message( " + message + " ) to " + ipAddress);
socket.disconnect();
socket.close();
} catch (UnknownHostException e) {
Log.e(LOG_TAG, "Failure. UnknownHostException in sendMessage: " + ipAddress);
} catch (SocketException e) {
Log.e(LOG_TAG, "Failure. SocketException in sendMessage: " + e);
} catch (IOException e) {
Log.e(LOG_TAG, "Failure. IOException in sendMessage: " + e);
}
}
});
replyThread.start();
}
**- Receiver side**
public void receiver() {
// Creates the thread for receiving massage
Thread receiveThread = new Thread(new Runnable() {
#Override
public void run() {
try {
DatagramSocket socket = new DatagramSocket(BROADCAST_PORT);
// InetAddress group = InetAddress.getByName(myIPAddress);
//socket.setSoTimeout(1000);
byte[] buffer = new byte[BUF_SIZE];
DatagramPacket packet = new DatagramPacket(buffer, BUF_SIZE);
while (LISTEN) {
// Listen for incoming call requests
try {
Log.i(LOG_TAG, "Listening for incoming message");
/* Arrays.fill(buffer,(byte)0);*/
socket.receive(packet);
String data = new String(buffer, 0, packet.getLength());
Log.i("SocketMSG", "Packet received from " + packet.getAddress() + " with contents: " + data);
String action = data.substring(0, 4);
//Toast.makeText(context,"Packet received from",Toast.LENGTH_SHORT).show();
} catch (Exception e) {
}
}
socket.disconnect();
socket.close();
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
});
receiveThread.start();
}

You could implement TCP-like behavior on top of UDP, see this repo for example: https://github.com/jin-zhe/reliable-UDP/blob/master/Sender.java

Related

Need help in Java Socket Programming[server & client]

I have created a Java server named server.java using java sockets which accepts a string from a client (client.java) on Android, modifies it and send the modified string to the client [which in my case is an Android app].
When I tried to run both of them, without any error the android app successfully sends the user inputted string to the server. The problem arises when server receives the string, sometimes the server does not provide any output. But if the client is closed (or killed) then server terminal outputs as :
message received from client is: null
request: Message sent to the client : i received message:null
message received from client is: null
request: Message sent to the client : i received message:null
message received from client is: null
request: Message sent to the client : i received message:null
message received from client is: null
request: Message sent to the client : i received message:null
message received from client is: null
request: Message sent to the client : i received message:null
Here is the code for Server.java which runs in a desktop computer:
public class Server {
static Socket socket;
static PrintWriter out;
static BufferedReader in;
static int port = 9999;
public static void main(String[] args) {
String query="blank", returnMessage="Server malfunctioning!";
try {
ServerSocket serverSocket = new ServerSocket(port);
System.out.println("Server Started and listening to the port "+port);
socket = serverSocket.accept();
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
while(true) {
try {
query=in.readLine();
System.out.println("message received from client is: "+query);
//Processing the query.
returnMessage="i received message:"+query;
//Sending the response back to the client.
out.print(returnMessage);
System.out.println("request: Message sent to the client : " + returnMessage);
} catch (IOException e) {
e.printStackTrace();
} finally {
out.flush();
out.close();
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
socket.close();
} catch(Exception e) {
System.out.println(e);
}
}
}
}
And here is ServerConnect.java which extends AsyncTask:
public class ServerConnect extends AsyncTask<Object, Object, Void> {
String TAG="Server";
String message="empty response";
String ip="EMPTY QUERY";
WebView wb;
TextToSpeech tts;
String host = "192.168.2.3";
int port = 9999;
PrintWriter out;
BufferedReader in;
Socket socket;
ServerConnect(String inp, WebView wbb, TextToSpeech ts) {
ip=inp;
this.wb=wbb;
tts=ts;
}
#Override
protected Void doInBackground(Object... voids) {
Log.d(TAG, "ip value "+ip);
try {
// InetAddress address = InetAddress.getByName(host);
socket = new Socket(host, port);
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
try {
//Send the message to the server
out.print(ip);
//out.flush();
Log.d(TAG, "request: Message sent to the server : " + ip);
message = in.readLine();
Log.d(TAG, "doInBackground: message" + message);
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
message = "UnknownHostException: " + e.toString();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
message = "My Brain is not working! Reason is: "+e;
} finally {
in.close();
out.flush();
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
Log.d(TAG, "doInBackground: finally block");
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
protected void onPostExecute(Void result) {
// wb.getSettings().setJavaScriptEnabled(true);
if(message!=null) {
wb.loadDataWithBaseURL(null, message, "text/html", "utf-8", null);
tts.speak(stripHtml(message), TextToSpeech.QUEUE_FLUSH, null, null);
if (!(pullLinks(stripHtml(message)).equals(""))) {
wb.setWebViewClient(new WebViewClient());
wb.setWebChromeClient(new WebChromeClient() {});
wb.loadUrl(pullLinks(message));
//ip.setText("");
super.onPostExecute(result);
}
} else {
wb.loadDataWithBaseURL(null, "Message is null!", "text/html", "utf-8", null);
tts.speak("Message is null!", TextToSpeech.QUEUE_FLUSH, null, null);
}
}
public String stripHtml(String html) {
return Html.fromHtml(html).toString();
}
private String pullLinks(String text) {
String links="";
String regex = "\\(?\\b(http://|www[.])[-A-Za-z0-9+&##/%?=~_()|!:,.;]*[-A-Za-z0-9+&##/%=~_()|]";
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(text);
while(m.find()) {
String urlStr = m.group();
if (urlStr.startsWith("(") && urlStr.endsWith(")"))
urlStr = urlStr.substring(1, urlStr.length() - 1);
links=urlStr;
}
return links;
}
}
readLine() returns null at end of stream, i.e. when the peer has closed the connection. You aren't detecting that case: you are treating the null as data. You need to terminate the read loop when you get the null.
NB UnknownHostException cannot be thrown by either print() or readLine().

How to send message from server to client

I am trying to make an chatprogram in Java, when I send message on the client side the server side gets the message. But when I send from the server side to the client it do not get the message.
I cannot see what I am doing wrong.
The server side code:
private void serverStart(){
textArea.append("Starting server " + " \n");
try {
serverSocket = new ServerSocket(4444);
textArea.append("Waiting for Clients " + " \n");
//Reading message from the client
socket = serverSocket.accept();
textArea.append("Client Connected " + "\n");
//Send message to client
out = new PrintWriter(socket.getOutputStream());
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while (true)
{
messageFromClient = in.readLine();
whileChat(messageFromClient);
}
} catch(IOException ioExecption) {
ioExecption.printStackTrace();
}
}
private void whileChat(String messageFromClient) {
showMessage(messageFromClient);
System.out.println("Message from client : " + messageFromClient);
}
protected static void showMessage(final String message) {
SwingUtilities.invokeLater(
new Runnable(){
public void run()
{
Gui.consoleTextArea.append(message + "\n");
}
});
}
public static void sendMessage(String message) {
out.println(message);
showMessage(name + " : " + message + "\n");
}
The Client side :
private void connectToServer() {
try {
socket = new Socket("localhost", 4444);
} catch (UnknownHostException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
Thread clientThread = new Thread(new Runnable() {
#Override
public void run() {
try {
// attach to socket's output stream with auto flush turned on
//Send message to the server
out = new PrintWriter(socket.getOutputStream(),
true);
//Get return message from server
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
messageFromServer = in.readLine();
whileChatting(messageFromServer);
} catch (Exception e) {
e.printStackTrace();
}
}
});
clientThread.start();
}
private void whileChatting(String messageFromServer) {
showMessage(messageFromServer);
System.out.println("Message from server to client " + messageFromServer);
}
public static void Send(String msg) {
out.println(name + " : " + msg);
showMessage(name + " : " + msg + "\n");
}
protected static void showMessage(final String message) {
SwingUtilities.invokeLater(
new Runnable(){
public void run(){
Gui.consoleTextArea.append(message);
}
});
}
Hope someone could help me with this problem.
You could perform a flush on the PrintWriter immediately after each println, or even better: Instance the PrintWriter with autoFlush=true:
out = new PrintWriter(socket.getOutputStream(), true);
In this way, each time you call println, printf, or format, the PrintWriter will perform a flush of the buffer at the end.
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
This line is always waiting the client output, and your client also doesn't send message to server.
Attention: both your server and client not read user input.

Netty 4 Receive Multicast packets on Linux

I have written an app which receives multicast packets sent by a sender (containing audio).
I have used Netty 4 and have got the app working on Windows but it will not receive multicast packets when run on Linux (Debian Wheezy (raspi) and Ubuntu 12).
I have created some test code that can send and receive multicast packets, the results are:
Send Windows to Windows works.
Send Linux to Windows works.
Send Windows to Linux, packets are sent but not received.
I run the app as root and have SO_BROADCAST set to true.
What have I missed?
If I use the standard Java MulticastSocket instead of Netty, then the app works, but I would prefer to use Netty as it is easy to use and simplifies to code greatly.
The test code is :
public class TestMulticast {
private int port = 51972;
private Logger log = Logger.getLogger(this.getClass());
private InetAddress remoteInetAddr = null;
private InetSocketAddress remoteInetSocket = null;
private InetAddress localInetAddr = null;
private InetSocketAddress localInetSocket = null;
private DatagramChannel ch = null;
private EventLoopGroup group = new NioEventLoopGroup();
private boolean bSend = false;
public TestMulticast(String localAddress, String remoteAddress, String sPort, boolean bSend) {
this.bSend = bSend;
try {
localInetAddr = InetAddress.getByName(localAddress.trim());
remoteInetAddr = InetAddress.getByName(remoteAddress.trim());
} catch (Exception e) {
log.error("Error creating InetAddresses. Local: " + localAddress + " Remote: " + remoteAddress, e);
}
try {
port = Integer.parseInt(sPort);
} catch (Exception e) {
log.error("Error Parsing Port: " + sPort, e);
}
}
public void run() throws Exception {
log.debug("Run TestMulticast, Send Packet = " + bSend);
try {
localInetSocket = new InetSocketAddress(port);
remoteInetSocket = new InetSocketAddress(remoteInetAddr, port);
Bootstrap b = new Bootstrap();
b.group(group);
b.channelFactory(new ChannelFactory<Channel>() {
#Override
public Channel newChannel() {
return new NioDatagramChannel(InternetProtocolFamily.IPv4);
}
});
b.option(ChannelOption.SO_BROADCAST, true);
b.option(ChannelOption.SO_REUSEADDR, true);
b.option(ChannelOption.IP_MULTICAST_LOOP_DISABLED, false);
b.option(ChannelOption.SO_RCVBUF, 2048);
b.option(ChannelOption.IP_MULTICAST_TTL, 255);
b.handler(new LoggingHandler(LogLevel.DEBUG));
log.debug("Am I Logged on as ROOT: " + PlatformDependent.isRoot());
ch = (DatagramChannel) b.bind(localInetSocket).sync().channel();
log.debug("Result of BIND: " + ch.toString());
if (remoteInetAddr.isMulticastAddress()) {
NetworkInterface nic = NetworkInterface.getByInetAddress(localInetAddr);
ChannelFuture future = ch.joinGroup(remoteInetSocket, nic);
log.debug("Result of Join: " + future.toString());
} else {
log.debug("############NOT A MULTICAST ADDRESS: '" + remoteInetAddr.getHostAddress() + "'");
}
if (bSend) {
group.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
try {
Date date = new Date();
byte[] bytes = date.toString().getBytes();
ByteBuf buffer = Unpooled.copiedBuffer(bytes);
DatagramPacket packet = new DatagramPacket(buffer, remoteInetSocket, localInetSocket);
ch.writeAndFlush(packet);
} catch (Exception e) {
log.error("Error Sending DatagramPacket", e);
}
}
}, 0, 10, TimeUnit.SECONDS);
}
} catch (Exception e) {
log.error(e);
}
}
public void stop() {
try {
if (ch != null) {
try {
ch.close();
} catch (Exception e) {
log.error("Error Closing Channel", e);
}
}
group.shutdownGracefully();
} catch (Exception e) {
log.error("Error ShuutingDown", e);
}
}
}
EDIT:
If found my problem, I should learn to read the docs!!
For Mutlicast you should bind to the WILDCARD Address.
So changing the code to
localInetSocket = new InetSocketAddress(remotePort);
....
ch = (DatagramChannel) b.bind(localInetSocket).sync().channel();
....
if (remoteInetAddr.isMulticastAddress()) {
NetworkInterface nic = NetworkInterface.getByInetAddress(localInetAddr);
ChannelFuture future = ch.joinGroup(remoteInetSocket, nic);
log.debug("Result of Join: " + future.toString());
}
I've modified the full code above with the new changes..
Pete.

MulticastSocket doesn't open port

I'm trying to create a simple multicast communication between my PC (Ubuntu, client) and my phone (Android, server).
Unicast/TCP connections work without any problem, the defined port (37659) opens both on PC and phone. When trying to use a MulticastSocket, no ports get opened. nmap tells me the specified port (36963) is a TCP port and that it is closed. (While the receive-method is being executed).
Am I doing something wrong? Or is the firewall blocking the multicast sockets? (I've tried about 20 different ports and none worked..., currently using port 36963)
EDIT: Also with the firewall completely down, nmap tells me the port is closed...
The server's code (phone):
private void multicastLoop() {
String res = Build.FINGERPRINT + "\n";
final InetAddress group;
final MulticastSocket socket;
final DatagramPacket response;
try {
group = InetAddress.getByName("224.0.0.115");
socket = new MulticastSocket(mport);
socket.setLoopbackMode(true);
socket.setSoTimeout(10000);
socket.joinGroup(group);
response = new DatagramPacket(res.getBytes(), res.length(), group, mport);
} catch (IOException e) {
e.printStackTrace();
return;
}
Thread t = new Thread(new Runnable() {
#Override
public void run() {
while(isRunning) {
try {
byte[] data = new byte[1024];
DatagramPacket dm = new DatagramPacket(data, data.length);
socket.receive(dm);
Log.d("udp", "received");
if (Arrays.equals(dm.getData(), "someone there".getBytes())) {
socket.send(response);
}
} catch (SocketTimeoutException e) {
continue;
} catch (IOException e) {
e.printStackTrace();
}
}
try {
socket.leaveGroup(group);
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
t.start();
}
The client's code (computer):
public String[] findServers() {
String hello = "someone there";
try {
InetAddress group = InetAddress.getByName(mhost);
MulticastSocket socket = new MulticastSocket(mport);
socket.setLoopbackMode(true);
socket.setSoTimeout(60000);
socket.joinGroup(group);
DatagramPacket p = new DatagramPacket(hello.getBytes(), hello.length(), group, mport);
byte[] buffer = new byte[1024];
socket.send(p);
DatagramPacket r = new DatagramPacket(buffer, buffer.length);
socket.receive(r);
socket.leaveGroup(group);
socket.close();
String srinfo = "";
byte[] data = r.getData();
for (byte b: data)
srinfo += (char) b;
System.out.println("Server found at " + r.getAddress().getHostName() + ": " + srinfo);
} catch (SocketTimeoutException e) {
return new String[] {"timeout"};
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
Make sure mhost is set to "224.0.0.115" not some machine name.
Make sure multicast is enabled on your router.
If the host is multi-homed, you need to join the multicast group via all local interfaces, not just the default one, which is what you're doing at present.
You could send the response back to the source address it came from, which is in the received datagram packet. That would also mean that the client doesn't need a MulticastSocket, only a DatagramSocket.

Exception in sending message via SCTP in Java

I am doing some testing with SCTP in a simple client server model.
My Server code is following:
public class SCTPServer extends Thread {
InetSocketAddress serverSocketAddress=null;
SctpServerChannel sctpServerChannel;
SctpChannel sctpChannel;
boolean running = false;
ByteBuffer bf = ByteBuffer.allocateDirect(160);
String id= null;
public SCTPClient sctpClient= null;
public SCTPServer(String IP, int port, String clientIp, int clientPort, String id) {
try {
serverSocketAddress = new InetSocketAddress(IP, port);
sctpServerChannel = SctpServerChannel.open().bind(serverSocketAddress);
} catch (Exception e) {
System.out.println("Failed to open Sctp connection Reciver on IP:" + IP + " and Port:" + port+" "+e);
System.exit(0);
}
}
public void run()
{
running = true;
while (running) {
try {
sctpClient.sendAsp();
sctpChannel = sctpServerChannel.accept();
try {
sctpChannel.receive(bf, null, null);
bf.flip();
byte[] barry = new byte[bf.limit()]; //we may keep the received data on this new byte arrray here or in some
bf.get(barry, 0, bf.limit());
bf.clear();
System.out.println("new sctp message is received");
System.out.println(new String(barry));
} catch (IOException ex) {
System.out.println("Failed to receive from sctp Channel " + ex);
}
} catch (Exception ex) {
System.out.println("Exception at Starting SCTP Server channel"+ ex);
}
}
}
}
and the client code following:
public class SCTPClient extends Thread {
SctpChannel sctpChannel;
InetSocketAddress socketAddress;//= new InetSocketAddress("202.51.176.44", 5555);
boolean runniung = false;
ByteBuffer bf = ByteBuffer.allocateDirect(160);
String id= null;
public SCTPClient(String ip, int port, int maxInStream, int maxOutStream, String id) {
socketAddress = new InetSocketAddress(ip, port);
this.id = id;
//InetSocketAddress sockAd = new InetSocketAddress("202.51.176.44",55556);
try {
sctpChannel = SctpChannel.open();
System.out.println("SCTP connection opened with IP==" + ip + " port == " + port);
//sctpChannel.bind(sockAd);
sctpChannel.connect(socketAddress, maxInStream, maxOutStream);
runniung = true;
sendMSG();
} catch (Exception ex) {
System.out.println("Exception at opening sctp connection:" + ex);
System.exit(0);
}
}
public void sendMSG()
{
MessageInfo messageInfo =null;
/*try {
} catch (IOException ex) {
System.out.println("Failed to create Message Info " + ex.toString());
}*/
messageInfo = MessageInfo.createOutgoing( null, 0);
ByteBuffer byteBuffer = buildMessage(1, "test");
try {
sctpChannel.send(byteBuffer, messageInfo);
byteBuffer.clear();
System.out.println("A message has been sent");
} catch (Exception e) {
e.printStackTrace();
System.out.println("Failed to send the message due to :" + e.toString());
}
}
public static ByteBuffer buildMessage(Integer id,String infoString)
{
//We can calculate the total length of the message hard codedly, even before building the total message.
int totalLength = (id!=null) ? 16 : 8;
totalLength += (infoString!=null) ? (4+infoString.length()) : 0;
ByteBuffer data = ByteBuffer.allocateDirect(totalLength);
//Own part of ASP Up message
if(id!=null)
{
data.putInt(ASPIdentifier);
}
if(infoString!=null)
{
data.put(infoString.getBytes());
}
return data;
}
}
The problem here is that, when I try to connect to a remote PC the SCTP association is established successfully. But when the SendMSG function is called the system aborts with following exception
java.net.SocketException: Invalid argument
at sun.nio.ch.SctpChannelImpl.send0(Native Method) Failed to send the message due to :java.net.SocketException: Invalid argument
at sun.nio.ch.SctpChannelImpl.sendFromNativeBuffer(SctpChannelImpl.java:1027)
at sun.nio.ch.SctpChannelImpl.send(SctpChannelImpl.java:987)
at sun.nio.ch.SctpChannelImpl.send(SctpChannelImpl.java:967)
at sctptester.SCTPClient.sendMSG(SCTPClient.java:79)
at sctptester.SCTPClient.<init>(SCTPClient.java:40)
at test.main(test.java:66)
After comparing your client code to a simulator that I just wrote last week, I can see only one real difference. You did not bind your client's socket to a local InetSocketAddress. Where you have:
sctpChannel.bind(sockAd);
You need to put something like:
InetSocketAddress localISA = new InetSocketAddress(localIPAddress, localPort);
sctpChannel.bind(localISA);
I believe this will do it for you, or at least get you past the error you posted.
I think you should add the destination when sending in the client,
messageInfo = MessageInfo.createOutgoing( null, 0);
//replace with
msgInfo = MessageInfo.createOutgoing(new InetSocketAddress(ip, port), 0);

Categories

Resources