Multiple threaded socket server in Java - java

I recently tried creating a socket server which can connect to multiple clients... I was too lazy to write a separate program for the client so I'm just using telnet.
The first time I connect(using telnet), it works fine... but the second telnet connection just hangs and the cmd screen goes blank...
Even the first connection gets hanged after sending a string.
Any help is appreciated
Here's the code:
Chatserver.java
I would really appreciate I if someone would correct the mistakes in the code and post it
You could have a look at it if you want but it might be easier if you just clicked the hyperlink and viewed the image:
package chatserver;
import java.io.*;
import java.net.*;
import java.util.logging.Level;
import java.util.logging.Logger;
class Chat extends Thread {
#Override
public void run() {
Chat server = new Chat();
try {
server.SERVER();
} catch (Exception ex) {
Logger.getLogger(Chat.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void SERVER() throws Exception {
ServerSocket SRVSOCK = new ServerSocket(8068);
Socket SOCK = SRVSOCK.accept();
InputStreamReader IR = new InputStreamReader(SOCK.getInputStream());
BufferedReader BR = new BufferedReader(IR);
PrintStream PS = new PrintStream(SOCK.getOutputStream());
PS.println("What is your name: ");
String name = BR.readLine();
String Message = BR.readLine();
PS.println(name + " : " + Message);
}
}
public class ChatServer {
public static void main(String[] args) {
Chat c1 = new Chat();
Chat c2 = new Chat();
while (true) {
c1.start();
c2.start();
}
}
}
Guys,
Today I typed up the same code in python as I am much more familiar with it than I am with Java
I have succeeded in connecting to multiple clients but am unable to see outputs from chat() yet...
I would like to know what mistake I made in this code below and would be very grateful if someone helps me transcribe it to Java:
#!/usr/bin/env python3
import socket
import threading
import time
clients = []
addr = []
HOST = '127.0.0.1'
PORT = 8068
client_no = 0
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
print('Socket bind complete')
def connect(clnt_no):
while True:
s.listen(1)
print('searching for clients')
clnt, adr = s.accept()
clients.append(clnt)
addr.append(adr)
print('connected to: ',addr[clnt_no])
# print(len(clients))
clnt_no += 1
client_no = clnt_no
def chat():
while True:
for x in range(0, client_no):
data = clients[x] = recv(1204)
if data:
for y in range(0, client_no):
clients[y].send('from client ', x, ' ', data)
else:
print('no data recieved from any client')
def Main():
conn = threading.Thread(target=connect, args=[0])
cht = threading.Thread(target=chat)
# while True:
conn.start()
cht.start()
if(__name__ == '__main__'):
Main()
Thanks in advance

Two problems:
First, every instance of Chat is listening on port 8068. You can only have one ServerSocket listening on a particular port, though it is free to accept() multiple connections. If you paid attention to the exceptions you’re getting instead of ignoring them, you would see an exception informing you of this.
Second, since the start() method of Thread returns immediately rather than waiting for the thread to finish, your while loop is creating hundreds, if not thousands, of threads. The only reason your system isn’t overwhelmed by them is because, as I mentioned above, all but the very first instance are immediately failing to bind their ServerSockets, so they return fairly quickly.
In summary, you need to create one server, with one ServerSocket. You will need to call accept() inside a loop, but you must not create more than one ServerSocket.

Related

Client-Server example does not work

I studied the Client-Server chapter of a Java book and I copied the code examples for a easy Client-Server interaction.
The server:
package knowledge;
import java.io.*;
import java.net.*;
public class DateTimeServer {
public static void main(String[] args) {
try {
int port = Integer.parseInt(args[0]);
ServerSocket server = new ServerSocket(port);
System.out.println("DateTimeServer laeuft");
Socket s = server.accept();
new DateTimeProtokoll(s).transact();
} catch (ArrayIndexOutOfBoundsException ae) {
System.out.println("Aufruf: java DateTimeServer <Port-Nr>");
} catch (IOException e) {
e.printStackTrace();
}
}
}
Protocol:
package knowledge;
import java.io.*;
import java.net.*;
import java.util.*;
import java.text.*;
public class DateTimeProtokoll {
static SimpleDateFormat time = new SimpleDateFormat(
"´Es ist gerade´H´.´mm´ Uhr.´");
static SimpleDateFormat date = new SimpleDateFormat(
"´Heute ist´EEEE´, der ´dd.MM.yy´");
Socket s;
BufferedReader vomClient;
PrintWriter zumClient;
public DateTimeProtokoll(Socket s) {
try {
this.s = s;
vomClient = new BufferedReader(new InputStreamReader(
s.getInputStream()));
zumClient = new PrintWriter(s.getOutputStream(), true);
} catch (IOException e) {
System.out.println("IO-Error");
e.printStackTrace();
}
}
public void transact() {
System.out.println("Protokoll gestartet");
try {
zumClient.println("Geben Sie DATE oder TIME ein");
String wunsch = vomClient.readLine();
Date jetzt = new Date();
if (wunsch.equalsIgnoreCase("date"))
zumClient.print(date.format(jetzt));
else if (wunsch.equalsIgnoreCase("time"))
zumClient.println(time.format(jetzt));
else
zumClient.println(wunsch + "ist als Kommando unzulaessig!");
s.close();
} catch (IOException e) {
System.out.println("IO-Error");
}
System.out.println("Protokoll beendet");
}
}
The Client:
package knowledge;
import java.net.*;
import java.io.*;
public class DateTimeClient {
public static void main(String[] args) {
String hostName="";
int port;
Socket c=null;
try{
hostName=args[0];
port= Integer.parseInt(args[1]);
c=new Socket(hostName,port);
BufferedReader vomServer=new BufferedReader(
new InputStreamReader(c.getInputStream()));
PrintWriter zumServer=new PrintWriter(c.getOutputStream(),true);
BufferedReader vonTastatur=new BufferedReader(
new InputStreamReader(System.in));
System.out.println("Server "+ hostName+":"+port+ "sagt:");
String text=vomServer.readLine();
System.out.println(text);
text=vonTastatur.readLine();
zumServer.println(text);
text=vomServer.readLine();
System.out.println(text);
c.close();
}
catch(ArrayIndexOutOfBoundsException ae){
System.out.println("Aufruf:");
System.out.println("java DateTimeClient <HostName><PortNr>");
}
catch(UnknownHostException ue){
System.out.println("Kein DNS-Eintrag fuer: "+hostName);
}
catch(IOException e){
System.out.println("IO-Error");
}
}
}
Here are some notes of my approach and my beliefs. Please disagree on wrong statements stated below:
1)I believe it is no problem to run Client as well as Server on the same (my) computer.
2)I use Eclipse, so I run Eclipse two times in two different workspaces.
3)My input for server program is (run configuration->arguments): 2222
4)My input for the client program is: 2223 my_ip
(my_ip is for example 127.0.0.1 I choosed to write my_ip instead because I am not sure if it is dangerous to reaveal my ip in public)
4b) also: "2223" "my_ip"
4c) and: {"2223","my_ip"}
5) also 2222 my_ip
(although the figure in my book suggests that the port numbers of client and server should be different, but you never know)
Also I get this very often this error message:
Address already in use sounds like client and server port numbers should be different. But I dont know and thats why I ask. Thank you for your help
(The page did not like my code so I took screenshots :/)
I replaced the images with code. Sorry for the inconvenience.
Restarting first the server with input 2222 and then the client with input 127.0.0.1 2222. After a while the client posts "IO-Error". Its the exception from the clien class (not from protocol class) right? Why is the exception triggered? Is the code working for someone? Thank you
1) Correct. Client and server can be on the same computer, no problem there.
2) Not required, but ok.
3) This will make the server listen on port 2222
4) 127.0.0.1 is just another way of saying "this computer". It is the same as "localhost". Your actual ip is irrelevant to the question anyway, 127.0.0.1 will suffice.
5) Your server is asking on which port to listen (the SOURCE port), your client is asking to which port to connect to (the TARGET port of the client). Of course that should be the SAME port, otherwise the client will try to send a message to port X while the server will listen on port Y.
Imagine the ip as a house address, for example "Mainstreet 12, MyCity". The port would be the appartment number then. Your server occupies appartment 2222, so of course the client needs to try to connect to appartment 2222, otherwise it will not reach any server.
The error is most likely just because you don't actually stop your old server program. Stop it (big red button in eclipse), otherwise it will "occupy" the given port (which will prevent any other program from listing at that port, thus you cannot have two servers running which are both listening on the same port). If we reuse my crude analogy: An appartment cannot contain two servers at the same time, so if one is already in appartment 2222, a second one trying to live there will fail.
I don't know exactly why, but usually server binds host as 127.0.0.1 or localhost or your IP like 192.168.1.100 but if one of that are not listed, than it might be failed to call. See more with netstat.exe on Windows.
The "Address already in use" exception is only because the last Java session still running, could not terminate for some reason, and if you use IDE like Eclipse, it will often happen. :)
Make sure that all java thread is terminated (with task manager in Windows). Note that Eclipse is a Java thread too! You would better run the server in console mode..
In real world, native sockets are rarely used, because there some higher level protocol and technology like HTTP, SOAP, WebService, microService, SOA etc. If native socket is not necessary, for example you communicate with microcontroller, you should use these technologies, because these are more robust and others can easily communicate with your interface.

