Hot questions for Using Transmission Control Protocol in server

Question:

I am trying to run this code using smack 4.1.0

 Thread D= new Thread(new Runnable() {

            @Override
            public void run() {
                SmackConfiguration.setDefaultPacketReplyTimeout(10000);
                XMPPTCPConnectionConfiguration config = XMPPTCPConnectionConfiguration.builder()
                        .setUsernameAndPassword("harsh", "pass")
                        .setServiceName("192.168.0.200")
                        .setHost("192.168.0.200")
                        .setPort(5223).setSecurityMode(ConnectionConfiguration.SecurityMode.ifpossible)
                        .build();

                AbstractXMPPConnection conn2 = new XMPPTCPConnection(config);
                try {
                    conn2.connect();

                    conn2.login();

                    Presence presence = new Presence(Presence.Type.unavailable);
                    presence.setStatus("Gone fishing");
                    // Send the packet (assume we have an XMPPConnection instance called "con").
                    conn2.sendStanza(presence);

                } catch (SmackException | IOException | XMPPException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    Log.d("TAG", e.toString());
                }

                ChatManager chatmanager = ChatManager.getInstanceFor(conn2);


                Chat newChat = chatmanager.createChat("harsh@192.168.0.200");

                try {
                    newChat.sendMessage("Howdy!");
                }
                catch (SmackException.NotConnectedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }



            }
        });





        D.start();


    }

This gives me an error :

05-15 14:59:35.350    4417-4439/com.example.smacktester W/System.err﹕ org.jivesoftware.smack.SmackException$NoResponseException: No response received within reply timeout. Timeout was 10000ms (~10s). Used filter: No filter used or filter was 'null'. 05-15 14:59:35.351    4417-4439/com.example.smacktester W/System.err﹕ at org.jivesoftware.smack.SynchronizationPoint.checkForResponse(SynchronizationPoint.java:192) 05-15 14:59:35.352    4417-4439/com.example.smacktester W/System.err﹕ at org.jivesoftware.smack.SynchronizationPoint.checkIfSuccessOrWait(SynchronizationPoint.java:114) 05-15 14:59:35.352    4417-4439/com.example.smacktester W/System.err﹕ at org.jivesoftware.smack.SynchronizationPoint.checkIfSuccessOrWaitOrThrow(SynchronizationPoint.java:97) 05-15 14:59:35.352    4417-4439/com.example.smacktester W/System.err﹕ at org.jivesoftware.smack.tcp.XMPPTCPConnection.connectInternal(XMPPTCPConnection.java:837) 05-15 14:59:35.352    4417-4439/com.example.smacktester W/System.err﹕ at org.jivesoftware.smack.AbstractXMPPConnection.connect(AbstractXMPPConnection.java:360) 05-15 14:59:35.354    4417-4439/com.example.smacktester W/System.err﹕ at com.example.smacktester.MainActivity$1.run(MainActivity.java:50) 05-15 14:59:35.354    4417-4439/com.example.smacktester W/System.err﹕ at java.lang.Thread.run(Thread.java:818) 05-15 14:59:35.355    4417-4439/com.example.smacktester D/TAG﹕ org.jivesoftware.smack.SmackException$NoResponseException: No response received within reply timeout. Timeout was 10000ms (~10s). Used filter: No filter used or filter was 'null'. 05-15 14:59:35.365    4417-4444/com.example.smacktester W/AbstractXMPPConnection﹕ Connection closed with error
    org.xmlpull.v1.XmlPullParserException: Unexpected token (position:TEXT ��P@1:8 in java.io.BufferedReader@16ea33d4)
            at org.kxml2.io.KXmlParser.next(KXmlParser.java:432)
            at org.kxml2.io.KXmlParser.next(KXmlParser.java:313)
            at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.parsePackets(XMPPTCPConnection.java:1151)
            at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.access$200(XMPPTCPConnection.java:937)
            at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader$1.run(XMPPTCPConnection.java:952)
            at java.lang.Thread.run(Thread.java:818) 05-15 14:59:35.377    4417-4439/com.example.smacktester W/System.err﹕ org.jivesoftware.smack.SmackException$NotConnectedException: Client is not, or no longer, connected 05-15 14:59:35.377    4417-4439/com.example.smacktester W/System.err﹕ at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketWriter.throwNotConnectedExceptionIfDoneAndResumptionNotPossible(XMPPTCPConnection.java:1226) 05-15 14:59:35.377    4417-4439/com.example.smacktester W/System.err﹕ at org.jivesoftware.smack.tcp.XMPPTCPConnection.throwNotConnectedExceptionIfAppropriate(XMPPTCPConnection.java:336) 05-15 14:59:35.377    4417-4439/com.example.smacktester W/System.err﹕ at org.jivesoftware.smack.AbstractXMPPConnection.sendStanza(AbstractXMPPConnection.java:609) 05-15 14:59:35.377    4417-4439/com.example.smacktester W/System.err﹕ at org.jivesoftware.smack.chat.ChatManager.sendMessage(ChatManager.java:365) 05-15 14:59:35.377    4417-4439/com.example.smacktester W/System.err﹕ at org.jivesoftware.smack.chat.Chat.sendMessage(Chat.java:114) 05-15 14:59:35.377    4417-4439/com.example.smacktester W/System.err﹕ at org.jivesoftware.smack.chat.Chat.sendMessage(Chat.java:98) 05-15 14:59:35.377    4417-4439/com.example.smacktester W/System.err﹕ at com.example.smacktester.MainActivity$1.run(MainActivity.java:71) 05-15 14:59:35.377    4417-4439/com.example.smacktester W/System.err﹕ at java.lang.Thread.run(Thread.java:818) 05-15 14:59:56.335    4417-4417/com.example.smacktester I/Timeline﹕ Timeline: Activity_idle id: android.os.BinderProxy@2763795b time:38739229 05-15 15:00:19.772   4417-4427/com.example.smacktester W/art﹕ Suspending all threads took:
10.531ms 05-15 15:02:44.503    4417-4427/com.example.smacktester W/art﹕ Suspending all threads took: 7.832ms

And, after enabling debugging in the local openfire server, I get this message:

2015.05.15 14:50:03 index.jsp - Failed to fetch RSS feed: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: root certificate not trusted of [vanity2.jiveon.com]

Where am I going wrong ?


Answer:

AS per discussion with user problem was .setPort(5223) in XMPPTCPConnectionConfiguration .Port 5223 by default Client SSL Port in Openfire,

you can change this port setting in  Openfire 3.10 from Admin panel 

Server >> Server Settings >> Client Connections

error

org.jivesoftware.smack.SmackException$NoResponseException: No response received within reply timeout. Timeout was 10000ms (~10s).

Means You are trying to connecting SSL enabled port [5223] with out doing SASL negotiation. Means you need to Store SSL certificate provided by XMPP server[Opnefire] in your application[some where in your internal/external memory] ,and use same certificate for further communication with Xmpp server on SSL Port.

For SSL authentication you can user Truststore

For more information on XMPP SASL negotiation refer this link

Question:

I'm trying to create a multi threaded server to which multiple clients can connect and can be served. However, I'm not sure on how to properly free up my resources should the need arise.

My server runs an input thread (waiting for user inputs) and a procressing thread (handles connections and users). I open up a ServerSocket in the server class and pass it to my processing thread. It looks like this:

