Jetpack Composables with TCP Socket Connection Crashing - sockets

I am using Jetpack Composables and Android WiFi P2P API guide to create buttons and animation but trying to maintain an active TCP socket to output and receive data. However, whenever the program tries to establishes the connection using "socket.connect((InetSocketAddress())" it crashes the app.
class MainActivity : ComponentActivity() {
val manager: WifiP2pManager? by lazy(LazyThreadSafetyMode.NONE) {
getSystemService(Context.WIFI_P2P_SERVICE) as WifiP2pManager?
}
var channel: WifiP2pManager.Channel? = null
var receiver: BroadcastReceiver? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Obtain an instance of WifiP2pManager and register application with the Wi-Fi P2P framework
// Initialize() method returns a WifiP2pManager.Channel, which is used to connect application to the Wi-Fi P2P framework
channel = manager?.initialize(this, mainLooper, null)
channel?.also { channel ->
receiver = manager?.let { WiFiDirectBroadcastReceiver(it, channel) }
}
setContent {
createButtons()
createAnimatingImages()
val socket = Socket()
var buf = ByteArray(1024)
try {
socket.bind(null)
socket.connect((InetSocketAddress(host, port)), 500)
if (socket.isConnected) {
println("Client Connected to " + host + " at " + port)
}
try {
val outputStream: OutputStream = socket.getOutputStream()
buf = doSomething(...)
outputStream.write(buf)
outputStream.flush()
} catch (e: IOException) {
println("IO Exception")
e.printStackTrace()
}
} catch (e: IOException) {
//catch logic
}
}

Related

UDP listener and broadcast message to main Activity

I have an android app with MainActivity.
I have succesfully deployed a BroadCastReceiver and I can receive messages.
Now I have another class that listens for new UDP messages on specific port. I would like to pass the received messages to my MainActivity so I could update some values here.
For some reason I cannot make BroadCasting from this class.
Here is the code:
MainActivity.kt
#RequiresApi(Build.VERSION_CODES.LOLLIPOP)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//hide top bar
supportActionBar?.hide()
//register broadcastreceiver
registerReceiver(mPlugInReceiver, getIntentFilter())
Log.d(TAG, "Registered broadcastreceiver")
//sending test message to broadcastreceiver, this works
val intent = Intent()
intent.action = "MESSAGE_RECEIVED"
intent.putExtra("MESSAGE_STRING", "sending test message to broadcastreceiver")
sendBroadcast(intent)
//start UDP server
val udpServer = udpServer()
Thread(udpServer).start()
}
udpServer.kt
class udpServer : Runnable {
private val UDP_PORT = 58651
override fun run() {
var run = true
Log.d(MainActivity.TAG, "udpServer started")
while (run) {
try {
val udpSocket = DatagramSocket(UDP_PORT)
val message = ByteArray(8000)
val packet = DatagramPacket(message, message.size)
//Log.i(MainActivity.TAG, "UDP server about to wait to receive")
udpSocket.receive(packet)
val text = String(message, 0, packet.length)
//Log.d(MainActivity.TAG, text)
//This does not work
val intent = Intent()
intent.action = "MESSAGE_RECEIVED"
intent.putExtra("MESSAGE_STRING", "sending test message to broadcastreceiver")
//This throws error: "create function 'sendBroadcast'"
sendBroadcast(intent)
} catch (e: IOException) {
//Log.e(MainActivity.TAG, "error: ", e)
//run = false
}
}
}
}
I tried to use companion object to pass data, but it doesn't work either.

ObjectInputStream readObject unexpectedly closing socket