Java - ServerSocket accept() method repeating in while(true) loop

Hopefully someone can shed some light on this one, and provide a workaround, or illuminate some method I'm missing here.
Just messing around trying to create a really simple web server.
So far I have:
public class SocketTest {
public static void main(String[] args) throws IOException {
ServerSocket sock = new ServerSocket(9876);
while(true) {
System.out.println("Before");
Socket conn = sock.accept();
System.out.println("After");
conn.close();
}
}
}
Then, once the project is running, the output window displays:
Before
Which is what I expect, but then as soon as I type:
127.0.0.1:9876
Into a web browser, I end up with:
Before
After
Before
After
Before
After
Before
Showing. So the browser is obviously connecting to that port multiple times, but only the first connection contains any info in its page header.
While writing this, I've decided to go a little further with my experimentation's, and come up with:
public class SocketTest {
public static void main(String[] args) throws IOException {
ServerSocket sock = new ServerSocket(9876);
while(true) {
System.out.println("Before");
Socket conn = sock.accept();
System.out.println("After");
Scanner sc = new Scanner(conn.getInputStream());
System.out.println("BEFORE if...");
if (sc.hasNext()) {
System.out.println("INSIDE if...");
String[] cnr = sc.nextLine().split("\\s+");
System.out.println("Command: " + cnr[0] + " - URL: " + cnr[1]);
} else {
System.out.println("INSIDE ELSE!");
}
System.out.println("Closing...");
conn.close();
System.out.println("Closed!");
}
}
}
If you compile and run this code, you'll notice that upon first opening a page on the socket, you get the repeated socket opening, but it also appears to hang for about 10 seconds at the line:
if (sc.hasNext()) {
As though it's watching the InputStream() for a set period of time, to see if it contains any information or not..?
Also, if I send two actual pages in quick succession (or just refresh the page), it goes through immediately.
Can anyone shed some light on this?
Either how I can remove the waiting on an InputStream() that's never going to materialise, or how I can get it to ignore the phantom sockets.
Even a bit of background as to what's causing the anomaly would be great!
The accepting thread should never wait on socket's input, it should delegate data exchange to a separate thread and immediately return to execution of ServerSocket.accept() like it is described at the end of this example. For highly loaded servers (thousands of simultaneous connections), that threads can consume too much memory, so asynchronous IO can be used.

Using sockets with PHP and Java

I attempted to create a PHP script which determines if the server (the computer which hosts the java program listed below) is running or not, If it is, the php funciton should return true, if not it returns false.
Here is the server:
package darestium.minecraft.server;
import java.io.BufferedReader;
import java.net.*;
import java.io.*;
public class Server {
private static ServerSocket socket;
private static Socket connection;
private static String command = new String();
private static String responseStr = new String();;
private static int port = 4343;
public static void main(String args[]) {
System.out.println("Signal Server is running.");
try {
socket = new ServerSocket(port);
while (true) {
connection = socket.accept();
InputStreamReader inputStream = new InputStreamReader(connection.getInputStream());
DataOutputStream response = new DataOutputStream(connection.getOutputStream());
BufferedReader input = new BufferedReader(inputStream);
command = input.readLine();
response.writeBytes(responseStr);
response.flush();
//response.close();
System.out.println("Running");
}
} catch (IOException e) {
System.out.println("Fail!: " + e.toString());
}
System.out.println("Closing...");
}
}
And here is the client:
<?
function isRunning() {
$address = 'darestium.dyndns-free.com';
$port = 4343;
$socket = socket_create(AF_INET, SOCK_STREAM, getprotobyname('tcp'));
$message = 'loolololol';
try {
socket_connect($socket, $address, $port);
$status = socket_sendto($socket, $message, strlen($message), MSG_EOF, $address, $port);
if ($status != false) {
return true;
}
return false;
} catch (Exception $e) {
return false;
}
}
?>
The following are the error messages that show up on the php page that echos out the result of the function like so:
include('server.php');
echo isRunning();
Then the error messages:
Warning: socket_connect() [function.socket-connect]: unable to connect [0]: No connection could be made because the target machine actively refused it. in C:\Users\darestium\Documents\Portables\xampp\htdocs\darestium\minecraftserver.php on line 9
Notice: Use of undefined constant MSG_EOF - assumed 'MSG_EOF' in C:\Users\darestium\Documents\Portables\xampp\htdocs\darestium\minecraftserver.php on line 11
Warning: socket_sendto() expects parameter 4 to be long, string given in C:\Users\darestium\Documents\Portables\xampp\htdocs\darestium\minecraftserver.php on line 11
I was wondering how I could fix this issue. Also, I would like to be able to send messages to the server, any ideas how I could do this? I am basing this off Simple Java TCP Server and PHP Client Problems
Note: that I am very new to Sockets, and Server/Client communication.
Edit:
#VideanuAdrian OK, just port forwarded the port 4343 and it no longer shows up with the first error, but the function always seems to return false, and the last two errors still show.
You should not close the DataOutputStream object in your server.
Just comment the line response.close(); in your server and the program should work.
When running a Client/Server you need to know if the user that runs the app has access to the port. Ports to 1024 are reserved by the system know apps/services. That´s point 1.
Point 2: One of the best ways is to run the server inside a connection-thread approach. Running in this way, when a new client request arrives, the server can delegate the request handle to the connection thread.
Point 3: The message is related to the protocol. If you are using a built protocol like HTTP or FTP, you must use the protocol rules. If not, you could built your own rules for the message request/response.
I recomend you to read the Java Networking Tutorial before continue. Run all Java examples. Later, you could mix with PHP. The more information about sockets and protocols you have, the better your programm will be.
http://docs.oracle.com/javase/tutorial/networking/
Hope this can help you.

Scala socket cannot write to output stream

I'm new in the scala world, so excuse my trivial question. :) I just want to open a socket to a port and sand and receive messages.
If I receive a HELO, I want to react with a message, but I'm not able to write to the socket in any way.
I used nc to listen for incoming connections:
nc -k -l 127.0.0.1 3333
When the client is connected I write
HELO
in the netcat, but the client sends no answer.
Here is my scala code:
package hello
import java.io._
import java.net.{ InetAddress, ServerSocket, Socket, SocketException }
import java.util.Random
import scala.actors.Actor
import scala.actors.Actor._
object HelloWorld extends {
def main(args: Array[String]) {}
val ia = InetAddress.getByName("localhost");
val socket = new Socket(ia, 3333)
val out = new ObjectOutputStream(
new DataOutputStream(this.socket.getOutputStream))
val in = new DataInputStream(socket.getInputStream())
println("Starting client");
var i = 0;
/* The actor!
*
*/
val myActor = actor {
loop {
receive {
case s: String => {
if (s.startsWith("HELO")) {
println("DEBUG: RECEIVED HELO=>SENDING AUTH!")
this.out.writeUTF("HALLO")
this.out.flush();
} else {
println("received:" + s);
}
}
case _ => println("I have no idea what I just got.")
}
}
}
/*
* Testing the actor!
*
*/
myActor ! "foobar";
while (!socket.isConnected()) {
println("Not connected waiting")
Thread.sleep(5000);
}
if (socket.isConnected()) {
println("connected");
}
try {
while (true) {
i += 1;
val x = in.readLine()
myActor ! x;
Thread.sleep(500);
}
} catch {
case e: IOException =>
e.printStackTrace()
}
}
The receiving works just fine, and the actor reacts on the incoming message, but the write is never done. Am I just oversee something, or is my code wrong for sending to an outputSteam.
Heres my output from the console window:
Starting client
connected
received:foobar
DEBUG: RECEIVED HELO=>SENDING AUTH!
If this code is truly the code you are using, it has a serious problem: it is using threads from inside a static initializer.
Here:
object HelloWorld extends {
Extends what?
def main(args: Array[String]) {}
No main method, so everything else is inside the constructor to object HelloWorld. Basically, that means everything using threads (including actors) is unreliable. Put this stuff inside the main method.
I'm not familiar with netcat, but is it possible that it's just not printing the "HALLO" response because it's encoded in a way that netcat can't make sense of (i.e. Java's serialization format)? Does it work if you don't wrap the output stream in an ObjectOutputStream?

Java threads doubt

I had earlier posted a query on Java threads. ( link text)
And based on the answers i received, i decided to implement them. So ive done this bit of coding on a machine with 2 cpu cores. The code is as follows
import java.net.*;
import java.io.*;
public class thready implements Runnable{
private Socket num;
public thready(Socket a) {
this.num=a;
}
public void run() {
try {
BufferedInputStream is = new BufferedInputStream(num.getInputStream());
System.out.println("Connected to port"+num);
} catch (IOException ex) {
//Logger.getLogger(thready.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static void main(String [] args)
{
int port = 80;
int port1= 81;
//int count = 0;
try{
ServerSocket socket1 = new ServerSocket(port);
ServerSocket socket2 = new ServerSocket(port1);
while (true) {
Socket connection = socket1.accept();
Socket connection1 = socket2.accept();
Runnable runnable =new thready(connection);
Runnable run= new thready(connection1);
Thread t1=new Thread(runnable);
Thread t2=new Thread(run);
t1.start();
t2.start();
}
}
catch(Exception e)
{
} }}
Now Im testing this piece of code using Hyperterminal and am connecting to both port 890 and port 81(am using 2 instances of the hyperterminal) and as i understand it the expected behavior should be that "Connected to port 'port number'" should be printed as soon as a connection to any port( 80 or 81) is made. But the output that im getting here from this piece of code is that if i connect to only 1 port then the required output is not getting printed and if i connect to both ports, one after the other, the output is printed only after both ports are connected. So this again leads me to the initial confusion as to whether both these threads are executing concurrently or the execution is alternating between these 2 threads.
Any suggestions would be of great help.
Cheers
You're calling accept before starting the threads. accept will block until a connection is made, so that's why you're seeing the behavior you do. If you want to listen on multiple ports, you will need to[1] create a thread for each ServerSocket and then either start a communication thread when the accept returns or process the connections one by one in the thread doing the listening.
[1] This applies only if you are using ServerSocket directly, which you probably should be using while learning. The java.nio package and its subpackages contain classes for use with multiplexing non-blocking I/O that can be used to, e.g., listen on multiple sockets in the same thread.
You're doing a lot of initialisation before kicking off your threads and blocking there.
I would move all that code into the runnable. Then you would also avoid these duplicated variables names such as connection and connection1, have those objects owned by Thready.
The code
Socket connection = socket1.t();
Socket connection1 = socket2.accept();
uses Socket.accept which is a blocking method. See the javadoc:
Listens for a connection to be made to
this socket and accepts it. The method
blocks until a connection is made.
You have these 2 lines
Socket connection = socket1.accept();
Socket connection1 = socket2.accept();
Now, .accept() blocks until a connection is made.
So that means when your code waits on the 2. line above. You'll never get around to start the thread for 'connection' until the 2. connection is made.
I tweaked the code a bit as per the suggestions and got it running, I guess.
Here is the modified constructor and run method
public thready(int a) {
this.num=a;
}
public void run() {
try {
ServerSocket socket1 = new ServerSocket(num);
while(true){
Socket connection = socket1.accept();
BufferedInputStream is = new BufferedInputStream(connection.getInputStream());
System.out.println("Connected to port"+num);
}
} catch (IOException ex) {
//Logger.getLogger(thready.class.getName()).log(Level.SEVERE, null, ex);
}
}
This does(I guess) implement concurrent threads. Thank you all for your suggestions.

Categories

Resources