EDIT: The code below throws no exception but has no output and hangs. It should output "Test message". In main(), we start a thread that's given a server socket listening on a random port. The main thread the tries to connect and communicate with the ServerSocket on that same random port, but is apparently failing. Why?
public class IntraProcSockTest {
private static int port;
private class Listener extends Thread {
public Listener() {
}
public void run() {
try {
ServerSocket serverSocket = new ServerSocket(0);
port = serverSocket.getLocalPort();
Socket socket = serverSocket.accept();
BufferedReader in;
String fromClient;
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
while ((fromClient = in.readLine()) != null) {
System.out.println("From client: " + fromClient);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public IntraProcSockTest() {
new Listener().start();
}
public static void main(String[] args) {
new IntraProcSockTest();
try {
Thread.sleep(5000);
Socket socket = new Socket("localhost", port);
PrintWriter socketOut = new PrintWriter(socket.getOutputStream());
socketOut.println("Test message");
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
A process can connect to a socket created by itself, there is no problem. Show us the code that throws an exception and/or more details about the exception.
First of all, be careful not to specify a local port for the client socket (the one connecting to the other which is listening). Let the OS choose a random port. Remember that any socket is identified by four elements (remote host, local host, remote port, local port), if you bind both the server socket and the client socket on the same local port, let it be 4498, both sockets are defined as follows: (localhost, localhost, 4498, 4498) and this doesn't work. I suspect this might be your problem.
To avoid such problems, client sockets are often bound to a random port, chosen by the OS. Show us your code, expecially the part in which the client sockets gets created and connects to the server socket.
And about IPC, it is not always bad to use sockets as an inter-process or even intra-process communication technique. The performance is worse, obviously, and you might loose some code readability, but your software will be easily portable to a network (distributed) application. It's up to your plans, it's not like IPC sockets == bad.
To create a Socket connection in one thread you can.
ServerSocket ss = new ServerSocket(0); // open a random free port.
Socket c = new Socket(ss.getInetAddress(), ss.getLocalPort());
Socket s = ss.accept();
ss.close();
final byte[] bytes = "Hello World!".getBytes();
final OutputStream out = c.getOutputStream();
out.write(bytes.length);
out.write(bytes);
final DataInputStream in = new DataInputStream(s.getInputStream());
int len = in.read();
final byte[] b = new byte[len];
in.readFully(b);
System.out.println(new String(b));
c.close();
s.close();
If all you want is IPC within a Process, a socket is not the fastest or simplest way to go. Try using a Pipe (NIO) or PipeInput/OutputStream (IO). Its faster and simpler.
Pipe pipe = Pipe.open();
SinkChannel sink = pipe.sink();
SourceChannel source = pipe.source();
or
PipedOutputStream output = new PipedOutputStream();
PipedInputStream input = new PipedOutputStream(output);
BTW: You can connect a client and server Socket in the same thread, however
Using an Exchanger is 10x faster, and using a ring buffer is faster again.
If you want convenience, using an ExecutorService is the best way to deleagte work to a background pool of threads. This can still perform millions of tasks per second.
Related
Am I doing this right? When I try to run this on my computers loopback address I'm getting a "connection reset" error.
public class DateTimeClient {
public static void main(String[] args) throws IOException {
int port = Integer.parseInt(args[0]);
String host = args[1];
try {
System.out.println("Connecting....\n");
Socket socket = new Socket(host, port);
PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
BufferedReader reader = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
System.out.println("Date: " + reader.read());
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class DateTimeServer {
public static void main(String[] args) {
int portNum = Integer.parseInt(args[0]);
try {
ServerSocket socket = new ServerSocket(portNum);
Socket client = socket.accept();
BufferedReader reader = new BufferedReader(new InputStreamReader(
client.getInputStream()));
PrintWriter writer = new PrintWriter(client.getOutputStream());
Date date = new Date();
writer.print(date.toString());
} catch(Exception e) {
e.printStackTrace();
}
}
}
I grab the port to run the server on, the port to connect to and the host as arguments in the main method, create sockets and use BufferedReader and PrintWriter. I followed Oracle's tutorial on this pretty closely so I'm not sure where I coulda made a mistake.
#EJP is correct, but I think that the actual problem is that the server side is neither closing or flushing writer. When the server exits, the TCP/IP connection gets closed (by the server-side OS) without any data having been written to the socket. The client side JVM sees a reset connection and throws an exception.
Solution: Close your streams properly on the server side and the client side should see the data. (Flushing would work too ... but if you neglect to close the streams in all cases, you risk problems with server-side file descriptor leaks. Hence, closing is the best solution.)
You're only reading one character, not a date. Try sending and receiving a line.
I'm learning about java sockets in a class of mine. I'm having issues with the communication between the peers. My question is why am I receiving this exception:
Exception java.net.ConnectionException: Connection refused: connect
for example:
in my main thread
ServerSocket listenSock = new ServerSocket(Integer.parseInt(argv[2]),0,InetAddress,getByName(null));
//Create Server loop to process inbound connections
while(true){
//accept an incoming client by saving it to a socket to use to communicate with it
Socket clientSock = listenSock.accept();
/waa/create a thread to handle the inbound client so that we can return to accept()
InboundHandler inboundMsg = new InboundHandler(clientSock); // listens to the peers outbound socket
Thread inThread = new Thread(inboundMsg);
inThread.start();
// add the peer to the list.
}
in a seperate thread I have a
public InboundHandler(Socket socket) throws Exception{
this.socket = socket; //save the socket object to "this" instance of the class
input = new BufferedReader(new InputStreamReader(socket.getInputStream())); // listens from the clients speaking socket
}
public void run(){
while(true){
try{
String line = input.readLine();
System.out.println(line);
}catch(IOException e){
System.out.println("Could not read input. " + e);
}
}
and finally I have a thread that sends out messages
for(int i=0;i<portList.size(); i++){
if(nameList.get(i)!=Username){
Socket peerSocket= new Socket(InetAddress.getByName(null),portList.get(i));
writer = new BufferedWriter(new OutputStreamWriter(peerSocket.getOutputStream()));
writer.write(Username + " has connected");
writer.flush();
}
}
}
catch(IOException e){
System.out.println("Some IO problem. " + e);
}
My program compiles, and when I run it, I receive the Exception
java.net.ConnectionException: Connection refused: connect
From what it's sounding like, is the port that my one peer is trying to speak to, isn't being heard by the other peers. But this is more guessing
As for the while(true) I am going to change that later, with a boolean statement.
I'm trying to implement a simple server(java application) and client(android app), where the client sends a string about 10 times a second. Everything works fine for a minute or so, after which the server stops receiving messages from the client. Relevant code below.
ClientThread.java
public class ClientThread implements Runnable{
static Socket socket;
static String message = "";
InetAddress serverAddr;
BufferedOutputStream bos;
public ClientThread(String message){
ClientThread.message = message;
}
#Override
public void run() {
try{
serverAddr = InetAddress.getByName(SERVER_IP);
if(socket != null && socket.isConnected())socket.close();
socket = new Socket(serverAddr, SERVER_PORT);
bos = new BufferedOutputStream (socket.getOutputStream());
OutputStreamWriter osw = new OutputStreamWriter(bos, "US-ASCII");
osw.write(message);
osw.flush();
socket.shutdownOutput();
socket.close();
}catch (Exception e) {
}
}
}
ServerThread.java
public class ServerThread extends Thread{
private ServerSocket serverSocket;
static String clientSentence;
public ServerThread(int port) throws IOException, AWTException{
serverSocket = new ServerSocket(port);
}
public void run() {
while(true){
try{
Socket server = serverSocket.accept();
BufferedReader d = new BufferedReader(new InputStreamReader(server.getInputStream()));
clientSentence = d.readLine();
System.out.println(clientSentence);
server.close();
}catch(IOException e){
e.printStackTrace();
break;
}
}
}
}
ClientThread.java is called about 10 times a second using:
Thread clientThread = new Thread(new ClientThread(message));
clientThread.start();
ServerThread.java is initialized and started using:
t = new ServerThread(8888);
t.start();
Any thoughts on why this would freeze after running for a bit? The only way to fix it is to restart the server, after which the same problem happens again after a minute. I spent a lot of time researching this issue but was unable to find a solution.
EDIT: I figured out the server freezes at the clientSentence = d.readLine(); part. Any idea why?
60 connection per second, one minute running: 3600 connections per minute.
Closing a socket doesn't release immediately the associated file descriptor. You may run out of resource at OS layer.
Try to run netstat on server side to see the active, pending and closed connections.
You may read this post on SU.
Your thread never exits and you keep creating new ones. So you run out of something: thread space, sockets, FDs, ...
This is all wrong. Either your thread should loop or you should create a new one. Not both.
Also:
You should use a single connection, not a new one per message.
You are reading lines but to sending them, unless the data already contains a newline, which it shouldn't.
There's a million examples on using Java sockets out there - and every one is the same!
Every one shows a client socket being created, some text being sent, and the socket closed.
I am writing some test code. I want my client to loop round and send quite a few messages. It seems silly to close the client socket each time and re-create, so I thought I would just create one client socket, loop round and send data on the same socket. The thing is though - my server socket does not print out what it has received until the last message has been sent by the client and the client socket closed.
Server:
Socket sock;
ClientConnection client;
ServerSocket ss = new ServerSocket(portNumber);
ss.setSoTimeout(0); // 0=infinite
while (true) {
sock = ss.accept();
client = new ClientConnection(sock);
new Thread(client).start();
// ClientConnection reads from sock, prints, and closes sock
}
ClientConnection (a separate class on the Server side):
public class ClientConnection implements Runnable
{
private Socket m_socket;
private BufferedReader m_in = null;
public ClientConnection(Socket socket)
{
m_socket = socket;
try {
InputStream inStream = socket.getInputStream();
m_in = new BufferedReader(new InputStreamReader(inStream));
}
catch (IOException ioe) {
ioe.printStackTrace();
}
}
public String getMessage()
{
String line = null;
StringBuffer completeMessage = new StringBuffer();
try {
while ((line = m_in.readLine()) != null)
{
completeMessage.append(line);
}
}
catch (IOException ioe) {
ioe.printStackTrace();
return "";
}
return completeMessage.toString();
}
public void run()
{
try {
String message = getMessage();
System.out.println("Received: " +message);
}
finally
{
try {
m_socket.close();
}
catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
}
Client:
socket = new java.net.Socket(m_destination, m_portNumber);
outputStream = socket.getOutputStream();
printStream = new java.io.PrintStream(outputStream);
while (more-stuff-to-send)
{
printStream.print(text);
printStream.print("\n");
printStream.flush();
}
prinStream.close();
socket.close();
ClientConnection is created by the server when I start the client, but it does not print what has been sent until the client is done sending.
I feel like I'm missing the point somewhere along the line. Chat examples are quite common, so if I had a chat client then every message it wanted to send to a chat server it would create a client socket, send the message, and close the socket? Just doesn't seem right somehow.
Thank you.
client = new ClientConnection(sock);
You are passing the socket in constructor.
so you shouldn't do:
socket = new java.net.Socket(m_destination, m_portNumber);
just cache that vatiable from contructor as : this.sock = sock;
getting the reader and the writer is ok, also the server is ok.
I would use a Vector to be synchromized queue for sending messages, and the while (more-stuff-to-send) loop would check the queue and id empty than sleep, if has something to send, than pop the first and sent it while he must do stuff, or socket is closed my the client.
I'm new to java and i'm trying to learn how to use sockets.
I'm trying to write a simple text messenger, server - client, but i don't know how to make the server always listening for client's stream:
Here's the server code, by now it just manages 1 incoming connection, when the client connects, the server send a message to it:
import java.net.*;
import java.io.*;
public class SocketServer {
private InetAddress ServerAddress;
private int ServerPort;
private int ServerQueue;
private ServerSocket Server;
public SocketServer(String ServerAddress, int ServerPort, int ServerQueue)
{
try
{
this.ServerAddress = InetAddress.getByName(ServerAddress);
}
catch (UnknownHostException uhe)
{
uhe.printStackTrace();
}
this.ServerPort = ServerPort;
}
public boolean ServerCreate()
{
try
{
Server = new ServerSocket(this.ServerPort, 10, this.ServerAddress);
System.out.println("System Message: Server started!");
return true;
}
catch(IOException ioe)
{
ioe.printStackTrace();
System.out.println("System Message: Can't start server!");
return false;
}
}
public void ServerStartListening()
{
int exit = -1;
while(exit < 1)
{
try
{
Socket client = this.Server.accept();
OutputStream clientout = client.getOutputStream();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(clientout));
bw.write("Welcome: "+client.toString());
bw.close();
}
catch (IOException ex)
{
ex.printStackTrace();
}
}
}
}
Sorry for my bad english.
You need to implement multi-threading in order to listen for multiple incoming requests. Refer this link: a very nice multi-threaded server example by oracle
You need to read sth. about threads. Here is an initial code:
ServerSocket socketListener;
DoSthWithThisSocket doSthWithThisSocketObj;
socketListener = new ServerSocket(LISTENINGPORT);
Socket socket;
Thread doSthWithThisSocketThread;
while (continueSocketListening()) {
socket = socketListener.accept();
doSthWithThisSocketObj = new DoSthWithThisSocket(socket);
doSthWithThisSocketThread = new Thread(doSthWithThisSocketObj);
doSthWithThisSocketThread.start();
}
There are two main options for doing multi-client socket servers in Java:
Start a new thread for each new client TCP connection as previous responders suggest. This is OK for smallish/toy servers, and when you are just starting playing with sockets. The big downside here is that this approach does not scale - just think about having a thousand concurrent clients ...
Use IO multiplexing with non-blocking sockets as provided by Java NIO package, dispatching accept/read/write events to registered callbacks. You can extend this with work-item queue(s) and a pool of pre-allocated worker threads to take advantage of multiple cores/CPUs in your hardware.