I want to set up a Server/Client where the client sends a serializable object over a socket to the server. For some reason, I keep getting java.net.SocketException: SocketClosed when I try to read the object sent to the server.
Here is my code for the client:
class Client(address: String, port: Int) {
private val connection: Socket = Socket(address, port)
private var connected: Boolean = true
private val writer = ObjectOutputStream(connection.getOutputStream())
private val reader = ObjectInputStream(connection.getInputStream())
init {
println("Connected to server at $address on port $port")
}
fun run() {
var sent = false
while (connected) {
try {
if (!sent) {
sent = true
writer.use {
it.writeObject("Hello")
it.flush()
}
println("Sent")
} else {
println("Didn't send")
}
Thread.sleep(1000)
} catch (ex: Exception) {
ex.printStackTrace()
shutdown()
}
}
}
...
}
and here is the code for the server:
class ClientHandler(private val client: Socket) {
private val reader = ObjectInputStream(client.getInputStream())
private val writer = ObjectOutputStream(client.getOutputStream())
private var running: Boolean = false
fun run() {
running = true
while (running) {
try {
reader.use {
val packet = it.readObject()
when (packet) {
is String -> {
println("Received packet with data: ${packet}")
}
}
}
} catch (ex: Exception) {
ex.printStackTrace()
shutdown()
}
}
}
...
}
The output on my server is
Server is running on port 9999
Client connected: 127.0.0.1
Received packet with data: Hello
java.net.SocketException: Socket closed
at java.base/java.net.SocketInputStream.socketRead0(Native Method)
at java.base/java.net.SocketInputStream.socketRead(SocketInputStream.java:115)
at java.base/java.net.SocketInputStream.read(SocketInputStream.java:168)
...
So, it seems like one instance of my String is making it across, but later calls claim that the socket is closed.
Every other post I've seen related to this problem claims that the sender (client) is closing the socket early. However, I know that the client is not closing the socket through its own means. If I change my client code to:
class Client(address: String, port: Int) {
...
private val writer = connection.getOutputStream() // Regular streams
private val reader = Scanner(connection.getInputStream())
...
fun run() {
var sent = false
while (connected) {
try {
if (!sent) {
sent = true
writer.write("Hello\n".toByteArray()) // Send regular byte array
println("Sent")
} else {
println("Didn't send")
}
...
}
and my server code to:
class ClientHandler(private val client: Socket) {
private val reader = Scanner(client.getInputStream()) // Regular streams
private val writer = client.getOutputStream()
private var running: Boolean = false
fun run() {
running = true
while (running) {
try {
// Just read lines from stream
println(reader.nextLine())
}
...
}
then my output is what I expect:
Server is running on port 9999
Client connected: 127.0.0.1
Hello
My only hypothesis is that .readObject() is somehow closing the socket connection, forcing the next readObject() to throw an exception. This doesn't make too much sense to me, though. Why would that happen?
Digging around through the code for a bit more gave me the answer I needed. It looks like .use closes the socket after it finishes. Removing the use { } blocks made this work as expected.

How do I multithread my Scala server?

I've been programming a simple client/server application that sends one response back in Scala, and I've been trying to multithread my server using ExecutionContext without any luck.
This is my server code, I think the position of my execute block is causing errors:
import java.net._;
import java.io._;
import scala.concurrent.ExecutionContext
object ServerTwo extends App {
var s1: Socket = null;
var dis: DataInputStream = null;
var s1In: InputStream= null;
var o1out: OutputStream = null;
var odos: DataOutputStream = null
while(true){
def execute(body: =>Unit)=
ExecutionContext.global.execute( new Runnable {def run()= body})
try{
// Open your connection to a server, at port 1234
var s: ServerSocket = new ServerSocket(999)
s1 = s.accept(); // Wait and accept a connection
execute{
s1In = s1.getInputStream()
dis = new DataInputStream(s1In)
var st = new String (dis.readUTF())
//println("Word received is "+st )
st="Received message";
var o1out: OutputStream = null; var odos: DataOutputStream = null
o1out = s1.getOutputStream()
odos = new DataOutputStream (o1out)
// Send the string back
odos.writeUTF(st);
}//end execute
}//end try
catch {
case e: Exception =>
} finally {
// Close the connection, but not the server socket
try{
s1.close()
}
catch{
case e: Exception =>
}
}
}
}

socket connection works well in wireless toolkit but no in my nokia phone

wireless toolkit code
//j2me code for client mobile
public class TCPConnectSend extends MIDlet implements CommandListener {
Display display;
public TCPConnectSend0 () {
frm = new Form ("TCPConnectSend0");
sendCmd = new Command("Send",Command.SCREEN, 1);
frm.addCommand(sendCmd);
frm.setCommandListener(this);
text = new TextField("text:","",40,TextField.ANY);
frm.append(text);
}
public void startApp() {
if(display==null) {
display = Display.getDisplay (this);
}
display.setCurrent(frm);
try {
conn=(SocketConnection)Connector.open("socket://|ip-address|:80");//socket connection to the server
outs=conn.openOutputStream();
} catch(IOException e) { }
}
public void pauseApp() { }
public void destroyApp(boolean unconditional) { }
public void commandAction(Command c, Displayable s) {
if(c==sendCmd) {
try {
outs.write((text.getString()+"\n").getBytes());
} catch(IOException e) {}
} else { }
}
}
server code
//this receives the socket request from client
class TCPServer
{
public static void main(String argv[]) throws Exception
{
try {
ServerSocket server = new ServerSocket(80);
System.out.println("ip address : "+InetAddress.getLocalHost());
System.out.println("waiting for connection");
Socket s1 = server.accept();
System.out.println("connection established");
BufferedReader br = new BufferedReader(new
InputStreamReader(s1.getInputStream()));
while (true) {
String str1 = br.readLine();
System.out.println("client says :" +str1);
if (str1.equals("quit"))
break;
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
//after running this code i m getting a java security exception in my nokia phone any other port no is no responding in the nokia phone
the problem happened because Nokia was blocking the 80 port no for some of its system application so changing of port no along with public ip address did the trick
You should add the public IP of the server in your client code ex.
(SocketConnection)Connection.open( "socket://105.225.251.58" + ":" + "port" );
Note that to use privileged ports like 80, 443, 8080 and generally anything below 1000, you need a code signing certificate(e.g from Thawte) for a real phone.
Otherwise, still to higher un-privileged ports likes 8000 etc

how to receive sms in netbeans mobile application

I am developing a mobile application in net-beans that will send and receive SMS, I'm done with sending text but I don't know how to receive SMS in NetBeans mobile application ?
WMA (Wireless Messaging API) is a wireless messaging api defined in MIDP 2.0. These apis are designed to handle text, binary and multipart messages. To make a connection, the application obtains an object implementing the MessageConnection from the Connector class by providing an URL connection string that identifies the address.
/* Make a connection */
public boolean connectSMSServer()
{
try
{
messageConnection messageConnection =
(MessageConnection)Connector.open("sms://:" + port);
messageConnection.setMessageListener(this);
}
catch (Exception e) {
}
}
/* Send text message */
public void sendTextmessage(String address,String message)
{
try
{
//creates a new TextMessage
TextMessage textMessage = (TextMessage)messageConnection.newMessage(
MessageConnection.TEXT_MESSAGE, address);
textMessage.setPayloadText(message);
messageConnection.send(textMessage);
}
catch (Exception e) {
}
}
/* Recieve text message */
public void receiveTextMessage()
{
try
{
Message message = messageConnection.receive();
if (message instanceof TextMessage)
{
TextMessage textMessage = (TextMessage)message;
}
else
{
//Message can be binary or multipart
}
}
catch (Exception e) {
}
}
/* Notify Incoming Message */
public synchronized void notifyIncomingMessage(MessageConnection conn)
{
//notiy thread of incoming message
synchronized (this)
{
notify();
}
}
/* Close Connection */
public void closeConnection()
{
if (messageConnection != null)
{
try
{
messageConnection.setMessageListener(null);
messageConnection.close();
}
catch (Exception e) {
}
}
}
}
When you are coding for Receiving SMS, you need to listen to one particular port. J2ME Application can not read directly from the inbox.