public class ClientConnector implements Runnable {

private ServerSocket serverSocket;

public ClientConnector(ServerSocket serverSocket) {
    this.serverSocket = serverSocket;
}

@Override
public void run() {
    ExecutorService tcpExecutor = Executors.newCachedThreadPool();

    while (!serverSocket.isClosed()) {
        Socket clientSocket = null;

        try {
            clientSocket = serverSocket.accept();
        } catch (IOException e) {
            System.err.println("could not accept connection");
        }

        if (clientSocket != null) {
            tcpExecutor.execute(new ClientHandler(clientSocket);
        }           
    }   
}
}

If I want to exit, I just run this method in my server class to close the ServerSocket:

public void exit() {
    try {
        serverSocket.close();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

Which should cause the next serverSocket.accept() call to throw an exception, and the loop stops since the socket is closed.

My question is - does closing a ServerSocket implicitly close ClientSockets that were created using it? Or should I make sure to close every single open ClientSocket by hand? If so, is there an easy way to do so instead of saving every single connection made to the server somewhere?


Answer:

does closing a ServerSocket implicitly close ClientSockets that were created using it?

No, it has no effect on them.

Or should I make sure to close every single open ClientSocket by hand?

Yes, and you should be doing that anyway, in every handler thread.

If so, is there an easy way to do so instead of saving every single connection made to the server somewhere?

Just impose a read timeout and close each socket that times out. This is a normal part of any server. You don't have to collect the sockets or take any special measures about them for shutdown.

Question:

I'm working on an Android application that

  • First, I have to connect to hardware server via TCP socket
  • After connected, I will have to send *99*1## to server, then server will response with "*#*1##*#*1##"
  • Then, I need to keep this socket alive and read incoming message
  • After this point, server can send me message from times to times. But, When will message sent or length of message are undetermined.
  • Every message will end with '##', For example, *1*1*18##, *1*0*19##, *1*1*#4*11## and else.
  • When client (this app) receive message, it will notify activity to update UI.

So, I create a thread subclass to do this

public class ServerThread extends Thread {
    public interface OnReadListener {
        public void onRead(ServerThread serverThread, String response);
    }

    Socket socket;
    String address;
    int port;
    OnReadListener listener = null;

    public ServerThread(String address, int port) {
        this.address = address;
        this.port = port;
    }

    @Override
    public void run() {
        try {
            socket = new Socket(InetAddress.getByName(address), port);

            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            PrintWriter writer = new PrintWriter(bw, true);
            writer.println("*99*1##");
            writer.flush();

            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String line;

            while (!socket.isConnected() && !Thread.currentThread().isInterrupted()) {
                line = br.readLine();

                if (line != null) {
                    Log.i("Dev", "Line ")

                    if (listener != null) {
                        listener.onRead(this, line);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void setListener(OnReadListener listener) {
        this.listener = listener;
    }
}

And in the activity, I do it like this

public class MainActivity extends Activity {

    ServerThread st = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_activity);
    }

    @Override
    public void onResume() {
        startMonitoring();

        super.onResume();
    }

    @Override
    public void onPause() {
        stopMonitoring();

        super.onPause();
    }

    private void startMonitoring() {
        stopMonitoring();

        st = new ServerThread(SERVER_IP_ADDRESS, SERVER_PORT);
        st.setListener(new OnReadListener{
            @Override
            public void onRead(ServerThread serverThread, String response) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        // update UI or do something with response
                    }
                })
            }
        });
        st.start();
    }

    private void stopMonitoring() {
        if (st != null) {
            st.stop();
            st = null;
        }
    }
}

After I start this activity, I found that

  • The message "*99*1##" has been send to server, I can see this message from server hardware.
  • But, I only got first line of response from server '*#*1##*#*1##'
  • After that, socket is still connected (stacktrace not printed) but I never got any further message from server. Listener never gets called.

I have no idea how to make this work. Any suggestion are welcome.

Some note you might need to know

I'm not quit sure that BufferReader is the right object I need for the job or not. Because when it failed to read, it will return null and the loop will keep running. I might need some object that can freeze the thread waiting for input. This object can wait for input as long as it takes since the server may send message in seconds, minutes, hours or more. Once message has received, the continue to execute the code and go to the next round of loop.

(I'm full-time iOS Dev, not really familiar with Java)

Final Edit

After I carefully check the code, I found the silly mistake I made

writer.println("*99*1##")

Basically, println will send "*99*1##" and then follow with newline. But my hardware server doesn't like that so it terminate the connection. That's why I got null from BufferReader's readLine().

After I change to

writer.print("*99*1##")

The server receive "*99*1##" and keep connection. Then, and I can loop to read response just like EJP suggest again

String line;
while ((line = br.readLine()) != null) {
    if (listener != null) {
        listener.onRead(this, line);
    }
}

if (listener != null) {
    listener.onTerminated(this);
}

Answer:

while (!socket.isConnected() ...

The problem is here. The test is pointless anyway, as it will never be false, but negating it means that the controlled block will never execute. Just remove the isConnected() test.

when it failed to read, it will return null and the loop will keep running.

Because you didn't handle that case correctly. If line is null you must exit the loop and close the connection. The usual way to write that is:

String line;
while ((line = reader.readLine()) != null)
{
    // ...
}

Your sleep in your loop is just literally a waste of time.

Question:

I am trying to create a simple TCP server and client. I want the client to be able to send multiple messages by only opening the socket once. I have looked at similar questions here, here, and here but they haven't been much use.

My code is a follows:

SampleServerTCP.java

public class SampleServerTCP {
    private static final int DEFAULT_PORT_NUMBER = 39277;

    public static void main(String[] args) throws IOException {
        ServerSocket defaultSocket = new ServerSocket(DEFAULT_PORT_NUMBER);

        System.out.println("Listening on port: " + DEFAULT_PORT_NUMBER);
        while (true){
            Socket connectionSocket = defaultSocket.accept();
            BufferedReader fromClient= new BufferedReader(new     InputStreamReader(connectionSocket.getInputStream()));
            String msg = fromClient.readLine();
            System.out.println("Recieved: " + msg);
        }
    }
}

TCPClientTest.java

public class TCPClientTest {

    public static void main(String args[]) throws UnknownHostException, IOException, InterruptedException{
        Socket clientSocket = new Socket("localhost", 39277); 
        DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());

        int c = 0;
        while(c<10){
            outToServer.writeBytes(c + "\n");
            outToServer.flush();
            c++;
            Thread.sleep(500);
        }
        clientSocket.close();
    }
}

The only output I get is:

Listening on port: 39277
Recieved: 0

Where am I going wrong?


Answer:

Your problem lies here:

ServerSocket defaultSocket = new ServerSocket(DEFAULT_PORT_NUMBER);

    System.out.println("Listening on port: " + DEFAULT_PORT_NUMBER);
    while (true){
        Socket connectionSocket = defaultSocket.accept();
        BufferedReader fromClient= new BufferedReader(new     InputStreamReader(connectionSocket.getInputStream()));
        String msg = fromClient.readLine();
        System.out.println("Recieved: " + msg);
    }

You are opening the socket, reading only one line and then you are waiting for the next socket.

Instead you should do Socket connectionSocket = defaultSocket.accept(); outside your while loop, and read from this socket in your loop, like this:

System.out.println("Listening on port: " + DEFAULT_PORT_NUMBER);
Socket connectionSocket = defaultSocket.accept();
BufferedReader fromClient= new BufferedReader(new     InputStreamReader(connectionSocket.getInputStream()));
String msg = "";
while ((msg = fromClient.readLine()) != null){    
    System.out.println("Recieved: " + msg);
}

Question:

I'm trying to make a simple text editor which can be shared accross multiple terminals at the same time. I have a Server waiting for new users, when a user enters the shared editor it just starts waiting for input characters.

public class Server {
    public static final int PORT = 8080; 
    public static void main(String[] args) throws IOException {
        ServerSocket ss = new ServerSocket(PORT);

        while (true) {
            Socket socket = ss.accept();
            System.out.println("A new user entered the sever");
            new Thread(() -> serve(socket)).start();
        }
    }

    private static void serve(Socket socket) {
        try {
            while (!socket.isClosed() && !socket.isInputShutdown()) {
                System.out.println("hey " + socket.isClosed() + " " + socket.isInputShutdown());
                System.out.print(new String(SocketUtil.receiveBytes(socket,1)));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

When a user closes the editor, the socket is closed on client side. However, the socket on the server side does not get closed and the server starts looping infinitly in the "wait for input" loop.

The Client is a singleton containing the following methods, called at the openning and closing of the editor.

public static void init() {
        try {
            if (socket == null) socket = new Socket(HOST,Server.PORT);
        } catch (IOException e) {
            e.printStackTrace();
            kill();
            throw new Error(e.getMessage());
        }
    }

    public static void kill() {
        Check.notNull(socket);
        try {
            SocketUtil.terminateCommunication(socket);
            System.out.println(socket.isClosed());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

Finally, here are utilitary methods (in SocketUtil) used in both classes :

public static void terminateCommunication(Socket socket) throws IOException {
    socket.shutdownInput();
    socket.shutdownOutput();
    socket.close();
}

public static char[] receiveBytes(Socket socket, int nBytes) throws IOException {
    char[]            bytes = new char[nBytes];
    InputStreamReader isr   = new InputStreamReader(socket.getInputStream());
    isr.read(bytes);
    return bytes;
}

Any idea of why the socket on server side is not closed after the Client gets killed ?


Answer:

It is not quite clear from the Javadoc, but isClosed() only returns true when you have explicitly called close() on the socket (see the sources to confirm that). You should check for exceptions and the return value of read() instead. If you read -1 or catch an IOException while trying to read (or write, for that matter), it essentially means that the other side has closed the connection, so you should close your socket as well (better to it in a finally block) and you're done with that particular connection. You don't check for -1 in receiveBytes(), but you really should. Perhaps throw a EOFException() if you want to merge these two possibility into one, so that the code up the stack (in serve()) doesn't have to figure out what exactly happened:

public static char[] receiveBytes(Socket socket, int nBytes) throws IOException {
    char[]            bytes = new char[nBytes];
    InputStreamReader isr   = new InputStreamReader(socket.getInputStream());
    if (isr.read(bytes) == -1)
        throw new EOFException();
    return bytes;
}

One exception from the IOException rule (sorry for the pun) is the SocketTimeoutException. If you get this, the connection is still alive, and you may just as well retry your read(). But I believe that in order to get these, you must call Socket.setSoTimeout() somewhere, and if you haven't, then you probably shouldn't worry about SocketTimeoutException.

You should also note that read() may sometimes return partial reads (that is, less than bytes.length). If it's important that receiveBytes() reads exactly nBytes (which probably is, since you never return the number of actual characters read), then you should call it in a loop, like this:

    int pos = 0;
    while (pos < bytes.length) {
        int l;
        if ((l = isr.read(bytes, pos, bytes.length - pos)) == -1) {
            throw new EOFException();
        }
        pos += l;
    }

I know this is cumbersome, which is exactly why many developers create utility methods like your receiveBytes().

Question:

Sample https://github.com/spring-projects/spring-integration-samples/tree/master/basic/tcp-client-server is great to build a TCP Server application. Its simple and runs on JVM. It does not need any Application Server.

Sample uses command line input to run the program. I want the server to accept data only from the Socket port and not through the command line. If I remove the command line input, main thread is finishing and the program no longer accepts input from the port. I have to keep the main thread running all the time.

I am thinking some thing like this:

    boolean isGatewayStopped = false;
    while (!isGatewayStopped) {
        try {
            Thread.sleep(5000);
            isGatewayStopped = getGatewayStatus();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

I have two questions:

  1. is there a clean way of making the Main thread continue to run?

  2. How to know that Gateway is stopped? If the user sends TCP data as "quit" then gateway can be stopped. is there any way to know that gateway is stopped?

Thanks


Answer:

Another solution is like this:

public static void main(String[] args) throws Exception {
        ConfigurableApplicationContext ctx = SpringApplication.run(Application.class, args);
        System.out.println("Hit 'Enter' to terminate");
        System.in.read();
        ctx.close();
}

You start the ApplicationContext and wait for the stop from the console input.

EDIT

For the case when you would like to stop program via an event in the application, you can register ApplicationListener and wait on the barrier before existing from the main:

CountDownLatch exitLatch = new CountDownLatch(1);
ctx.addApplicationListener(ContextClosedEvent e -> exitLatch.countDown())
exitLatch.await();

Now you should just come up with some logic in your application to call ctx.stop() there.

Question:

I have written tcp server using spring integration. Thanks to excellent sample https://github.com/spring-projects/spring-integration-samples/tree/master/basic/tcp-client-server Sample server stops if the user pressed q on the console.

TCP Server is a stand alone application and runs perfectly fine accepting requests and sending responses. I would like to add orderly shutdown of the server because Console access is not possible if the server is started as a background process.

is there a way for the server to wait for events? If the shutdown event comes then I can call applicationContext.stop().

I would appreciate if you can suggest any ideas on orderly shutdown process.

Thanks


Answer:

I am not sure what kind of "event" you are talking about but there are a number of things you can do.

If you enable JMX, the IntegrationMBeanExporter provides for orderly shutdown.

In the case of TCP, this stops it from accepting new connections, drops any new requests and gives you time to wait for any in-process requests to terminate).

You can use a control-bus to send a stop request to the inbound endpoint.

The source for the control bus message could be anything you want - another tcp adapter...

telnet 123.123.123.123
bar.stop()

or using any other messaging technology.

Or you could just use the OS to kill the JVM.

Question:

I have been tasked with getting a simple TCP Client to timeout. The client works as expected, however I cannot seem to get the client to timeout when the client does not receive an input for 3 seconds or more. I have a basic understanding of SO_TIMEOUT, but can't get it to work here. Please help

Here is my code: TCPClient

private static final String host = "localhost";
    private static final int serverPort = 22003;

    public static void main(String[] args) throws Exception
    {

        try
        {
            System.out.println("You are connected to the TCPCLient;" + "\n" + "Please enter a message:");
            BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in));
            @SuppressWarnings("resource")
            Socket client = new Socket(host, serverPort);
            client.setSoTimeout(3000);
            while(true)
            {
                DataOutputStream outToServer = new DataOutputStream(client.getOutputStream());
                BufferedReader inFromServer = new BufferedReader(new InputStreamReader(client.getInputStream()));
                String input = inFromUser.readLine();
                outToServer.writeBytes(input + "\n");
                String modedInput = inFromServer.readLine();
                System.out.println("You Sent: " + modedInput);
                try
                {
                    Thread.sleep(2000);
                }
                catch(InterruptedException e)
                {
                    System.out.println("Slept-in");
                    e.getStackTrace();
                }
            }
        }
        catch(SocketTimeoutException e)
        {
            System.out.println("Timed Out Waiting for a Response from the Server");
        }
    }

Answer:

setSoTimeout doesn't do what you think it does. From the Javadoc:

With this option set to a non-zero timeout, a read() call on the InputStream associated with this Socket will block for only this amount of time.

It's a timeout for reads from the socket, so reads() will return after 3 seconds even if there's no data. It's not a timeout for socket inactivity - i.e. the socket won't disconnect after being idle for 3 seconds.

Question:

I am testing some TCP code and it seems to work fine except for one problem. The read from the socket hangs in one of the methods when there is nothing more to read:

Here is the TCP code:

package com.comp424.service;

import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TCPService implements Runnable
{
    protected int             serverPort;
    protected InetAddress     bindAddress;

    protected ServerSocket    serverSocket  = null;
    protected boolean         isStopped     = false;
    protected Thread          runningThread = null;

    protected ExecutorService threadPool = Executors.newFixedThreadPool(10);

    public TCPService(String host,int port)
    {
        serverPort = port;

        try
        {
            bindAddress = InetAddress.getByName(host);
        }
        catch (UnknownHostException e)
        {
            throw new RuntimeException("Failed to get bind address", e);
        }
    }

    private void start()
    {
        try
        {
            serverSocket = new ServerSocket(serverPort, 10, bindAddress);
        }
        catch (IOException e)
        {
            throw new RuntimeException("Cannot open port " + serverPort, e);
        }
    }

    public void run()
    {
        synchronized (this)
        {
            runningThread = Thread.currentThread();
        }

        start();

        while (!isStopped())
        {
            Socket clientSocket = null;

            try
            {
                clientSocket = serverSocket.accept();
            }
            catch (IOException e)
            {
                if (isStopped())
                {
                    System.out.println("Server Stopped.");
                    break;
                }
                throw new RuntimeException("Error accepting client connection", e);
            }

            threadPool.execute(new ClientHandler(clientSocket));
        }
        threadPool.shutdown();

        System.out.println("Server Stopped.");
    }

    public synchronized void stop()
    {
        isStopped = true;

        try
        {
            serverSocket.close();
        }
        catch (IOException e)
        {
            throw new RuntimeException("Error closing server", e);
        }
    }    

    private synchronized boolean isStopped()
    {
        return isStopped;
    }  
}

package com.comp424.service;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

import com.comp424.impl.dao.DaoFactory;
import com.comp424.intf.dao.ICourseDao;
import com.comp424.intf.dao.IPersonDao;
import com.comp424.intf.dao.IRegisterCourseDao;
import com.comp424.model.Course;
import com.comp424.model.Person;

public class ClientHandler implements Runnable
{
    private static IRegisterCourseDao registrationDao;
    private static IPersonDao         personDao;
    private static ICourseDao         courseDao;

    protected Socket                  clientSocket = null;

    public ClientHandler(Socket socket)
    {
        registrationDao = DaoFactory.getInstance().getCourseRegistrationDao();
        personDao = DaoFactory.getInstance().getPersonDao();
        courseDao = DaoFactory.getInstance().getCourseDao();
        clientSocket = socket;
    }

    public void run()
    {
        try
        {
            String command = null;

            OutputStream output = clientSocket.getOutputStream();
            BufferedReader buffer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));

            command = buffer.readLine();

            while (command != null)
            {
                String separator = ":";

                StringTokenizer tokenizer = new StringTokenizer(command, separator);

                List<String> tokens = new ArrayList<>();

                while (tokenizer.hasMoreElements())
                {
                    tokens.add((String) tokenizer.nextElement());
                }

                int operation = Integer.parseInt(tokens.get(0));

                switch (operation)
                {
                    case 1:
                        try
                        {
                            Person person = personDao.findByID(Long.parseLong(tokens.get(1)));
                            Course course = courseDao.findByID(Long.parseLong(tokens.get(2)));

                            registrationDao.register(person, course);
                            output.write(("0\r\n").getBytes());
                        }
                        catch (Exception e)
                        {
                            e.printStackTrace();
                            output.write(("1\r\n").getBytes());
                        }
                        break;

                    case 2:
                        try
                        {
                            Person person = personDao.findByID(Long.parseLong(tokens.get(1)));
                            Course course = courseDao.findByID(Long.parseLong(tokens.get(2)));

                            registrationDao.register(person, course);
                            output.write(("0\r\n").getBytes());
                        }
                        catch (Exception e)
                        {
                            e.printStackTrace();
                            output.write(("1\r\n").getBytes());
                        }
                        break;

                    case 3:
                        try
                        {
                            Person person = personDao.findByID(Long.parseLong(tokens.get(1)));

                            List<Course> courses = registrationDao.findByPerson(person);

                            for (Course c : courses)
                            {
                                output.write((c.getName() + "\r\n").getBytes());
                            }
                        }
                        catch (Exception e)
                        {
                            e.printStackTrace();
                            output.write(("1\r\n").getBytes());
                        }
                        break;

                }
                command = buffer.readLine();
            }

            output.close();
        }
        catch (IOException e)
        {
            // report exception somewhere.
            e.printStackTrace();
        }
    }
}

And here is the code where it just hangs in findRegisteredCourses() after reading two strings returned instead of exiting the while loop:

    while (response != null)
    {
        result.add(response);
        System.out.println("findRegisteredCourses():Response = " + response);
        response = reader.readLine();

    }

Full code for findRegisteredCourses():

    @Override
    public List<String> findRegisteredCourses(String personID) throws Exception
    {
        try (Socket server = new Socket("localhost", 7000))
        {
            List<String> result = new ArrayList<>();

            DataOutputStream writer = new DataOutputStream(server.getOutputStream());
            BufferedReader reader = new BufferedReader(new InputStreamReader(server.getInputStream()));

            String operation = "3:" + personID + "\r\n";
            writer.writeBytes(operation);
            writer.flush();

            String response = reader.readLine();

            while (response != null)
            {
                result.add(response);
                System.out.println("findRegisteredCourses():Response = " + response);
                response = reader.readLine();

            }
            server.close();
            return result;
        }
    }

Answer:

You're continuing to try to read from the server until it's closed the socket - whereas the server is waiting for another command from the client. Neither side is going to do anything, as they're waiting for the other.

Basically, you need to change your protocol, either to have some "here's the end of the response" indication (such as an empty line, if that's not a valid value in the response data), or to only have a single request/response per connection.

Your suggested "fix" of using the ready() method is very broken - it basically means you assume there's no more data as soon as there's a pause. Maybe the server is taking a while to find the next item. Maybe there's a delay on the network - or maybe it's finished. You can't tell, and basically you're violating the design of streaming protocols (such as TCP) by trying to infer information from the fact that there's no data available right now. Don't do that - fix your protocol.

Question:

I am working on a TCP server that needs to be able to manage up to 500 simultaneous connections. It's a simple server, that waits for the client to establish a connection. Then, it calculates resources asked by the client, and sends it to it.

Rather than using a thread per connection, I have decided to use Vertx.

A colleague adviced me to use one verticle per connection. Reading the documentation, I had the feeling that doing this would go against the principle of Vertx, and that it would amount to doing one thread per connection.

But the thing is, I don't really know how I could do it another way. I could have different Verticles to handle different operations, but these operations are executed a lot in a short time, so it would involve tons of Verticles creation. It would probably be expensive, in terms of performances.

So my question is : Should I do as my colleague said ? If not, Do you have any recommandation?

I understand that this might be hard to answer without knowing exactly what the server needs to do, but the point of this question is to understand the way Vertx should be used to make it as efficient as possible. I don't expect an anwser that will exactly fit my needs, but recommandations to put me in the right track.

Thanks a lot!


Answer:

You do not need one verticle per connection. Start with one verticle instance and then increase the number of instances as needed (depends on your hardware).

The vertx-examples repository has an Echo TCP server and client to get you started.

Question:

My TCP server built using Spring integration works great. I use ByteArrayLengthHeaderSerializer as a serializer.

Once in a while, client data comes very slowly making the server respond very slowly.

I would like to wait a maximum of 5 seconds to read each byte of the data from the client. If the data byte does not come in 5 seconds, I would like to send NAK.

How to set the timeout of 5 seconds? Where should it be set? Do I need to customize serializer?

Here is my spring context:

<int-ip:tcp-connection-factory id="crLfServer"
        type="server"
        port="${availableServerSocket}"
        single-use="true"
        so-timeout="10000"
        using-nio="false" 
        serializer="connectionSerializeDeserialize"
        deserializer="connectionSerializeDeserialize"
        so-linger="2000"/>

    <bean id="connectionSerializeDeserialize" class="org.springframework.integration.ip.tcp.serializer.ByteArrayLengthHeaderSerializer"/>

    <int-ip:tcp-inbound-gateway id="gatewayCrLf"
        connection-factory="crLfServer"
        request-channel="serverBytes2StringChannel"
        error-channel="errorChannel"
        reply-timeout="10000"/> <!-- reply-timeout works on inbound-gateway -->

    <int:channel id="toSA" />

    <int:service-activator input-channel="toSA"
        ref="myService"
        method="prepare"/>

    <int:object-to-string-transformer id="serverBytes2String"
        input-channel="serverBytes2StringChannel"
        output-channel="toSA"/>

    <int:transformer id="errorHandler"
        input-channel="errorChannel"
        expression="payload.failedMessage.payload + ':' + payload.cause.message"/>

Thank you


Answer:

You would need a custom deserializer; by default when the read times out (after the so-timeout) we close the socket. You would have to catch the timeout and return a partial message, with some information to tell the downstream flow to return the nack.

The deserializer does not have access to the connection so it can't send the nack itself.

You could do it in a custom subclass TcpMessageMapper, though - override toMessage().

That said, your solution might be brittle unless you close the socket anyway because the stream may still contain some data from the previous message, although with single-use true, I assume you are only sending one message per socket.

EDIT

@SpringBootApplication
public class So40408085Application {

    public static void main(String[] args) throws Exception {
        ConfigurableApplicationContext context = SpringApplication.run(So40408085Application.class, args);
        context.getBean("toTcp", MessageChannel.class).send(new GenericMessage<>("foo"));
        Thread.sleep(5000);
        context.close();
    }

    @Bean
    public TcpNetServerConnectionFactory server() {
        TcpNetServerConnectionFactory server = new TcpNetServerConnectionFactory(1234);
        server.setSoTimeout(1000);
        server.setMapper(new TimeoutMapper()); // use 'mapper' attribute in XML
        return server;
    }

    @Bean
    public TcpInboundGateway inGate() {
        TcpInboundGateway inGate = new TcpInboundGateway();
        inGate.setConnectionFactory(server());
        inGate.setRequestChannelName("inChannel");
        return inGate;
    }

    @ServiceActivator(inputChannel = "inChannel")
    public String upCase(byte[] in) {
        return new String(in).toUpperCase();
    }

    @Bean
    public TcpNetClientConnectionFactory client() {
        TcpNetClientConnectionFactory client = new TcpNetClientConnectionFactory("localhost", 1234);
        client.setSerializer(new ByteArrayLfSerializer()); // so the server will timeout - he's expecting CRLF
        return client;
    }

    @Bean
    @ServiceActivator(inputChannel = "toTcp")
    public TcpOutboundGateway out() {
        TcpOutboundGateway outGate = new TcpOutboundGateway();
        outGate.setConnectionFactory(client());
        outGate.setOutputChannelName("reply");
        return outGate;
    }

    @ServiceActivator(inputChannel = "reply")
    public void reply(byte[] in) {
        System.out.println(new String(in));
    }

    public static class TimeoutMapper extends TcpMessageMapper {

        @Override
        public Message<?> toMessage(TcpConnection connection) throws Exception {
            try {
                return super.toMessage(connection);
            }
            catch (SocketTimeoutException e) {
                connection.send(new GenericMessage<>("You took too long to send me data, sorry"));
                connection.close();
                return null;
            }
        }

    }

}

Question:

I'm writing a TCP server using Netty v4. The server will handle multiple connections from clients, and stream data to them.

I want to be able to detect when a client is consuming data at a slow ratio. I basically want to avoid the TCP buffers to get full just because a client is slow!

It's basically what ZeroMQ does (called "Slow Subscriber Detection (Suicidal Snail Pattern)"). How can that be done using Netty?

My current code is (I'll just show the server setup):

      ServerBootstrap b = new ServerBootstrap();
      b.group(bossGroup, workerGroup)
          .channel(NioServerSocketChannel.class)
          .option(ChannelOption.SO_BACKLOG, 1000)
          .handler(new LoggingHandler(LogLevel.INFO))
          .childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            public void initChannel(SocketChannel ch) throws Exception {
              ChannelPipeline p = ch.pipeline();
              p.addLast(new Handler());
            }
          });

      ChannelFuture f = b.bind(8000).sync();
      f.channel().closeFuture().sync();

Is that wha the SO_BACKLOG option does? It says it's for connections being queued, but I'm interested in packets being queued for a specific connection.


Answer:

One way you might do this is to use WriteBufferWaterMarks. Quoting from the javadoc:

WriteBufferWaterMark is used to set low water mark and high water mark for the write buffer. If the number of bytes queued in the write buffer exceeds the high water mark, Channel.isWritable() will start to return false. If the number of bytes queued in the write buffer exceeds the high water mark and then dropped down below the low water mark, Channel.isWritable() will start to return true again.

Setting the appropriate water marks on your child channel configs, a slow consumer will mark the channel not-writable for "long" periods of time versus snappy consumers. Therefore, listening on channel write-ability state changes and tracking the amount of time channels are non-writable should identify slow consumers and the relative severity of the backlog, and then you can disconnect a client if their sluggishness reaches some threshold.

Question:

I know spring integration has TcpInboundGateway, TcpOutboundGateway and ByteArrayLengthHeaderSerializer to handle data coming through TCP port.

ByteArrayLengthHeaderSerializer works great if the TCP server needs to read all the data sent from the client and then processes it. (request and response model)

For example if the client sends 9AAPL then Server can send the AAPL price.

I am looking for a way where the client can interact with the server without closing the connection in multiple requests.

For example: if the client sends 9AAPL then the server should send AAPL price and wait for another request from the client without closing connection. This interaction can go on till the client sends 5 or no response from a client in 50 seconds.

can you please suggest the spring integration classes (TCP Gateways, Serializers etc.) that needs to be used for this interactive behavior?

we are using spring integration 4.2.6.RELEASE version and java 8. Are those versions good enough or do we need to upgrade to newer versions?

UPDATE: Here is my spring configuration:

    <bean id="connectionSerializeDeserialize" class="org.springframework.integration.ip.tcp.serializer.ByteArrayLengthHeaderSerializer"/>

    <int-ip:tcp-inbound-gateway id="gatewayCrLf"
        connection-factory="crLfServer"
        request-channel="serverBytes2StringChannel"
        error-channel="errorChannel"
        reply-timeout="10000"/> <!-- reply-timeout works on inbound-gateway -->

    <int:channel id="toSA" />

    <int:service-activator input-channel="toSA"
        ref="myService"
        method="prepare"/>

    <int:object-to-string-transformer id="serverBytes2String"
        input-channel="serverBytes2StringChannel"
        output-channel="toSA"/>

    <int:transformer id="errorHandler"
        input-channel="errorChannel"
        expression="payload.failedMessage.payload + ':' + payload.cause.message"/>

Thanks


Answer:

Please show your configuration - what you want is the default behavior.

Only if you set singleUse to true will the gateway close the socket.

Of course, your client must not close the socket either.

Set the soTimeout to close the socket after receiving no requests for that time.

You don't need newer versions, but we always recommend using the latest (4.3.4).

Question:

I have to connect with a server (I don´t have access to the server code) but the transmission protocol (Socket) is:

(client) --> data

ack <-- (server) data response <-- (server)

(client) --> ack

It's assumed that the server should always respond quickly. I connect to the server, I send the data but the response is NULL and if I debug my code, an exception occurs when I catch the response: "java.net.SocketException: Software caused connection abort: recv failed"

My code:

public static void main(String[] args){
    try{
        String order = "datahere";
        String responseServer;   
        BufferedReader inFromUser = new BufferedReader( new InputStreamReader(System.in));  

        Socket clientSocket = new Socket();
        InetSocketAddress sa = new InetSocketAddress("XXX.XX.XX.XX", 9300);
        clientSocket.connect(sa,500);

        DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());   
        BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));    
        outToServer.writeBytes(order);   
        responseServer = inFromServer.readLine();//exception if I try to debug my code   
        System.out.println("From server: " + responseServer); //responseServer is NULL
        clientSocket.close(); 

    } catch (IOException ex) {
            System.out.println("Error: "+ex);
    }

}

That's wrong? Any idea?

I tried to disable the firewall and also add a rule for the port 9300 but the result is the same.

The client gave me an example code in Vb.Net that it's supposed to work and I try to replicate it in Java.

Code in Vb.Net:

Dim message As String = "datahere";

 Try
     Dim data As [Byte]() = System.Text.Encoding.ASCII.GetBytes(message)

     Dim client As New TcpClient(ip, port)
     Dim stream As NetworkStream = client.GetStream()
     stream.Write(data, 0, data.Length)

     data = New [Byte](2048) {}

     Dim responseData As [String] = [String].Empty
     Dim bytes As Integer = stream.Read(data, 0, data.Length)
     responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes)

     stream.Close()
     client.Close()

 Catch ex As Exception

End Try

SOLUTION:

Socket clientSocket = new Socket();
InetSocketAddress sa = new InetSocketAddress("XXX.XX.XX.XX", 9300);
clientSocket.connect(sa,500);

clientSocket.getOutputStream().write(order.getBytes("ASCII"));

byte[] data = new byte[2048];
int bytes = clientSocket.getInputStream().read(data, 0, data.length);
String responseData = new String(data, 0, bytes, "ASCII");
System.out.println("From server: " + responseData);

//Another way to catch the response:
//InputStreamReader in = new InputStreamReader(clientSocket.getInputStream());
//int data1 = in.read();
//while(data1 != -1) {
//   System.out.print((char) data1);
//   data1 = in.read();
//}

clientSocket.close();

Answer:

Here is a translation of your VB code in java

public static void main(String[] args) throws IOException {
    String order = "datahere";

    // Try-with-resource statement will close your socket automatically
    try (Socket clientSocket = new Socket("XXX.XX.XX.XX", 9300)) {
        // Send to the sever the order encoded in ASCII
        clientSocket.getOutputStream().write(order.getBytes("ASCII"));
        // Sleep until we have bytes to read available
        while (clientSocket.getInputStream().available() == 0) {
            Thread.sleep(100L);
        }
        // Create the buffer of exactly the amount of bytes available without blocking
        byte[] data = new byte[clientSocket.getInputStream().available()];
        // Read the bytes from the server and put it into the buffer
        int bytes = clientSocket.getInputStream().read(data, 0, data.length);
        // Decode what has been read from the server that was encoded in ASCII
        String responseData = new String(data, 0, bytes, "ASCII");
        System.out.println("From server: " + responseData);
    }
}

Question:

Spring integration has excellent example to TCP Server. But it seems to be using single thread for every socket connection.

Is there any example on how to create TCP Server which can process requests with multiple threads? Better yet, is there any example to use thread pooling in TCP Server.

I would appreciate if you can provide any links.

Thanks


Answer:

Set using-nio="true" when processing a large number of sockets and a thread pool is shared across the connections.

For a small number of sockets it's generally faster to use a single thread per socket.

Question:

I am programming a external Taskmanager and i need to send the process list via tcp to my server application. But i don't know how to start and how this works.

Edit: I have the processlist i only have to send it via TCP to the Serverside.

Thx for your help.


Answer:

If you already have a processlist, then it's not so hard to make client-server logic for your purposes with Java. First of all, you need to make a server side:

public class ServerSide {

    public static void main(String[] args) {
        try
        {
            ServerSocket myServerSocket = new ServerSocket(9999);
            Socket skt = myServerSocket.accept();
            List<Process> objects = null;
            try {
                ObjectInputStream objectInput = new ObjectInputStream(skt.getInputStream());
                try {
                    Object object = objectInput.readObject();
                    objects =  (ArrayList<Process>) object;
                    System.out.println(objects);
                } catch (ClassNotFoundException e) {             
                    e.printStackTrace();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }
}

Wich will use a ServerSocket to listen on specified port, in this case is 9999. Then connection accepted (take a look at myServerSocket.accept(), it stops the execution, until any connection is accepted), it creates a Socket and you can get it's InputStream and get an object from it. In this example server stops after first accepted connection, you should make it accept any number of connections with infinity loop for example.

When you have a server, you can make a client side, which will send a list of Processes to the Server:

public class ClientSide {

    public static void main(String[] args) {
        try {
            Socket socket = new Socket("127.0.0.1",9999);

            ArrayList<Process> my =  new ArrayList<Process>();
            my.add(new Process("Test1"));
            my.add(new Process("Test2"));
            try
            {
                ObjectOutputStream objectOutput = new ObjectOutputStream(socket.getOutputStream());
                objectOutput.writeObject(my);
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

In this case, you'll create a Socket by youself, give an eddress and port number to it, where it will send a data. Then you can get an OutputStream and pass your data through it. In example above, you pass an Array of Process object instances. The Process class looks like:

public class Process implements Serializable {

    private String processName = null;

    public Process(String processName) {
        this.processName = processName;
    }

    @Override
    public String toString() {
        return processName;
    }
}

The main thing in case of Process class, it should implement the Serializable interface. In that case, you don't need to make some logic for it's serialization.

But if you have to make a client with Java, but not a server, then it could be a little bit harder. You may take a look here, to see some kind of example, how Java-client communicates with C++ server. Anyway, in Java-part you should use a Socket and it's OutputStream, only the data representation will differ.

Question:

Server : package Server;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

import javax.imageio.ImageIO;

public class Server extends Thread{

private ServerSocket mServer_Socket;
private ArrayList<SocketManager> managers = new ArrayList<SocketManager>();

public Server(){
    try {
        mServer_Socket = new ServerSocket(4242);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

@Override
public void run() {
    Socket msocket;
    try{
        msocket = mServer_Socket.accept();
        System.out.println("connected");
        managers.add(new SocketManager(msocket));
    }catch(Exception e){
        e.printStackTrace();
    }
}

public void SendMessage(String m, int i){
    try {
        managers.get(i).write(m.getBytes());
    } catch (IOException e) {
        e.printStackTrace();
    }
}

private class SocketManager{
    private OutputStream mout;
    private InputStream min;

    public SocketManager(Socket socket){
        try{
            mout = socket.getOutputStream();
            min = socket.getInputStream();
        }catch (IOException ioe) {
            ioe.printStackTrace();
        }
        startListen();
    }

    public void write(byte[] data) throws IOException{
        mout.write(data);
    }

    public void startListen(){
        new Thread() {
            BufferedImage image;
            public void run(){
                try {
                    System.out.println("listen..");
                    while(true){
                        if((image = ImageIO.read(min)) != null){
                            while(min.read() != 'y');
                            System.out.println("received");
                            mout.write('y');
                            mout.flush();
                            Main.drawImage(image);
                        }
                    }

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }
    }
}

Client :package Client;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.List;

import javax.imageio.ImageIO;

import com.github.sarxos.webcam.Webcam;
import com.github.sarxos.webcam.WebcamResolution;
import com.github.sarxos.webcam.ds.fswebcam.FsWebcamDriver;

public class Client {
    private static List<Webcam> webcams = null;
    static Webcam webcam = null;

    static {
        Webcam.setDriver(new FsWebcamDriver());
    }

    public static void main(String[] args) {

    try {
        webcams =(List<Webcam>) Webcam.getWebcams(1000000);
    } catch (Exception e) {
        e.printStackTrace();
    }

    for(Webcam device : webcams){
        String name;
        System.out.println(name = device.getDevice().getName());
        //if(name.equals("Logitech HD Webcam C270 1"))
        webcam = device;
    }
    webcam.setViewSize(WebcamResolution.VGA.getSize());

    webcam.open();

    try{
        Socket socket = new Socket("localhost", 4242);
        OutputStream out = socket.getOutputStream();
        InputStream in = socket.getInputStream();
        byte[] buffer = new byte[10];
        while(true){
            ImageIO.write(webcam.getImage(), "png", out);
            out.flush();
            out.write('y');
            out.flush();
            System.out.println("read");
            while(in.read() != 'y');
        }
    }catch(Exception e){
        e.printStackTrace();
    }

    }
}

This Program works well about 10sec. But after that It doesn't work. Socket is Connected but It doesn't send anything. I guess it doesn't match sync, so I match sync, but it's not work too. I don't have an idea. why It doesn't work. please help. I can't find problem


Answer:

Your client needs to send the size of transfered image to server prior to sending the image itself, because your server needs to know how long the image is, in order to read it from socket and start receiving the char data coming right after the image. And since "ImageIO" has no means of specifying the number of bytes supposed to be read from the input stream, you should use InputStream instead. See the modified code below (I put comments whenever added a new line, everything else is identical with yours):

Server:

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream; //<--- added
import java.io.DataInputStream;      //<--- added
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

import javax.imageio.ImageIO;

public class Server extends Thread{

private ServerSocket mServer_Socket;
private ArrayList<SocketManager> managers = new ArrayList<SocketManager>();

public Server(){
    try {
        mServer_Socket = new ServerSocket(4242);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

@Override
public void run() {
    Socket msocket;
    try{
        msocket = mServer_Socket.accept();
        System.out.println("connected");
        managers.add(new SocketManager(msocket));
    }catch(Exception e){
        e.printStackTrace();
    }
}

public void SendMessage(String m, int i){
    try {
        managers.get(i).write(m.getBytes());
    } catch (IOException e) {
        e.printStackTrace();
    }
}

private class SocketManager{
    private OutputStream mout;
    private InputStream min;
    private DataInputStream din; //<--- added DataInputStream    

    public SocketManager(Socket socket){
        try{
            mout = socket.getOutputStream();
            min = socket.getInputStream(); 
            din = new DataInputStream(min); //<--- initialized DataInputStream

        }catch (IOException ioe) {
            ioe.printStackTrace();
        }
        startListen();
    }

    public void write(byte[] data) throws IOException{
        mout.write(data);
    }


    public void startListen()
    {
        new Thread() {                                   
            BufferedImage image;
            public void run(){
                try {                   
                    System.out.println("listen..");                                                                                                           
                    while(true)
                    {
                        int arrlen = din.readInt();  //<--- receive image size in order to prepare a buffer for it                      
                        byte[] b = new byte[arrlen]; //<--- prepare a buffer
                        din.readFully(b);            //<--- receive image data

                        while(min.read() != 'y');                                                                  
                        mout.write('y');                       
                        mout.flush();

                        InputStream bais = new ByteArrayInputStream(b); //<--- get ByteArrayInputStream from buffer
                        BufferedImage image = ImageIO.read(bais);       //<--- prepare BufferedImage from ByteArrayInputStream 
                        bais.close();                                   //<--- close ByteArrayInputStream

                        Main.drawImage(image);  

                    }//end while true

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }.start();


    }


    }


}

Client:

import java.awt.image.BufferedImage;  //<--- added
import java.io.ByteArrayOutputStream; //<--- added
import java.io.DataOutputStream;      //<--- added
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.List;

import javax.imageio.ImageIO;

import com.github.sarxos.webcam.Webcam;
import com.github.sarxos.webcam.WebcamResolution;
import com.github.sarxos.webcam.ds.fswebcam.FsWebcamDriver;

public class Client {
    private static List<Webcam> webcams = null;
    static Webcam webcam = null;

    static {
        Webcam.setDriver(new FsWebcamDriver());
    }

    public static void main(String[] args) {

    try {
        webcams =(List<Webcam>) Webcam.getWebcams(1000000);
    } catch (Exception e) {
        e.printStackTrace();
    }

    for(Webcam device : webcams){
        String name;
        System.out.println(name = device.getDevice().getName());
        //if(name.equals("Logitech HD Webcam C270 1"))
        webcam = device;
    }
    webcam.setViewSize(WebcamResolution.VGA.getSize());

    webcam.open();

    try{
        Socket socket = new Socket("localhost", 4242);       
        OutputStream out = socket.getOutputStream();
        InputStream in = socket.getInputStream();
        DataOutputStream dos = new DataOutputStream(out);           //<--- added DataOutputStream
        BufferedImage image = null;                                 //<--- added BufferedImage to keep image from webcam                 
        while(true){

            ByteArrayOutputStream baos = new ByteArrayOutputStream();        //<--- create ByteArrayOutputStream            
            image = webcam.getImage();                                       //<--- get BufferedImage from webcam
            ImageIO.write(image, "png", baos);                               //<--- write image into ByteArrayOutputStream
            dos.writeInt(baos.size());                                       //<--- send image size                                                 
            dos.flush();  //<--- flush DataOutputStream                                                        
            baos.close(); //<--- close ByteArrayOutputStream

            ImageIO.write(image, "png", out);                                    
            out.flush();                                                                                       
            out.write('y');
            out.flush();
            System.out.println("read");
            while(in.read() != 'y');
        }
    }catch(Exception e){
        e.printStackTrace();
    }

    }
}

Question:

So I have a TCP server which has the ability for clients to register users.It contains a UserRepo object which holds the registered users and handles the adding of users.How do I make it that even with multiple clients accessing my server on different threads that the data for UserRepo remains consistent and correct across all threads?

Server.java

  package danielhaughtonemailapplicationca1;


 import java.io.*;
 import java.net.*;

class Server implements Runnable
{
Socket connectionSocket;
   UserRepo userRepo;
public Server(Socket s){
    try{
        System.out.println("Client Got Connected  " );
        connectionSocket=s;
                    userRepo = new UserRepo();
    }catch(Exception e){e.printStackTrace();}
}

public void run(){
    try{
                User loggedInUser = null;
                String input="";
                while(!"exit".equals(input)){

            BufferedReader reader =
                    new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
            BufferedWriter writer= 
                    new BufferedWriter(new OutputStreamWriter(connectionSocket.getOutputStream()));
                   if(loggedInUser == null){
                       loginOrRegister(reader,writer,input);
                   }else{

                   }

                }
                System.out.println("A connection was closed");
                connectionSocket.close();
    }catch(Exception e){e.printStackTrace();}
   }
    public  void loginOrRegister(BufferedReader reader,BufferedWriter writer,String input) throws IOException{
                        while(input.equals("exit")){
        writer.write("*** Hi!Write login to login or register to register ***\r\n");            
            writer.flush();
            input = reader.readLine().trim();
                    if(input.equals("register")){
                     writer.write("*** write the email address you want ***\r\n");            
            writer.flush();
                        String email = reader.readLine().trim();
                                                 writer.write("*** write the password you want ***\r\n");            
            writer.flush();
                        String password = reader.readLine().trim();
                        User user = userRepo.addUser(email, password);
                    }else if(input.equals("login")){

                    }

    }
    }

 public static void main(String argv[]) throws Exception
  {
     System.out.println("Threaded Server is Running  " );
     ServerSocket mysocket = new ServerSocket(5555);
     while(true)
     {
        Socket sock = mysocket.accept();
        Server server=new Server(sock);

        Thread serverThread=new Thread(server);
        serverThread.start();

     }
  }
  }

UserRepo

public class UserRepo {
ArrayList<User> registeredUsers;

public UserRepo() {
}

public UserRepo(ArrayList<User> registeredUsers) {
    this.registeredUsers = registeredUsers;
}
public ArrayList<User> getRegisteredUsers() {
    return registeredUsers;
}
public void setRegisteredUsers(ArrayList<User> registeredUsers) {
    this.registeredUsers = registeredUsers;
}

public User addUser(String email,String password){
    for(int i=0;i<=registeredUsers.size();i++){
        if(registeredUsers.get(i).getEmail().equalsIgnoreCase("email")){
            //if the email already exists,return null,we cant add the user
            return null;
        }
    }
    //if we get here the user can be added
    User user = new User(email,password);
        registeredUsers.add(user);
        return user;
}
public User login(String email,String password){
            for(int i=0;i<=registeredUsers.size();i++){
        if(registeredUsers.get(i).getEmail().equalsIgnoreCase("email")){
           //here we found the user with the given email
           //lets check if the password is right
            if(password.equals(registeredUsers.get(i).getPassword())){
                //password is right
                return registeredUsers.get(i);
            }else{
                //the password isnt correct
                return null;
            }
        }
 }
            //we get here if we didnt find a matching email,return null
            return null;
 }
 }

Answer:

Probably the most basic synchronization mechanism in Java is the use of synchronized, either as a method modifier [1] (i.e. public synchronized User addUser(String email,String password) or as a statement [2].

Of course, the smaller the synchronized block (whether as a statement or as a function), the less performance you have to trade since other threads will block (be waiting) for a smaller number of instructions.

In this case, you could do something like:

synchronized(this) {
    registeredUsers.add(user);
}

This would make Thread A acquire a lock on the registeredUsers. When Thread B tries to add a new user while another is being added, Thread B would wait until it can acquire the lock from Thread A (in this case, as soon as Thread A's execution leaves the synchronized block).

See also the references below.

[1] https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html

[2] https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html

Question:

I have a netty client application. This app is connecting to a port and retrieving tcp response. When i read respose under load some response messages are concatenating. My request and response messages have a unique transaction key. I am following it for my business logic;

Actual: 000010690013200000101PMAX 567F 0000000000 1554092081842400 0 000010690013200000101PMAX 567F 0000000000 1556083801080400 0

Expected: 000010690013200000102PMAX 567F 0000000000 1554092081842400 0

Dublicate response is have 2 response but server send just 1 response we aggregated it while reading

@Override
public void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf in) {
    String input = in.toString(CharsetUtil.UTF_8);
    log.info(input);
}

How can i resolve this issue and it is occuring under load.

Netty Version: 4.1.25.Final Java Version: OpenJDK 64-Bit Server VM (build 25.161-b14, mixed mode)

Thanks.


Answer:

This is expected and just how TCP work. TCP has not notion of message boundaries and so you may receive the bytes just as you read them (which means stuff can be fragmented etc).

If you need to preserve some sort of message boundaries you will need to encode this information in your protocol. For example you could prepend the length of the message and then use this information on the receiving peer to correct decode the message.

Netty itself contains some decoders / encoders that

LengthFieldPrepender

LengthFieldBasedFrameDecoder

Question:

I am trying now for a while to get started with Spring Integration, but unfortunately can't get it to work.

I would like to have a server listening on a TCP port and printing out the data sent to it from the client. My client is another command line tool, but because I couldn't get it to work I am using this dummy client to send a message.

So far I looked into two examples and am lost which one to follow actually:

  1. Blog post on TCP vending machine connection
  2. The official annotation based example TcpClientServerAnnotationDemoTest.java which is the code here used.
@EnableIntegration
@IntegrationComponentScan
@Configuration
public class Config {

    @MessagingGateway(defaultRequestChannel = "toTcp")
    public interface Gateway {
        String viaTcp(String in);
    }


    @Bean
    public TcpInboundGateway tcpInGate(AbstractServerConnectionFactory connectionFactory) {
        TcpInboundGateway inGate = new TcpInboundGateway();
        inGate.setConnectionFactory(connectionFactory);
        inGate.setRequestChannel(fromTcp());
        return inGate;
    }

    @Bean
    public MessageChannel fromTcp() {
        return new DirectChannel();
    }

    @MessageEndpoint
    public static class Echo {

        @Transformer(inputChannel = "fromTcp", outputChannel = "toEcho")
        public String convert(byte[] bytes) {
            return new String(bytes);
        }

        @ServiceActivator(inputChannel = "toEcho")
        public String upCase(String in) {
            return in.toUpperCase();
        }

        @Transformer(inputChannel = "resultToString")
        public String convertResult(byte[] bytes) {
            return new String(bytes);
        }
    }

    @Bean
    public AbstractServerConnectionFactory serverCF() {
        return new TcpNetServerConnectionFactory(8000);
    }
}

and here my dummy client sending a message.

String host = "localhost";
int port = 8000;
InetAddress address = InetAddress.getByName(host);
socket = new Socket(address, port);

//Send the message to the server
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);

String myMessage = "THIS IS MY MESSAGE!";

String sendMessage = myMessage + "\n";
bw.write(sendMessage);
bw.flush();
System.out.println("Message sent to the server : "+ sendMessage);

//Get the return message from the server
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String message = br.readLine();
System.out.println("Message received from the server : " + message);

It does successfully create a TCP connection! But, where can I see the message? I was initially thinking that I could just print whatever passes through the @Transformer or @ServiceActivator but that didn't work.

2019-03-06 15:46:12.023 DEBUG 22941 --- [pool-2-thread-1] .s.i.i.t.c.TcpNetServerConnectionFactory : Accepted connection from 127.0.0.1:41178
2019-03-06 15:46:12.025 DEBUG 22941 --- [pool-2-thread-1] o.s.i.i.tcp.connection.TcpNetConnection  : New connection localhost:41178:8000:fdaf998f-7045-43e6-aa4a-2e4ecf6b1d9d
2019-03-06 15:46:12.025 DEBUG 22941 --- [pool-2-thread-1] .s.i.i.t.c.TcpNetServerConnectionFactory : serverCF: Added new connection: localhost:41178:8000:fdaf998f-7045-43e6-aa4a-2e4ecf6b1d9d
2019-03-06 15:46:12.025 TRACE 22941 --- [pool-2-thread-1] .s.i.i.t.c.TcpNetServerConnectionFactory : serverCF: Connection is open: localhost:41178:8000:fdaf998f-7045-43e6-aa4a-2e4ecf6b1d9d
2019-03-06 15:46:12.025 DEBUG 22941 --- [pool-2-thread-2] o.s.i.i.tcp.connection.TcpNetConnection  : localhost:41178:8000:fdaf998f-7045-43e6-aa4a-2e4ecf6b1d9d Reading...
2019-03-06 15:46:12.025 DEBUG 22941 --- [pool-2-thread-2] o.s.i.i.t.s.ByteArrayCrLfSerializer      : Available to read: 20
2019-03-06 15:46:12.026 TRACE 22941 --- [pool-2-thread-1] o.s.i.i.tcp.connection.TcpNetConnection  : Published: TcpConnectionOpenEvent [source=TcpNetConnection:localhost:41178:8000:fdaf998f-7045-43e6-aa4a-2e4ecf6b1d9d], [factory=serverCF, connectionId=localhost:41178:8000:fdaf998f-7045-43e6-aa4a-2e4ecf6b1d9d] **OPENED**

When I am using the actual client the command line tool, the connection is established as well, but any follow up messages send throw SocketTimeoutException.

I appreciate any help, as well as any suggestion for a tutorial on Spring Integration for TCP using annotations! Thank you!


Answer:

To print the data from the client there is just enough to have a WireTap on the fromTcp or toEcho channel and tap it into some other channel for printing. Typically the LoggingHandler is enough to have as a subscriber to that wire-tapping channel.

You can see more info in the Reference Manual: https://docs.spring.io/spring-integration/docs/current/reference/html/#channel-interceptors

Question:

I have developed an embedded system which sends data to a server as TCP requests. I can't use more-frequent HTTP requests, because of its data overhead. Less package length will result in less energy consumption and less communication expenses.

The server has to listen to a special port, get the data from device and store in a table.

As I explored, Java servlets + Apache Tomcat is a popular solution but in this case should not be used, because a Java servlet is more suitable for HTTP-based connections.

Is there a better solution for this type of communication?


Answer:

Please take a look at Sockets. They are on the Application layer TCP/IP model and they provide reliable, bidirectional communication, with no data overhead. However, you will need to design a tiny protocol for the communication to much your needs.

Most probably this will suffice your needs, but if you decide to go with the HTTP solution, keep in mind Websockets which is an interesting solution, will diminish the overhead of the HTTP protocol (but they won't eliminate it, the overhead will remain at around 2-10 bytes.). Unfortunately, Java SE doesn't built in provide support for Websockets so you will need to use an external library.

PS: Both options support encryption over TLS but I didn't mention it, cause it adds a noticeable overhead (at least during the initialization of the connection)

Question:

Hi guys so I have a task where I'm suppose to send a message to a server, and then get a reply back. I keep getting failed 1recvfrom failed: EBADF (Bad file descriptor) error and I'm new to this socket stuff. Hopefully someone can help me out. Here's my async task:

 private class SendDataAsyncTask extends AsyncTask<Void,Void,Void>
    {
        private String reply = "";
        @Override
        protected Void doInBackground(Void... params)
        {
            try {
                Socket socket = new Socket("ip",portNumber);
                PrintWriter printWriter = new PrintWriter(socket.getOutputStream());
                //printWriter.write("hello there");

                printWriter.println("hello there");
                bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                printWriter.flush();
                reply = bufferedReader.readLine();
                if(reply != null && !reply.equals(""))
                {
                    Log.d(SOCKET_TESTING_TAG,"my message is " + reply);
                }
                else
                {
                    Log.d(SOCKET_TESTING_TAG,"no message yet");
                }
                Log.d(SOCKET_TESTING_TAG,"break 3");
                printWriter.close();

            }
            catch (IOException e)
            {
                Log.d(SOCKET_TESTING_TAG,"failed " + e.getMessage());
                e.printStackTrace();
            }
            return null;
        }
        @Override
        public void onPostExecute(Void var)
        {
            tv_response.setText(reply);
        }
    }
  • Note: When I put the if statement to check for the null readline before printWriter.flush() I still get an error.

Answer:

printWriter.close();

Closing the input or output stream of a socket closes the other stream and the socket. Remove both occurrences.

if(bufferedReader.readLine() != null)

This doesn't make sense. You are throwing the line away and then reading the next line if it wasn't null. You need to store the result into a variable.

You probably need to use printWriter.println() instead of printWriter.write(). Probably the peer is reading lines too, and you aren't sending one (no line terminator).

If reply == null it means the peer has closed the connection. Not 'no message yet'. An empty string may be a protocol error but it also is not 'no message yet'.

Question:

i am working on a problem on socket programming in JAVA. There is a server and a client. 1) server is connected to client 2) server sends N no of Strings which are stored in an array on server side(obviously ;)). 3)Client doesn't know the size of array 4)Server receives Strings from server one by one. 5)When Client reads all the Strings it sends one msg to server 6)Server receives the msg. 7)This process goes on(step 2-step 6) for multiple times.

The problem i am facing is, Client does not know when server sends the last String and it is waiting for its turn. I have solved this problem using: a)Multi threading. b)Telling size of array to client at the beginning of the first msg

I want to know is there any in-built function which indicates if the server has stoped sending data?

here is the code for 1 iteration(step 1-step 6)

Server code:

public class server {
static String[] a;
static DataOutputStream dos;
static DataInputStream dis;
static ServerSocket server;
static Socket socket;

public static void main(String[] args)
{

    a=new String[]{"String1","String2","String3"};


     try {

        server=new ServerSocket(8080);

        socket=server.accept();
        dos=new DataOutputStream(socket.getOutputStream());
        dis=new DataInputStream(socket.getInputStream());

        ///sending array values

        //String temp=null;

        for(int i=0;i<a.length;i++)
        {
            dos.writeUTF(a[i]);
        }

        String msg_from_client=dis.readUTF();
        System.out.println(msg_from_client);



    } catch (IOException e) {

        e.printStackTrace();
    }

}


}

Client code:

public class client {


static String[] a;
static DataOutputStream dos;
static DataInputStream dis;
static Socket socket;
static Scanner sc;

public static void main(String[] args)
{
    try {
        socket=new Socket("127.0.0.1",8080);
        System.out.println("connected");
        dos=new DataOutputStream(socket.getOutputStream());
        dis=new DataInputStream(socket.getInputStream());
        sc=new Scanner(System.in);

        //reading from server i dont know what is the size of array at server side
        String temp=null;
        while((temp=dis.readUTF())!=null)
        {
            System.out.println(temp);
        }
        System.out.println("out of the loop");

        ////now client sends the msg;

        String msg=sc.nextLine();
        dos.writeUTF(msg);

        System.out.println("sent");




    } catch (UnknownHostException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }


}
}

output at client side:

connected String1 String2 String3


Answer:

This is the time to learn more about protocols. You can setup your own protocol between your server and client i.e., the first message from the server would always contain the # of strings to follow. The client would keep a note of it and then it will request for # of strings that server told in first method.

EDIT: Little more enhanced protocol

If you chose the path to open a new connection for each message as suggested by other user, then you would have to add a little more to your protocol. You would need

  1. Client Information, so that server knows what communication it has done with this client previously
  2. Message information, so that server knows if this client is asking for new message or it sent some message earlier to this client and he is asking for next part of this message.

1 can be achieved by allotting a client ID. If you know how many clients you are dealing with, you can have it a hardcoded value. Otherwise generate at runtime

2 Message information could be "null" indicating that the client is asking for "any new message" for him. Keep in mind that having a "null" message_id doesn't mean that you skip this field. You have to make sure you add "message_id" "key" in the request but keep that field empty. The reply to this request would be expected # of strings that server would be returning plus a newly generated message_id. The client will use this message_id in all subsequent calls and will tell the server, I am asking for string x of y from message_id z

Question:

I just wanna make a Server application which gets Strings and put these into a JTextArea. There are two errors I get, even no errors are showed.

  1. the window can't be closed although I used this statement:

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

  2. If the client connects to the Server, the whole window turns black. What could be the error? Here the code:

Client:

public Main() {
    super("Main");
    setIconImage(Toolkit.getDefaultToolkit().getImage(Main.class.getResource("/images/ic.png")));

    panelFields = new JPanel();
    panelFields.setLayout(new BoxLayout(panelFields,BoxLayout.X_AXIS));
    panelFields2 = new JPanel();
    panelFields2.setLayout(new BoxLayout(panelFields2,BoxLayout.X_AXIS));

    scrollPane = new JScrollPane();
    panelFields.add(scrollPane);

    getContentPane().add(panelFields);
    getContentPane().add(panelFields2);
    getContentPane().setLayout(new BoxLayout(getContentPane(),BoxLayout.Y_AXIS));
    setSize(326, 264);
    setVisible(true);

    messagesArea = new JTextArea();
    scrollPane.setViewportView(messagesArea);
    messagesArea.setColumns(30);
    messagesArea.setRows(10);
    messagesArea.setEditable(false);

    startServer = new JButton("Start");
    startServer.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            socketConnection();
            startServer.setEnabled(false);
        }
    });

    panelFields.add(startServer);
}

And the Server connection:

private void socketConnection() {
    try {
        serverSocket = new ServerSocket(9090);
        System.out.println("Listening: " + serverSocket.getLocalPort());
    } catch (IOException e) {
        e.printStackTrace();
    }

    while (true) {
        try {
            socket = serverSocket.accept();
            dataInputStream = new DataInputStream(socket.getInputStream());
            System.out.println("ip: " + socket.getInetAddress());
            System.out.println("message: " + dataInputStream.readUTF());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if (dataInputStream != null) {
                try {
                    dataInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

Maybe you could tell me, how I can fix those problems and also, how I can make, that the server doesn't close the socket although the client disconnects. I wanna reconnect maybe later...


Answer:

You need to start your socket listener in its own thread, and you need to add a window close listener that shuts down that thread.

For example:

private ServerSocket serverSocket = null;
private boolean done = false;

private void startServer() {
    Thread t = new Thread(new Runnable() {
        public void Run() {
            socketConnection();
        });
    }
    t.start();
}

private void socketConnection() {
    try {
        serverSocket = new ServerSocket(9090);
        System.out.println("Listening: " + serverSocket.getLocalPort());

        while (!done) {
            try {
                final Socket socket = serverSocket.accept();
                Thread t = new Thread(new Runnable() {
                    public void Run() {
                        handle(socket);
                    }
                });
                t.start();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

private void handle(Socket socket) {
    if (socket == null) return;
    try {
        dataInputStream = new DataInputStream(socket.getInputStream());
        System.out.println("ip: " + socket.getInetAddress());
        System.out.println("message: " + dataInputStream.readUTF());
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (dataInputStream != null) {
            try {
                dataInputStream.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        try {
            socket.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


public void windowClosing(WindowEvent e) { 
    done = true; 
    socketServer.close(); 
} 

Your button click listener should call startServer(), then your window close function would set done = true and call socketServer.close().

Now you have one thread for the UI, one thread for the socket server, and one thread for each connection to the server.

Question:

It's a stupid novice question, I know. However, on the internet, there are only horrible examples of TCP servers. Like this:

try {
    Socket skt = new Socket("localhost", 1332);
    BufferedReader in = new BufferedReader(new
    InputStreamReader(skt.getInputStream()));
    System.out.print("Received string: '");

    while (!in.ready()) {}
    System.out.println(in.readLine()); // Read one line and output it
    System.out.print("'\n");
    in.close();
} catch(Exception e) {
    System.out.print("Whoops! It didn't work!\n");
}

How would I make this handle multiple clients, and also be able to constantly receive data instead of just closing the input stream?

There are no easily-found code snippets on the internet for it.


Answer:

The code you are showing is for a client, an application that talks to the server for a specific session.

For a server (like here) one uses a ServerSocket where you enter the specific port number. The socket listens to the port and each time someone aims to connect creates a connection. That connection is some kind of session where the server communicates with a client.

A minimal example of a server is thus something like:

class TCPServer {

   public static void main(String argv[]) throws Exception {
         int port = 8081;
         ServerSocket waiting = new ServerSocket(port);

         while(true) {
            Socket socket = waiting.accept(); //wait until a client shows up
            new SessionHandler(socket).start();//create new handler with the socket
            //start listening again
         }
      }
}

So you run the .accept in a while loop such that from the moment you received a connection with a client, you wait for another one.

And as SessionHandler

class SessionHandler extends Thread {

    private Socket socket;

    public SessionHandler (Socket socket) {
        this.socket = socket;
    }

    public void run () {
        //handle the session using the socket (example)
        BufferedReader inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
        DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());
        //read input from inFromClient, write to outToClient
    }

}

Now on an industrial TCP server, the story is of corse a bit more complicated: you will use a thread pool to prevent the server from getting too much work, etc.

Question:

I am using winsock and c++ 11 threads for the tcp server. For every client, I create a new ReceiveThread object, which has a std::thread object. Tcp client is in Java. I would like to create a simple broadcasting feature. (if someone sends a message, then the server forwards it to everybody). I use a wrapper class for the client sockets, which is including a mutex. (synchronized unordered_map). Every message is structured. The first byte is the length of the message, the second byte indicates the type, then the actual data. (the length of the data is known, the first byte was that)

[EDIT] My existing code works fine with one client. When the second client connects, he can also send messages and both of the clients get it. But if I send a message with the first client, the server receives it on second thread (the messages arrives correctly btw.), which belongs to the second client. After this, the server doesn't receive anything from the first client. (I removed the 'send forward to everybody' part, because the problem appears at receiving part, and I also edited the void ReceiveThread::receive(), now I call only once, and I will process it later)

Server.cpp

#include "Server.h"
#include <thread>
#include <string>
#include <winsock2.h>
#include <iostream>
#include "ReceiveThread.h"


using namespace std;

Server::Server(string ip, int port):ip(ip),port(port){
    init();
}

int Server::init(){

    //init the winsock library
    WSADATA wsaData;
    int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != NO_ERROR){
        cout << "Error WSAStartup!";
        return -1;
    }

    // Create a SOCKET for listening for incoming connection requests.
    listenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (listenSocket == INVALID_SOCKET) {
        cout << "Error at socket(): " << WSAGetLastError();
        WSACleanup();
        return -1;
    }

    //----------------------
    // The sockaddr_in structure specifies the address family,
    // IP address, and port for the socket that is being bound.
    sockaddr_in service;
    service.sin_family = AF_INET;
    service.sin_addr.s_addr = inet_addr(ip.c_str());
    service.sin_port = htons(port);

    if ( ::bind(listenSocket, (SOCKADDR*)&service, sizeof(service)) == SOCKET_ERROR) {
        cout << "Bind error.";
        closesocket(listenSocket);
        WSACleanup();
        return -1;
    }

    //----------------------
    // Listen for incoming connection requests.
    // on the created socket
    if (listen(listenSocket, 1) == SOCKET_ERROR) {
        cout << "Error listening on socket.\n";
        closesocket(listenSocket);
        WSACleanup();
        return -1;
    }

    // Accept connections
    acceptConnections();

}
void Server::acceptConnections(){
    // Create a SOCKET for accepting incoming request.
    SOCKET acceptSocket;
    cout << "Waiting for clients.";
    int counter = 0;
    while (1){
        acceptSocket = accept(listenSocket, NULL, NULL);
        if (acceptSocket == INVALID_SOCKET){
            cout << "Accept error";
            closesocket(listenSocket);
            WSACleanup();
            return;
        }
        else{
            clientSockets.add(acceptSocket);
            cout << "Client connected.";
            // create a new receive thread object for every client
            counter++;
            ReceiveThread receiveThread(clientSockets, acceptSocket,counter);
        }
    }
}

ReceiveThread.cpp

#include "ReceiveThread.h"
#include <winsock2.h>
#include "Message.h"
#include <iostream>
#include <string>

using namespace std;

ReceiveThread::ReceiveThread(ClientSockList &clients, SOCKET &socket,int counter) :clients(clients), socket(socket),counter(counter){
    //cout << clients.getList().size();
    receiveThread = new thread(&ReceiveThread::receive, this);
}

void ReceiveThread::terminateThread(){
    terminated = true;
}
void ReceiveThread::receive(){
    int res;
    while (!terminated){

        char recvbuf[BUF_SIZE]; // BU_SIZE = 1024
        int recv_len = 0;
        res = recv(socket, recvbuf + recv_len, BUF_SIZE - recv_len, 0);
        if (!checkSocket(res)) break;
        cout << "[" << counter << "] ";
        for (int i = 0; i < res; ++i){
            cout << recvbuf[i];
        }
        cout << endl;
    }
    //delete receiveThread;
}

bool ReceiveThread::checkSocket(int res){
    if (res == SOCKET_ERROR || res == 0){
        terminated = true;
        cout << endl << "Terminated" << endl;
        clients.remove(socket);
        closesocket(socket);
        return false;
    }
    else{
        return true;
    }
}

This is how I send messages from the client:

public void sendMessageForBroadcast(String message) throws IOException {
    //String m = buildMessage(message,Message.TYPE_BROADCAST);
    StringBuffer buff = new StringBuffer();
    buff.append(Character.toChars(message.length()));
    buff.append(Character.toChars(1));
    buff.append(message);

    //System.out.println("Sending message: " + m + "["+m.length()+"]");
    outputStream.write(buff.toString().getBytes("UTF8"));
    outputStream.flush();
}

[EDIT] Scenario:

  1. connect with client1
  2. send message with client1
  3. receive message on server (thread 1)
  4. connect with client2
  5. send message with client2
  6. receive message on server (thread 2)
  7. send message with client1
  8. receive message on server (thread 2)
  9. from now the server doesn't receive anything from client1

Answer:

You have a serious case of undefined behavior.

It all starts with this line:

ReceiveThread receiveThread(clientSockets, acceptSocket,counter);

That creates a ReceiveThread object (whose constructor creates your thread referencing this). The problem is that as soon as the declaration is made, the block of code the variable is declared in ends, which makes the variable go out of scope and destructs the object.

Once the object is destroyed, any code dereferencing the former objects this pointer (which is all code that uses the objects non-static member variables or functions) will dereference the pointer of a destructed object, leading to said undefined behavior.

I suggest you keep a collection of pointers to the thread object, both to keep the object in scope until it needs to be destructed, and to keep a reference to the object if you later need to use it from other threads.


There's also another possible source of undefined behavior, because I don't see you initialize the member variable terminated which means its value will be indeterminate when you reference it in the thread.

Question:

I'm looking for verification on the following:

In order to find out whether a server is up, I'm supposed to establish a TCP connection to the host:port combination of the server given to me. And in that case, "if a connection is established, then the service is up, otherwise - if the connection is refused, the service is down".

So, should i be satisfied that the server is up when getRemoteSocketAddress() of Socket returns an object and not null? That is, does the following code always print the accurate info to the console?

    Socket clientSocket = new Socket(hostName, port);
    System.out.println("To console: The server is " + (clientSocket.getRemoteSocketAddress()==null?"down.":"up.")  );

To me, it does. However, i haven't practical info on these things and won't make sure without a second opinion.

Note: I'm aware that, the server being up doesn't necessarily mean that it is accepting and processing requests. That goes by exchanging some greetings to see/hear one another on who's who and go from there based on the protocol in between. However, these aren't relevant on this one.

TIA


Answer:

You would not even need to call

clientSocket.getRemoteSocketAddress();

because the constructor call from:

Socket clientSocket = new Socket(hostName, port);

will try to connect to the socket and will throw an IOException if it fails to do so. So I would rather do this:

public boolean hostUp(String hostName, int port) {
    try {
        Socket clientSocket = new Socket(hostName, port);
        return true;
    } catch(IOException e) {
        return false;
    }
}

That should do the trick.

Question:

Assuming the following scenario, what would be the best/advised solution to the problem?

I have two streams, one which represensts a TCP connection and the other represents status of that TCP connection. Once the status changes (i.e. to disconnected), I would like to re-aquire the TCP connection.

My initial idea was to have those 2 streams, merge them and apply retryWith on the resultant Observable. The second stream is an instance of PublishSubject, which gives me a very handy way of failing. Now, that idea partially works, except for the fact that when I call onError() on the publisher, the connection stream (#1) keeps subscribing/unsubscribing until if runs out of the limit set by retryWhen.

I'm sure this problem must have been solved in the past, whereby you want to keep a TCP connection up and running, I'm just not sure how to progress from here. Any help would be appreciated.


Answer:

You don't need two streams. Just use one. The typical construction would involve Observable.using() to create socket, establish observable on that socket and to handle closing the socket and then chain that with retry() (normally with a delay).

Question:

I'm Trying to make a android TCP Server App which can get messages from my arduino board through wifi-shield.

I am newbie in java coding, so i downloaded the code from http://www.roman10.net/android-tcp-client-and-server-communication-programmingillustrated-with-example/

But it seems it doesnt work. It doesnt have any errors, but when I run it, it just doesnt respond.

Can anyone help me out? package com.example.androidserversocket;

package roman10.tutorial.tcpcommserver;
package roman10.tutorial.tcpcommserver;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.InterruptedIOException;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;

public class TcpServer extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        textDisplay = (TextView) this.findViewById(R.id.text1);
        textDisplay.setText("");
        runTcpServer();
    }
    private TextView textDisplay;
    private static final int TCP_SERVER_PORT = 5000;
    private void runTcpServer() {
        ServerSocket ss = null;
        try {
            ss = new ServerSocket(TCP_SERVER_PORT);
            //ss.setSoTimeout(10000);
            //accept connections
            Socket s = ss.accept();
            BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
            BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
            //receive a message
            String incomingMsg = in.readLine() + System.getProperty("line.separator");
            Log.i("TcpServer", "received: " + incomingMsg);
            textDisplay.append("received: " + incomingMsg);
            //send a message
            String outgoingMsg = "goodbye from port " + TCP_SERVER_PORT + System.getProperty("line.separator");
            out.write(outgoingMsg);
            out.flush();
            Log.i("TcpServer", "sent: " + outgoingMsg);
            textDisplay.append("sent: " + outgoingMsg);
            //SystemClock.sleep(5000);
            s.close();
        } catch (InterruptedIOException e) {
            //if timeout occurs
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (ss != null) {
                try {
                    ss.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
            }

Answer:

As far as I'm concerned onCreate() method will be called on the UI thread. It is no longer possible to run network operations on the UI thread. Hence you should replace

runTcpServer();

with

Thread t = new Thread(new Runnable() {
    @Override
    public void run() {
        runTcpServer();
    }
});
t.start();

You also need to add the following line to AndroidManifest.xml

<uses-permission android:name="android.permission.INTERNET" />

if you haven't done so already You can find more information about the issue here

Question:

I need help to receive messages for my client and I need a basic TCP Server to receive and send messages to the client.

This is my connection

public class TCPClient {

    private static final String TAG = TCPClient.class.getSimpleName();

    private Socket socket;
    private PrintWriter out;
    private boolean connected;

    public TCPClient() {
        socket = null;
        out = null;
        connected = false;
    }

    public void connect(Context context, String host, int port) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            new ConnectTask(context).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, host, String.valueOf(port));
        } else {
            new ConnectTask(context).execute(host, String.valueOf(port));
        }
    }

    public Boolean isConnected() {
        return connected;
    }

    private class ConnectTask extends AsyncTask<String, Void, Void> {

        private ProgressDialog pDialog;
        private Context context;

        public ConnectTask(Context context) {
            this.context = context;
            pDialog = new ProgressDialog(context);
            pDialog.setTitle(context.getString(R.string.login));
            pDialog.setMessage(context.getString(R.string.connecting) + "...");
            pDialog.setIndeterminate(false);
            pDialog.setCancelable(false);
            pDialog.show();
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

        @Override
        protected void onPostExecute(Void result) {
            if (connected) {
                MainActivity.session.publicname = "BETA-AY";
                MainActivity.session.status = "Hey, ich nutze AYCA!";
                showToast(context, context.getString(R.string.welcome) + " " + MainActivity.session.publicname);
                Intent intent = new Intent(context, ChatsActivity.class);
                context.startActivity(intent);
                ((Activity) context).finish();
            }

            if(pDialog.isShowing()) {
                pDialog.dismiss();
            }
            super.onPostExecute(result);
        }

        @Override
        protected Void doInBackground(String... params) {
            try {
                String host = params[0];
                int port = Integer.parseInt(params[1]);
                socket = new Socket(host, port);
                out = new PrintWriter(socket.getOutputStream(), true);
                connected = true;
            } catch (UnknownHostException e) {
                showToast(context, context.getString(R.string.connectionfail));
                Log.e(TAG, e.getMessage());
            } catch (IOException e) {
                showToast(context, context.getString(R.string.connectionfail));
                Log.e(TAG, e.getMessage());
            }
            return null;
        }

    }

    public void disconnect(Context context) {
        if (connected) {
            try {
                out.close();
                socket.close();
                connected = false;
            } catch (IOException e) {
                Log.e(TAG, e.getMessage());
            }
        }
    }

    public void send(String command) {
        if (connected) {
            out.println(command + ";");
        }
    }

    private void showToast(final Context context, final String message) {
        new Handler(context.getMainLooper()).post(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
            }
        });
    }
}

The connection has successfully, but I don't get a log when the client has connected.

This is my server class

public class Main {

    static int PORT;

    public static void main(String[] args) throws Exception {

        Logging.Write("Konfigurationen werden geladen...");
        Properties properties = new Properties();
        BufferedInputStream stream = new BufferedInputStream(new FileInputStream("Config.properties"));
        properties.load(stream);
        stream.close();

        PORT = Integer.valueOf(properties.getProperty("PORT")).intValue();

        Logging.Write("Verbindung wird aufgebaut...");

        String clientSentence;
        String capitalizedSentence;
        ServerSocket socket = new ServerSocket(PORT);

        while(true)
        {
            Socket connectionSocket = socket.accept();
            BufferedReader inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
            DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());
            clientSentence = inFromClient.readLine();

            System.out.println("Received: " + clientSentence);

            capitalizedSentence = clientSentence.toUpperCase() + '\n';
            outToClient.writeBytes(capitalizedSentence);
        }
    }

}

Answer:

I would start with testing the server; so stop it and then try to 'telnet ' to see if you canNOT get a connection. Then stop it - and check that you do get a connection.

If this works - see if you can enter a line - and if it is logged (i.e. you got all your end of line characters right; no \r or \n fun and games).

Once that work - try your client again. If it still fails; but connects - try having it send 10-20 chars and reading (just) 2 or 3 -- and verify that what you think arrives.

Question:

I'm trying to setup a simple web server in java, and I can read the web browser's request to my machine, but the web browser can't seem to read my reply. You can duplicate my issue by running the code below and attempting to connect to http://localhost:8080.

The browser doesn't acknowledge any response, and just keeps waiting forever. Does anyone know what is causing this? I suspect it's related to the output stream but I don't know what's wrong.

I'm running a slightly modified version of the code in this tutorial: https://javarevisited.blogspot.com/2015/06/how-to-create-http-server-in-java-serversocket-example.html

EDIT: I just tested the connection with curl localhost:8080 and it worked fine. No clue why the web browser has any issues. You're welcome to download and test this code on your own machine.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;

public class SimpleHttpServer {
    public static void main(String args[]) throws IOException {
        Socket client = null;
        try {
            ServerSocket server = new ServerSocket(8080);
            BufferedReader reader;

            System.out.println("Listening for connection on port 8080 ....");
            client = server.accept();
            System.out.println("Got connection.");

            while (true) { 
                reader = new BufferedReader(new InputStreamReader(client.getInputStream()));

                String temp = reader.readLine();
                while ( temp != null && !temp.isEmpty() ) {
                    System.out.println("<"+temp+">");
                    temp = reader.readLine();
                }

                Date today = new Date();
                String httpResponse = "HTTP/1.1 200 OK\r\n\r\n" + today;
                client.getOutputStream().write(httpResponse.getBytes());
                System.out.println("Sent: "+httpResponse);

                Thread.sleep(1000);
            }
        } catch (Exception e) {
            client.getOutputStream().close();
            client.getInputStream().close();
            client.close();
        }
    }
}

Answer:

You are missing required headers and you're not flushing the output.

Since you seem to want to keep the connection alive for multiple requests, you need to send header:

Connection: keep-alive

You also need to tell the browser what you're sending, and how much, so it knows when the response is complete:

Content-Type: text/plain
Content-Length: 999

Working code:

// ... existing code ...

Date today = new Date();
String content = today.toString();
String httpResponse = "HTTP/1.1 200 OK\r\n" +
                      "Content-Type: text/plain\r\n" +
                      "Content-Length: " + content.length() + "\r\n" +
                      "Connection: keep-alive\r\n" +
                      "\r\n" +
                      content;
client.getOutputStream().write(httpResponse.getBytes());
client.getOutputStream().flush();
System.out.println("Sent: "+httpResponse);

// ... existing code ...

Question:


Answer:

The way I do this is to broadcast a periodic "heartbeat" via multicast and listen for that. Nowadays the best practice is to use multicast DNS using something like jmDNS (https://github.com/openhab/jmdns).

Question:

I'm using a TCP java server to receive data from clients and send data back to the clients. The problem is that when the server writes faster to a client socket than the client can read, the server hangs/freezes and it won't process any of the data from the other clients anymore.

For example the server writes 3 kb/s to a client socket and the client can only read 1 kb/s. How do I recognize this, so I can close this socket and stop writing to it?

What is happening? Is data being buffered?

I use the following code to write data:

this.out_ = new PrintWriter(this.clientSocket_.getOutputStream(), true);

this.out_.print(msg);

Edit: complete code

Main.java

import java.net.Socket;
import java.net.SocketAddress;
import java.net.InetSocketAddress;
import java.io.IOException;
import java.util.HashMap;
import java.net.ServerSocket;
import java.net.SocketTimeoutException;

public class Main
{
    static ServerSocket serverSocket_;
    static HashMap<String, ServerInformation> servers_;
    static int verboseLevel_;
    static int threadTimeout_;
    static int masterPort_;
    static int serverNumber_;
    static int socketTimeOut_;

    static {
        Main.serverSocket_ = null;
        Main.servers_ = new HashMap<String, ServerInformation>();
        Main.verboseLevel_ = 5;
        Main.threadTimeout_ = 10;
        Main.masterPort_ = 6510;
        Main.serverNumber_ = 1;
        Main.socketTimeOut_ = 6000;
    }

    public static void main(final String[] args) {
        try {
            setupServerAndCleanup(Main.masterPort_);
            while (true) {
                handleIncomingConnection();
            }
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }

    static void setupServerAndCleanup(final int port) throws IOException {
        (Main.serverSocket_ = new ServerSocket()).setReuseAddress(true);
        Main.serverSocket_.bind(new InetSocketAddress(Main.masterPort_));
        System.out.println("Server socket up and running on port " + Main.masterPort_);
        Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
            @Override
            public void run() {
                if (Main.serverSocket_ != null) {
                    try {
                        Main.serverSocket_.close();
                        System.out.println("Server socket closed, port released");
                    }
                    catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }));
    }

    static void handleIncomingConnection() throws IOException {
        final Socket clientSocket = Main.serverSocket_.accept();
        clientSocket.setSoTimeout(Main.socketTimeOut_);
        final ClientThread client = new ClientThread(clientSocket);
        client.start();
    }

}

ClientThread.java

import java.util.Iterator;
    import java.io.IOException;
    import java.io.Reader;
    import java.io.InputStreamReader;
    import java.util.regex.Pattern;
    import java.io.BufferedReader;
    import java.io.PrintWriter;
    import java.net.Socket;
    import java.net.SocketTimeoutException;

    public class ClientThread extends Thread
    {
    Socket clientSocket_;
    String clientIp_;
    String serverIp_;
    ServerInformation server_;
    PrintWriter out_;
    BufferedReader in_;
    boolean prepareTermination_;
    boolean terminated_;
    private static final Pattern numberPattern;

    static {
        numberPattern = Pattern.compile("\\d+");
    }

    public ClientThread(final Socket sock) {
        this.clientSocket_ = sock;
        this.clientIp_ = this.clientSocket_.getRemoteSocketAddress().toString();
        this.serverIp_ = null;
        this.server_ = null;
        this.prepareTermination_ = false;
        this.terminated_ = false;
    }

    @Override
    public void run() {
        try {
            this.out_ = new PrintWriter(this.clientSocket_.getOutputStream(), true);
            this.in_ = new BufferedReader(new InputStreamReader(this.clientSocket_.getInputStream()));

            long lastActionTime = System.currentTimeMillis();
            while (true) {

                if (this.in_.ready() || System.currentTimeMillis() - lastActionTime >= 1000 * Main.threadTimeout_) {
                    if (System.currentTimeMillis() - lastActionTime >= 1000 * Main.threadTimeout_) {
                        //this.logDebugMessage(3, "Thread was killed due to prolonged inactivity (" + Main.threadTimeout_ + " seconds)");
                        this.terminateThread();
                        return;
                    }

                    final String tempInputLine;
                    if(((tempInputLine = this.in_.readLine()) == null )){
                        this.terminateThread(); //end thread                        
                        return;             
                    }
                    else
                    {                   
                        lastActionTime = System.currentTimeMillis();                    
                        final String inputLine = tempInputLine.trim();
                        if (ClientThread.numberPattern.matcher(inputLine).matches()){
                        final int val = Integer.parseInt(inputLine);
                        switch (val) {
                          case 1: { //send data to other players
                                final int parseCount = Integer.parseInt(this.in_.readLine().trim());
                                final StringBuilder msg = new StringBuilder();
                                for (int j = 0; j < parseCount; ++j) {
                                    msg.append(String.valueOf(this.in_.readLine().trim()) + "|");
                                }
                                for (final ClientThread thread2 : this.server_.ipToClientThread_.values()) {
                                    if (thread2 != this) {
                                        thread2.out_.print(msg);
                                        thread2.out_.flush();
                                    }
                                }
                                //this.logDebugMessage(5, "Packet for others: '" + msg.toString() + "'");
                                break;
                            }   

                            case 2: { //remove game server
                                //this.logDebugMessage(1, "A game server has been deleted, ip: " + ipServer);
                                Main.servers_.remove(this.server_.ip_);
                                this.serverIp_ = null;
                                for (final ClientThread thread : this.server_.ipToClientThread_.values()) {
                                    thread.prepareTermination_ = true;
                                }
                                this.terminateThread();
                                return;
                            }
                            case 3: { //connect new client
                                final String ipServer = this.in_.readLine().trim();
                                final String ipClient = this.in_.readLine().trim(); 
                                this.logDebugMessage(1, "A client wishes to connect to a server, client: " + ipClient + ", server: " + ipServer);
                                final ServerInformation info = Main.servers_.getOrDefault(ipServer, null);
                                if (info == null) {
                                    System.out.println("Connection to the server failed, no such server in the server list");
                                   this.out_.print("*" + 1 + "|" + 1 + "~" + "|");
                                   this.out_.flush();                                   
                                break;
                                }
                                this.server_ = info;
                                this.server_.ipToClientThread_.put(ipClient, this);
                                this.logDebugMessage(1, "Connection success");
                                this.logDebugMessage(5,"Map: " + this.server_.ipToClientThread_);
                                    this.out_.print("*" + 1 + "|" + 2 + "~" + "|");
                                    this.out_.flush();
                                break;
                            }         
                            case 4: { //disconnect client
                                final String ipClient = this.in_.readLine().trim();
                                this.server_.ipToClientThread_.remove(ipClient);
                                this.logDebugMessage(1, String.valueOf(ipClient) + " disconnected from the server at " + this.server_.ip_);
                                this.serverIp_ = null;
                                this.terminateThread();
                                return;
                            }                   

                            case 5: { //host create new game
                                if (Main.serverNumber_ > 1000000) {
                                Main.serverNumber_ = 10;    
                                }
                                Main.serverNumber_ += 1;                                
                                final String ipServer = Integer.toString(Main.serverNumber_); //unique server number
                                final String ipHost =  this.in_.readLine().trim(); //host 
                                final String name = this.in_.readLine().trim(); //Server name
                                final String description = this.in_.readLine().trim(); //class
                                final String servervar1 = this.in_.readLine().trim(); //max players
                                final String servervar3 = this.in_.readLine().trim(); //current lap
                                final String servervar4 = this.in_.readLine().trim(); //total laps
                                final String servervar5 = this.in_.readLine().trim(); //status
                                final String servervar6 = this.in_.readLine().trim(); //Password
                                final String servervar7 = this.in_.readLine().trim(); //Online version
                                final String servervar8 = this.in_.readLine().trim(); //Game server
                                final long servervar9 = System.currentTimeMillis(); //server creation time
                                //this.logDebugMessage(1, "A game server has been registered, ip: " + ipServer + ", name: " + name + ", description: " + description + ", servervar1: " + servervar1);
                                final ServerInformation gameServer = new ServerInformation(name, servervar1, servervar3, servervar4, servervar5, servervar6, servervar7, servervar8, servervar9, ipHost, ipServer, this.clientSocket_, this.out_, this.in_);
                                gameServer.description_ = description;
                                gameServer.ipToClientThread_.put(ipHost, this);
                                this.server_ = gameServer;
                                Main.servers_.put(ipServer, gameServer);
                                this.serverIp_ = ipServer;
                                break;
                            }                               
                            default: {
                                this.logDebugMessage(0, "Unrecognized case: '" + inputLine + "', " + val);
                                break;
                            }
                        }
                    }
                    else if (inputLine.length() > 0) {
                        this.logDebugMessage(0, "Unformated '" + inputLine + "'");
                        if (this.server_ != null) {
                            this.server_.out_.print(inputLine);
                            this.server_.out_.flush();
                        }
                    }
                    if (this.prepareTermination_) {
                        this.terminateThread();
                        return;
                    }
                    continue;
                    }
                }
            }
        }
        catch (SocketTimeoutException e) {
            e.printStackTrace();
            try {
                this.terminateThread();
            }
            catch (IOException e2) {
                e2.printStackTrace();
            }
        }
        catch (IOException e3) {
            e3.printStackTrace();
            try {
                this.terminateThread();
            }
            catch (IOException e4) {
                e4.printStackTrace();
            }
        }
    }

    //debug messages
    void logDebugMessage(final int requiredVerbose, final String msg) {
        if (Main.verboseLevel_ >= requiredVerbose) {
            System.out.println("[" + this.clientIp_ + "]  " + msg);
        }
    }

    //terminate thread
    void terminateThread() throws IOException {
        if (!this.terminated_) {
            if (this.serverIp_ != null) {
                Main.servers_.remove(this.serverIp_);
            }
            this.clientSocket_.close();
            this.in_.close();
            this.out_.close();
            this.logDebugMessage(3, "Cleanup successful");
            this.terminated_ = true;
        }
    }
}

Answer:

What is happening? Is data being buffered?

TCP write buffer will overflow.

And what happens depends on the Channel type you are using. If the channel is blocking in the blocking mode the Thread writing data will block waiting the client to receive data.

If the channel is in non-blocking mode y̶o̶u̶ ̶a̶r̶e̶ ̶m̶o̶s̶t̶ ̶l̶i̶k̶e̶l̶y̶ ̶t̶o̶ ̶r̶e̶c̶e̶i̶v̶e̶ ̶I̶O̶E̶x̶c̶e̶p̶t̶i̶o̶n̶ the write returns zero as specified in JavaDoc https://docs.oracle.com/javase/7/docs/api/java/nio/channels/SocketChannel.html#write(java.nio.ByteBuffer)

A socket channel in non-blocking mode, for example, cannot write any more bytes than are free in the socket's output buffer.

Socket's OutputStream is blocking by definition.

Question:

Hi I'm trying to run simple server-client game. Server is in C, client in java (it's school project I can't change that). My client is Windows 7 64bit and server is running on the Virtualbox (Debian 32bit) I'm using bridged connection via WiFi. I'm trying to just simply accept new connection and create new thread for it using TCP and sockets.

When I compare if client_socket is > 0 it's alright and client is connected. But when I put some code in the if block (commented part in code bellow) socket is -1 and it can't connect (it doesn't even reach the code). It doesn't matter what code it is even if it is int x = 0 it will still not work. It seems like only printf() is OK. Thanks for any kind of response.

perror() prints "Invalid argument".

Here is my code for C server:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>


void *serve_request(void *arg){

    printf("Thread is running.\n");
}


int start_server (void){
    int server_socket;
    int client_socket;
    int return_value;
    char cbuf;
    int *th_socket;
    struct sockaddr_in server_addr;
    struct sockaddr_in client_addr;
    socklen_t client_addr_len;
    pthread_t thread_id;;

    server_socket = socket(AF_INET, SOCK_STREAM, 0);

    if (server_socket < 0) return -1;

    memset(&server_addr, 0, sizeof(struct sockaddr_in));

    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(10001);
    server_addr.sin_addr.s_addr = INADDR_ANY;

    return_value = bind(server_socket, (struct sockaddr *)&server_addr, sizeof(struct sockaddr_in));

    if (return_value == 0)
     printf("Bind OK\n");
    else{
     printf("Bind Error\n");
     return -1;
    }

    return_value = listen(server_socket, 5);
    if (return_value == 0)
     printf("Listen OK\n");
    else{
     printf("Listen Error\n");
     return -1;
    }


    while(1){

     client_socket = accept(server_socket, (struct sockaddr *)&client_addr, &client_addr_len);

        printf("Socket number: %d\n", client_socket);

     if (client_socket >= 0 ) {

         printf("Socket OK\n");

         // #### PROBLEM PART ####
         //th_socket=malloc(sizeof(int));
         //*th_socket=client_sock;

         //thread_id = 0;
         //pthread_create(&thread_id, NULL, (void *)&serve_request, (void *)th_socket);

     } else {
         printf("Socket Error\n");
         return -1;
     }

    }

return 0;
}   

Answer:

You need to initialize client_addr_len to the size of the client_addr structure. The accept function uses that argument to determine what kind of address structure is passed.

What you have now is undefined behavior since uninitialized (non-static) local variables have indeterminate values (the contents of uninitialized non-static variables will be seemingly random).