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 =>
}
}
}
}
Related
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.
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.
It seems like the server is not receiving the message sent from the client as it should. From my understanding the client is writing to the socket outputstream. And the server is reading from the socket inputstream. Please help.
Server Code:
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPServer {
static final int DEFAULT_PORTNUMBER = 1236;
public static void main(String[] args){
int portnumber;
if(args.length >= 1){
portnumber = Integer.parseInt(args[0]);
}else{
portnumber = DEFAULT_PORTNUMBER;
}
//Setting a server socket and a possible client socket
ServerSocket server = null;
Socket client;
try{
server = new ServerSocket(portnumber);
} catch (IOException e){
e.printStackTrace();
}
while(true){
try{
System.out.println("Waiting for client...");
client = server.accept();
System.out.println("Client accepted... ");
//Read data form the client
BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
while(!br.ready()){
System.out.println("No message from client");
}
String msgFromClient = br.readLine();
//System.out.println("Message received from client = " + msgFromClient);
//Send Response
if(msgFromClient != null && !msgFromClient.equalsIgnoreCase("bye")){
OutputStream clientOut = client.getOutputStream();
PrintWriter pw = new PrintWriter(clientOut, true);
String ansMsg = "Hello, " + msgFromClient;
pw.println(ansMsg);
}
if(msgFromClient != null && msgFromClient.equalsIgnoreCase("Bye")){
server.close();
client.close();
break;
}
} catch(IOException e) {
e.printStackTrace();
}
//New thread for client
/*new ServerThread(client).start();
System.out.println("Client connection accepted... ");*/
}
}
}
Client Code:
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
public class TCPClient {
static final int DEFAULT_PORTNUMBER = 1236;
public static void main(String args[]){
Socket client = null;
int portnumber;
//Default port number if not specified as an argument
if(args.length >= 1){
portnumber = Integer.parseInt(args[0]);
}else{
portnumber = DEFAULT_PORTNUMBER;
}
try {
String msg = "";
//Creating a client socket
client = new Socket(InetAddress.getLocalHost(), portnumber);
System.out.println("Client socket is created: " + client);
//Creating an output stream for the client socket
OutputStream clientOUt = client.getOutputStream();
PrintWriter pw = new PrintWriter(clientOUt, true);
//Creating an input stream for the client socket
InputStream clientIn = client.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(clientIn));
//Creating a buffered reader for standard input System.in
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter your name. Type Bye to exit.");
//Read data from standard input and write to output stream
msg = stdIn.readLine().trim();
pw.print(msg);
while(!br.ready()){
//System.out.println("No Input From Server");
}
//Read data from input stream of client socket
System.out.println("Message returned from the server = " + br.readLine());
pw.close();
br.close();
client.close();
//Stop operation
if (msg.equalsIgnoreCase("Bye")) {
System.exit(0);
} else {
}
} catch (IOException e) {
System.out.println("I/O error " + e);
}
}
}
Note: I did disable firewall but that did not help.
Found the answer PrintWriter or any other output stream in Java do not know "\r\n". It describes how printwriter doesn't flush properly with printwriter.print() but rather only works when you use printwriter.println().
server.java
import java.net.*;
import java.io.*;
public class server {
public static void main(String args[]) throws Exception {
ServerSocket server = null;
Socket client = null;
PrintStream out = null;
BufferedReader buf = null;
server = new ServerSocket(8000);
client = server.accept();
buf = new BufferedReader(
new InputStreamReader(client
.getInputStream()));
out = new PrintStream(
client.getOutputStream());
String str = buf.readLine();
out.println("Echo:"+str);
System.out.println("HELLO"+str);
out.close();
client.close();
}
};
client.lua
local socket = require("socket")
local host = "127.0.0.1"
local port = 8000
local sock = assert(socket.connect(host, port))
sock:settimeout(0)
print("Press enter after input something:")
local input, recvt, sendt, status
input = io.read()
if #input > 0 then
assert(sock:send(input .. "\n"))
end
recvt, sendt, status = socket.select({sock}, nil, 1)
local response, receive_status = sock:receive()
print(response)
The server can get the messages from the client, but the client can't get the reply.
I can get the reply with other languages like Python or Java.
But I can only get the reply with Lua by the message sent by Lua.
Why can't I get reply from the server?
you must change settimeout(0) to settimeout(10) and test again and
remove this line recvt, sendt, status = socket.select({sock}, nil, 1)
I have my socket closed or reset by peer after a while,I think garbage collection problem through its reader or writer.
Asynctask for handling responses:
#Override
protected Void doInBackground(Void... params) {
//Log.e("NEW LISTENER THREAD NAME", name);
//initializations
try{
clientSocket = new Socket();
//clientSocket.setTcpNoDelay(true);
clientSocket.connect(new InetSocketAddress(serverURL, dataServerPort));
requestSender = new PrintWriter(new PrintStream(clientSocket.getOutputStream(), true,"UTF-8"));
Sender.Init();
}catch(Exception e){
e.printStackTrace();
}
gsonObj = new GsonBuilder().create();//This the object that handels every comming response
finish = false;
try{
listener = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
}catch (IOException e) {
Log.e("FROM CREATING LISTENER", "FROM CREATING LISTENER ========> ");
e.printStackTrace();
}
LOGGED_IN = StaticArea.getLoggedIn(cnt);
if(LOGGED_IN){
USER = StaticArea.getUserName(cnt);
Sender.ResumeUser();
/*********DELEGATING CONNECTING TO SERVER TO BE USED IN SERVICE*************/
Message connectionMsg = new Message();
connectionMsg.obj = Boolean.valueOf(true);
serviceHandler.handleMessage(connectionMsg);
/*********END DELEGATING CONNECTING TO SERVER*************/
}else{
/*********DELEGATING CONNECTING TO SERVER TO BE USED IN SERVICE*************/
Message connectionMsg = new Message();
connectionMsg.obj = Boolean.valueOf(false);
serviceHandler.handleMessage(connectionMsg);
/*********END DELEGATING CONNECTING TO SERVER*************/
}
GoOnline();
while(!finish){
try{
answerS = listener.readLine();
if(answerS != null )//to avoid any null response
if(answerS.contains(Response.MYRESPONSE){
if(MyService.theHandler != null){
Message msg = new Message();
msg.obj = answerS;
MyService.theHandler.sendMessage(msg);
The Sender class is class that has a static methods and uses my sockets output:
public class Sender {
private static Gson gsonObj;
public static void Init() {
gsonObj = new GsonBuilder().create();
}
public static void SendTestRequest(){
try{
Request req = new Request();
req.setR_TYPE(Request.TEST);
String reqString = gsonObj.toJson(req);
requestSender.println(reqString);
requestSender.flush();
}catch(Exception e){
}
}//end method