Hot questions for Using Transmission Control Protocol in port

Question:

Is there a public constant for the maximum TCP port number (65535) defined in java or a common library such as Apache Commons, that I could refer to from my code (instead of using the integer hardcoded)?


Answer:

I'm afraid there is none you can use.

Looking at the source code of Java 8 I see the following code used by the Socket class to verify a valid port in several functions:

private static int checkPort(int port) {
    if (port < 0 || port > 0xFFFF)
        throw new IllegalArgumentException("port out of range:" + port);
    return port;
}

This can be found in java.net.InetSocketAddress.checkPort(int)

As you can see Java itself doesn't use a named constant either.

A search of the code turns up the following hit in java.net.HostPortrange:

static final int PORT_MIN = 0;
static final int PORT_MAX = (1 << 16) -1;

But as you can see this isn't a public reference. Another private reference turns up in java.net.SocketPermission.

So after the inspection above, I conclude there is none available in the Java API.

Question:

I have a TcpServer class that is responsible to, well, act like a tcp server. You can find the class below :

public class TcpServer {
    private ServerSocket serverSocket;
    private Socket socket;
    private int locallyBoundPort;

    public TcpServer() {


    }

    public TcpServer(int locallyBoundPort) {
        try {
            this.serverSocket = new ServerSocket(locallyBoundPort);
            serverSocket.setReuseAddress(true);
        } catch (IOException e) {
            System.out.println("Error at binding to port TCP : " + locallyBoundPort + "...cause : " + e.getMessage());
        }
        socket = null;

    }

    public void accept() {
        try {
            socket = serverSocket.accept();
            socket.setReuseAddress(true);
        } catch (IOException e) {
            System.out.println("Error at accept : " + locallyBoundPort);
        }
    }



    public void send(Data data) throws IOException {
        if(socket != null) {

            ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
            out.writeObject(data);

        }
    }

    public Data receive() throws ClassNotFoundException, IOException {
        if(socket != null) {

                ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
                return (Data) in.readObject();

        } else {
            return null;
        }
    }

    public boolean bind(int port) throws IOException {
        try {
            this.serverSocket = new ServerSocket(port);
            this.locallyBoundPort = port;
        } catch(IOException e) {
            return false;
        }
        return true;

    }

    public void close() {
        try {
            serverSocket.close();
            socket.close();
        } catch (IOException e) {
            OzumUtils.print("IOException in close, TcpServer");
        }

    }

    public int getLocallyBoundPort() {
        return locallyBoundPort;
    }

    public Socket getSocket() {
        return socket;
    }

    public ServerSocket getServerSocket() {
        return serverSocket;
    }
}

And I have a code piece that does this :

TcpServer tcpServer = new TcpServer(LocalPort);
while(1)
{
    tcpServer.accept();
    Thread thread = new Thread(new runnable(tcpServer));
    thread.start();
    tcpServer = new TcpServer(LocalPort);
}

However I am getting a port already in use error. I thought two different socket instances could listen to the same port as multiplexing allows two connections through the same port when the connector has different ip or port ? What am I missing?


Answer:

You cannot bind two tcp server sockets to the same port. reuseAddress is really for client sockets, and it does not work the way you think it does ... and the way you are using it would not do anything at all either way (because you are setting it after binding).

You don't really need to bind twice to the same port either. Just remove this line tcpServer = new TcpServer(LocalPort); from the bottom of your while loop, and you'll be all set.

The way this works is that you bind your server socket once and listen to the port. When a connection arrives, it forks a client socket for you to communicate with the client, and the original server socket continues to listen for more connections.

Basically, you need to remove the socket member (and any other state) from your TcpServer, and make the accept method return the accepted socket. Then make your runnable take that socket as a parameter instead of the TcpServer, and use that to serve the client connection. Then just keep calling accept in the loop, and forking threads for new connections same way you do know, except do not recreate the server every time.

Or, alternatively, remove the server socket and port from TcpServer, create the socket outside the loop, then while(true) call accept on it, create a new TcpServer with the returned client socket, and use it in a thread to process the connection.

Do not forget to close client sockets after you are done with them.

Question:

I just downloaded this project:

https://github.com/oktadeveloper/okta-spring-boot-2-angular-5-example

explained on this tutorial:

https://developer.okta.com/blog/2017/12/04/basic-crud-angular-and-spring-boot

But when I try to run the server with the recommended command:

./mvnw spring-boot:run

I get the following output:

David@HP /cygdrive/d/wamp64/www/external/okta.example.com/server
$ ./mvnw spring-boot:run
/cygdrive/d/wamp64/www/external/okta.example.com/server
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------< com.okta.developer:demo >-----------------------
[INFO] Building demo 0.0.1-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] >>> spring-boot-maven-plugin:2.0.1.RELEASE:run (default-cli) > test-compile @ demo >>>
[INFO]
[INFO] --- maven-resources-plugin:3.0.1:resources (default-resources) @ demo ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.7.0:compile (default-compile) @ demo ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:3.0.1:testResources (default-testResources) @ demo ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory D:\wamp64\www\external\okta.example.com\server\src\test\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.7.0:testCompile (default-testCompile) @ demo ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] <<< spring-boot-maven-plugin:2.0.1.RELEASE:run (default-cli) < test-compile @ demo <<<
[INFO]
[INFO]
[INFO] --- spring-boot-maven-plugin:2.0.1.RELEASE:run (default-cli) @ demo ---

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.0.1.RELEASE)

2018-07-12 20:35:06.400  INFO 2812 --- [           main] com.okta.developer.demo.DemoApplication  : Starting DemoApplication on HP with PID 2812 (D:\wamp64\www\external\okta.example.com\server\target\classes started by David in D:\wamp64\www\external\okta.example.com\server)
2018-07-12 20:35:06.410  INFO 2812 --- [           main] com.okta.developer.demo.DemoApplication  : No active profile set, falling back to default profiles: default
2018-07-12 20:35:06.499  INFO 2812 --- [           main] ConfigServletWebServerApplicationContext : Refreshing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@ae5e109: startup date [Thu Jul 12 20:35:06 CDT 2018]; root of context hierarchy
2018-07-12 20:35:08.603  INFO 2812 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Overriding bean definition for bean 'httpRequestHandlerAdapter' with a different definition: replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration; factoryMethodName=httpRequestHandlerAdapter; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration; factoryMethodName=httpRequestHandlerAdapter; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/data/rest/webmvc/config/RepositoryRestMvcConfiguration.class]]
2018-07-12 20:35:09.470  INFO 2812 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$29541950] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2018-07-12 20:35:10.064  INFO 2812 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2018-07-12 20:35:10.114  INFO 2812 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]

...

Using generated security password: 4f87a125-b4d8-47c0-9a24-bb5fb3b2a658

2018-07-12 20:35:17.428  INFO 2812 --- [           main] o.s.s.web.DefaultSecurityFilterChain     : Creating filter chain: org.springframework.security.web.util.matcher.AnyRequestMatcher@1, [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@3052460, org.springframework.security.web.context.SecurityContextPersistenceFilter@76eee741, org.springframework.security.web.header.HeaderWriterFilter@622ee9f2, org.springframework.security.web.authentication.logout.LogoutFilter@59d663e0, org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter@a2d3781, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@7492ef4f, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@77d8457b, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@1e249f41, org.springframework.security.web.session.SessionManagementFilter@43e1a956, org.springframework.security.web.access.ExceptionTranslationFilter@7130b0d2, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@384e11db]
2018-07-12 20:35:17.539  INFO 2812 --- [           main] o.s.b.a.e.web.EndpointLinksResolver      : Exposing 2 endpoint(s) beneath base path '/actuator'
2018-07-12 20:35:17.558  INFO 2812 --- [           main] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/actuator/health],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
2018-07-12 20:35:17.558  INFO 2812 --- [           main] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/actuator/info],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
2018-07-12 20:35:17.558  INFO 2812 --- [           main] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/actuator],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto protected java.util.Map<java.lang.String, java.util.Map<java.lang.String, org.springframework.boot.actuate.endpoint.web.Link>> org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping.links(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
2018-07-12 20:35:17.660  INFO 2812 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2018-07-12 20:35:17.665  INFO 2812 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Bean with name 'dataSource' has been autodetected for JMX exposure
2018-07-12 20:35:10.114  INFO 2812 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.5.29
2018-07-12 20:35:17.684  INFO 2812 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Located MBean 'dataSource': registering with JMX server as MBean [com.zaxxer.hikari:name=dataSource,type=HikariDataSource]
2018-07-12 20:35:17.755 ERROR 2812 --- [           main] o.apache.catalina.core.StandardService   : Failed to start connector [Connector[HTTP/1.1-8080]]

org.apache.catalina.LifecycleException: Failed to start component [Connector[HTTP/1.1-8080]]
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) ~[tomcat-embed-core-8.5.29.jar:8.5.29]
        at org.apache.catalina.core.StandardService.addConnector(StandardService.java:225) ~[tomcat-embed-core-8.5.29.jar:8.5.29]
        at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.addPreviouslyRemovedConnectors(TomcatWebServer.java:256) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
        at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.start(TomcatWebServer.java:198) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.startWebServer(ServletWebServerApplicationContext.java:300) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.finishRefresh(ServletWebServerApplicationContext.java:162) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:553) [spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:395) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:327) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1255) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1243) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
        at com.okta.developer.demo.DemoApplication.main(DemoApplication.java:23) [classes/:na]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_172]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_172]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_172]
        at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_172]
        at org.springframework.boot.maven.AbstractRunMojo$LaunchRunner.run(AbstractRunMojo.java:496) [spring-boot-maven-plugin-2.0.1.RELEASE.jar:2.0.1.RELEASE]
        at java.lang.Thread.run(Thread.java:748) [na:1.8.0_172]
Caused by: org.apache.catalina.LifecycleException: Protocol handler start failed
        at org.apache.catalina.connector.Connector.startInternal(Connector.java:1020) ~[tomcat-embed-core-8.5.29.jar:8.5.29]
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) ~[tomcat-embed-core-8.5.29.jar:8.5.29]
        ... 19 common frames omitted
Caused by: java.net.BindException: Address already in use: bind
        at sun.nio.ch.Net.bind0(Native Method) ~[na:1.8.0_172]
        at sun.nio.ch.Net.bind(Net.java:433) ~[na:1.8.0_172]
        at sun.nio.ch.Net.bind(Net.java:425) ~[na:1.8.0_172]
        at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:223) ~[na:1.8.0_172]
        at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:74) ~[na:1.8.0_172]
        at org.apache.tomcat.util.net.NioEndpoint.bind(NioEndpoint.java:210) ~[tomcat-embed-core-8.5.29.jar:8.5.29]
        at org.apache.tomcat.util.net.AbstractEndpoint.start(AbstractEndpoint.java:1150) ~[tomcat-embed-core-8.5.29.jar:8.5.29]
        at org.apache.coyote.AbstractProtocol.start(AbstractProtocol.java:591) ~[tomcat-embed-core-8.5.29.jar:8.5.29]
        at org.apache.catalina.connector.Connector.startInternal(Connector.java:1018) ~[tomcat-embed-core-8.5.29.jar:8.5.29]
        ... 20 common frames omitted

2018-07-12 20:35:17.770  INFO 2812 --- [           main] o.apache.catalina.core.StandardService   : Stopping service [Tomcat]
2018-07-12 20:35:17.815  INFO 2812 --- [           main] ConditionEvaluationReportLoggingListener :

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2018-07-12 20:35:17.820 ERROR 2812 --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   :

***************************
APPLICATION FAILED TO START
***************************

Description:

The Tomcat connector configured to listen on port 8080 failed to start. The port may already be in use or the connector may be misconfigured.

Action:

Verify the connector's configuration, identify and stop any process that's listening on port 8080, or configure this application to listen on another port.

2018-07-12 20:35:17.820  INFO 2812 --- [           main] ConfigServletWebServerApplicationContext : Closing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@ae5e109: startup date [Thu Jul 12 20:35:06 CDT 2018]; root of context hierarchy
2018-07-12 20:35:17.825  INFO 2812 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Unregistering JMX-exposed beans on shutdown
2018-07-12 20:35:17.825  INFO 2812 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Unregistering JMX-exposed beans
2018-07-12 20:35:17.835  INFO 2812 --- [           main] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2018-07-12 20:35:17.835  INFO 2812 --- [           main] .SchemaDropperImpl$DelayedDropActionImpl : HHH000477: Starting delayed drop of schema as part of SessionFactory shut-down'
2018-07-12 20:35:17.850  INFO 2812 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2018-07-12 20:35:17.860  INFO 2812 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.
[WARNING]
java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke (Method.java:498)
    at org.springframework.boot.maven.AbstractRunMojo$LaunchRunner.run (AbstractRunMojo.java:496)
    at java.lang.Thread.run (Thread.java:748)
Caused by: org.springframework.boot.web.embedded.tomcat.ConnectorStartFailedException: Connector configured to listen on port 8080 failed to start
    at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.checkThatConnectorsHaveStarted (TomcatWebServer.java:228)
    at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.start (TomcatWebServer.java:203)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.startWebServer (ServletWebServerApplicationContext.java:300)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.finishRefresh (ServletWebServerApplicationContext.java:162)
    at org.springframework.context.support.AbstractApplicationContext.refresh (AbstractApplicationContext.java:553)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh (ServletWebServerApplicationContext.java:140)
    at org.springframework.boot.SpringApplication.refresh (SpringApplication.java:759)
    at org.springframework.boot.SpringApplication.refreshContext (SpringApplication.java:395)
    at org.springframework.boot.SpringApplication.run (SpringApplication.java:327)
    at org.springframework.boot.SpringApplication.run (SpringApplication.java:1255)
    at org.springframework.boot.SpringApplication.run (SpringApplication.java:1243)
    at com.okta.developer.demo.DemoApplication.main (DemoApplication.java:23)
    at sun.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke (Method.java:498)
    at org.springframework.boot.maven.AbstractRunMojo$LaunchRunner.run (AbstractRunMojo.java:496)
    at java.lang.Thread.run (Thread.java:748)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 19.171 s
[INFO] Finished at: 2018-07-12T20:35:17-05:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:2.0.1.RELEASE:run (default-cli) on project demo: An exception occurred while running. null: InvocationTargetException: Connector configured to listen on port 8080 failed to start -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException

As you can see, there is one line that says:

The Tomcat connector configured to listen on port 8080 failed to start. 

Any idea on how to make the server work?

Thanks!


Answer:

It says "BindException: Address already in use: bind", you must already be running some application under port 8080. Try to terminate that server and start again, or use a different port for this application, like 8081. If you can't check which app is using port 8080 already, use the following command

netstat -anob 

You can now check and kill the application through task manager, assuming you're on windows.

Question:

I have a java process that make use of ServerSocket API (Java 8) and bind to the local port 12000. Process runs under a Windows service Wrapper (exe4j). I have a scheduled task that runs at 4am that stop the service and restart it after a couple of seconds. That process is installed over 400 customers locations.

Everything was running smooth until about last friday. A few processes failed to restart properly at 4am. On 2 servers I was able to connect and verify, the restart failed with both a "Address already in use: JVM_Bind". It's seems that the port 12000 was still in use by a the system.

I used every tools (processexplorer, tcpview, netstat -ano, name it) I know to try to find the process... with no success. Only a machine reboot fixed the issue. But problem came back a night or two later.

After some reading, I saw that I was doing a sockect.accept() with infinite timeout so I changed it for socket.setSoTimeout(15000); socket.accept(); instead.

I putted the new version in place but the problem is still there.

Machines got Windows updates. I did tests with the same Windows version fully updated but I can't reproduce.

I'm out of solution now.

Any ideas Thanks


Answer:

A windows update affected the release of address/port after process shutdown.

Refer to Address Bind exception in Tomcat for solution.

Question:

I am working on a device which would work to measure some readings through sensors. Device is operated by an Android app. I have to take readings from TCP layer. This is the code to send data on TCP

TcpClient.java

import android.util.Log;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;

/**
* Created by shahbaz on 25/4/17.
*/

 public class TcpClient {

 public static final String SERVER_IP = "192.168.1.76"; //server IP address
 public static final int SERVER_PORT = 1800;
 // message to send to the server
 private String mServerMessage;
 // sends message received notifications
 private OnMessageReceived mMessageListener = null;
 // while this is true, the server will continue running
 private boolean mRun = false;
 // used to send messages
 private PrintWriter mBufferOut;
 // used to read messages from the server
 private BufferedReader mBufferIn;

 /**
  * Constructor of the class. OnMessagedReceived listens for the messages received from server
  */
 public TcpClient(OnMessageReceived listener) {
    mMessageListener = listener;
 }

/**
 * Sends the message entered by client to the server
 *
 * @param message text entered by client
 */
public void sendMessage(String message) {
    if (mBufferOut != null && !mBufferOut.checkError()) {
        mBufferOut.println(message);
        mBufferOut.flush();
    }
}

/**
 * Close the connection and release the members
 */
public void stopClient() {

    mRun = false;

    if (mBufferOut != null) {
        mBufferOut.flush();
        mBufferOut.close();
    }

    mMessageListener = null;
    mBufferIn = null;
    mBufferOut = null;
    mServerMessage = null;
}

public void run() {

    mRun = true;

    try {
        //here you must put your computer's IP address.
        InetAddress serverAddr = InetAddress.getByName(SERVER_IP);

        Log.e("TCP Client", "C: Connecting...");

        //create a socket to make the connection with the server
        Socket socket = new Socket(serverAddr, SERVER_PORT);

        try {

            //sends the message to the server
            mBufferOut = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);

            //receives the message which the server sends back
            mBufferIn = new BufferedReader(new InputStreamReader(socket.getInputStream()));


            //in this while the client listens for the messages sent by the server
            while (mRun) {

                mServerMessage = mBufferIn.readLine();

                if (mServerMessage != null && mMessageListener != null) {
                    //call the method messageReceived from MyActivity class
                    mMessageListener.messageReceived(mServerMessage);
                }

            }

            Log.e("RESPONSE FROM SERVER", "S: Received Message: '" + mServerMessage + "'");

        } catch (Exception e) {

            Log.e("TCP", "S: Error", e);

        } finally {
            //the socket must be closed. It is not possible to reconnect to this socket
            // after it is closed, which means a new socket instance has to be created.
            socket.close();
        }

    } catch (Exception e) {

        Log.e("TCP", "C: Error", e);

    }

}

   //Declare the interface. The method messageReceived(String message) will must be implemented in the MyActivity
   //class at on asynckTask doInBackground
   public interface OnMessageReceived {
    public void messageReceived(String message);
}

}

Packet Structure

Packet format contains, While communicating with the device on TCP, boundaries between packets are not identified, in this case if the packets are out of sequence or if any of the packets is missed one can identify a new packet using ‘header start’. So, first 2 bytes in the packet represent the start of the packet.

Header start: Two-byte field that indicates the start of every packet. 0x55AA is a 2 bytes number used as header start.

Protocol version: One-byte field to specify the version of the protocol in use. Version specified in the payload will decide the payload structure. At any given moment a device will support single protocol version. Present protocol version is ‘1’.

DSN: Sequence number is 1-byte field which will identify the packet uniquely. Requester of the packet will have to fill this field in request payload; responder has to fill the same unique identifier in the response payload.

Request Id: One-byte field specifies the command id. The parsing of the payload will be done on the basis of the command id. In case of request payload this field will be non zero and in case of response it will be zero.

Payload length: Two-byte field specifies the length of the payload in bytes. It specifies the number of bytes followed payload length field. In the payload length, header length and CRC is not included. Currently, Max payload length supported by gateway device is 512 (bytes). CRC: 1 byte field which will be calculated by XORing all the bytes and add the XOR count of 0.

And it is working. But according to docs I have to send packet using binary communication protocol. Including header start, payload data, etc. How can I send these params in packet structure? How can I create packet?

Any help is appreciated.


Answer:

The main mistake was that I was not thinking much about size of primitive data types.

byte = 1 byte

short = 2 bytes

int = 4 bytes

long = 8 bytes

float = 4 bytes

double = 8 bytes

char = 2 byte

After referencing the size of primitive datatypes I realised we should track the size and index of packet because we are dealing with byte array.

TcpPacket.java

public class TcpPacket {

private static int header_start =  0x55AA;

private static int protocol_version = 1;

private PacketUtils packetUtils = new PacketUtils();






 public byte[] getHandshakePacket()
 {
    int request_id = 1;

    byte[] header_data = packetUtils.ItoBA2(header_start);
    byte[] payload_data = packetUtils.ItoBA4(packetUtils.getDateTime());
    byte[] payload_length = packetUtils.ItoBA2(4);


    byte[] a_data = new byte[]{header_data[0], header_data[1], (byte) protocol_version, packetUtils.getDSN(), (byte) request_id, payload_length[0], payload_length[1],
            payload_data[0], payload_data[1], payload_data[2], payload_data[3]};

    byte[] b_data = new byte[]{ packetUtils.getCRC(a_data)};

    byte[] packet_data = packetUtils.concatBytes(a_data,b_data);


    return packet_data;
 }

}

PacketUtils.java

public class PacketUtils {



public byte[] ItoBA4(int value) {       // integer to bytes function (return byte array of 4 bytes)
    return new byte[] {
            (byte)(value >>> 24),
            (byte)(value >>> 16),
            (byte)(value >>> 8),
            (byte)value};
}


public byte[] ItoBA2(int value) {   // integer to bytes function (return byte array of 2 bytes)
    return new byte[] {
            (byte)(value >>> 8),
            (byte)value};
}


public byte getDSN()    // return one byte random number
{
    char[] chars = "1234567890".toCharArray();
    StringBuilder sb = new StringBuilder();
    Random random = new Random();
    for (int i = 0; i < 1; i++) {
        char c = chars[random.nextInt(chars.length)];
        sb.append(c);
    }
    byte output = Byte.valueOf(sb.toString());
    return output;
}



public byte getCRC(byte[] packet)   //  required CRC function (return byte)
{
    try
    {
        if (packet == null)
        {
            //Logger.Error("empty packet received");
            return (byte)0;
        }

        byte XORCheckSum = 0;
        byte zeroCount = 0;
        byte FFCount = 0;

        for (int i = 0; i < packet.length; i++)
        {
            XORCheckSum ^= packet[i];
            if (packet[i] == (byte) 0)
            {
                zeroCount++;
                continue;
            }
            if (packet[i] == (byte)255)
            {
                FFCount++;
                continue;
            }
        }

        XORCheckSum ^= zeroCount;
        XORCheckSum ^= FFCount;
        return XORCheckSum;
    }
    catch (Exception ex)
    {
        //Logger.Error(ex);
        return (byte)0;
    }
}



byte[] concatBytes(byte[]...arrays)     //  concatenate byte arrays
{
    // Determine the length of the result array
    int totalLength = 0;
    for (int i = 0; i < arrays.length; i++)
    {
        totalLength += arrays[i].length;
    }

    // create the result array
    byte[] result = new byte[totalLength];

    // copy the source arrays into the result array
    int currentIndex = 0;
    for (int i = 0; i < arrays.length; i++)
    {
        System.arraycopy(arrays[i], 0, result, currentIndex, arrays[i].length);
        currentIndex += arrays[i].length;
    }

    return result;
}

public int getDateTime()
{
    int dateInSec = (int) (System.currentTimeMillis() / 1000);
    return dateInSec;

}



}

Question:

Current Situation

  • On the linux server several jars are running with sockets - listening and responding with string messages
  • A new war running in an wildfly application server is delegating requests to these sockets
  • The WAR is using spring and especially spring integration with annotations

I have a configuration class holding the services @Configuration / @EnableIntegration /@IntegrationComponentScan

I've created a messaging gateway

@MessagingGateway(defaultRequestChannel = "testGateway")
public interface TestGateway{
    public Future<String> sendMessage(String in);
}

The application should sending requests and receiving it as a client. I've created a null event handler since the application should just send the string and wait for the answer

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

@Bean
@ServiceActivator(inputChannel = "testGateway")
public MessageHandler testGate() {
    final TcpOutboundGateway gate = new TcpOutboundGateway();
    gate.setConnectionFactory(connectionFactory());
    gate.setReplyChannel(docServerChannel());
    return gate;
}

@Bean
public AbstractClientConnectionFactory connectionFactory() {
    final AbstractClientConnectionFactory connectionFactory = new TcpNetClientConnectionFactory("localhost", 5959);
    connectionFactory.setSoTimeout(300000);
    connectionFactory.setApplicationEventPublisher(new NullEventPublisher());
    connectionFactory.setSerializer(new DefaultSerializer());
    connectionFactory.setDeserializer(new DefaultDeserializer());
    return connectionFactory;
}

The messages should be converted to Strings when receiving data and to bytes when sending them

@MessageEndpoint
public static class TestMessage {

    @Transformer(inputChannel = "testChannel")
    public String convert(final byte[] bytes) {
        return new String(bytes);
    }

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

}

The application is deployed but the response is always timing out. The socket is running. I just want a simple direct bidirectional connection: WAR <-> JAR.

Can someone help or give me a hint?

------UPDATE-1----------

The socket is receiving the message but then response cannot be read beacuse the socket is closed after sending the message.

------UPDATE-2----------

  • It was a typo. The system is return a MessageHandler
  • I've added the factory as a spring managed bean
  • I've added '\r\n' to the legacy code
  • The application is still complaining "Timed out waiting for response"

The legacy server is opening up a server socket and sending messages to socket

final OutputStream os = serverSocket.getOutputStream();
final PrintWriter pw = new PrintWriter(os, true);
final BufferedReader br = new BufferedReader(new InputStreamReader(serverSocket.getInputStream()));
final String incoming = br.readLine();
final String response= "ok\r\n";
pw.println(response);
pw.flush();
Thread.sleep(5000);
pw.close();
serverSocket.close();

------UPDATE-3----------

The TcpOutboundGateway from Spring is getting no response

        connection.send(requestMessage);
        Message<?> replyMessage = reply.getReply();
        if (replyMessage == null) {

Answer:

The connection factory needs to be a @Bean so that Spring can manage it.

public TcpInboundGateway testGate() {
    final AbstractClientConnectionFactory connectionFactory = new TcpNetClientConnectionFactory("localhost", 5959); // already running socket
    connectionFactory.setApplicationEventPublisher(new NullEventPublisher());
    final TcpOutboundGateway gate = new TcpOutboundGateway();
    gate.setConnectionFactory(connectionFactory);
    gate.setOutputChannelName("testChannel");
    return gate;
}

This won't compile; the return type doesn't match what you are returning.

Assuming this is just a typo here and the bean is in fact an outbound gateway, with this configuration, the reply must be terminated with \r\n (CRLF).

See the documentation; scroll down to...

TCP is a streaming protocol; this means that some structure has to be provided to data transported over TCP, so the receiver can demarcate the data into discrete messages. Connection factories are configured to use (de)serializers to convert between the message payload and the bits that are sent over TCP. This is accomplished by providing a deserializer and serializer for inbound and outbound messages respectively. A number of standard (de)serializers are provided.

...and read about the standard deserializers. With your configuration, the standard deserializer is waiting for the terminaing \r\n (CRLF).

What does the server code do?

EDIT

@SpringBootApplication
public class So49046888Application {

    public static void main(String[] args) throws Exception {
        ConfigurableApplicationContext ctx = SpringApplication.run(So49046888Application.class, args);
        String reply = ctx.getBean(TestGateway.class).sendMessage("foo").get();
        System.out.println(reply);
        Thread.sleep(10_000);
        ctx.close();
    }

    @Bean
    public ServerSocket serverSocket() throws IOException {
        return ServerSocketFactory.getDefault().createServerSocket(5959);
    }

    @Bean
    public ApplicationRunner runner(TaskExecutor exec) {
        return args -> {
            exec.execute(() -> {
                try {
                    while (true) {
                        Socket socket = serverSocket().accept();
                        final OutputStream os = socket.getOutputStream();
                        final PrintWriter pw = new PrintWriter(os, true);
                        final BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                        final String incoming = br.readLine();
                        System.out.println(incoming);
                        final String response= "ok\r\n";
                        pw.print(response);
                        pw.flush();
                        Thread.sleep(5000);
                        pw.close();
                        socket.close();
                    }
                }
                catch (Exception e) {
                    e.printStackTrace();
                }
            });
        };
    }

    @Bean
    public TaskExecutor exec() {
        return new ThreadPoolTaskExecutor();
    }

    @Bean
    @ServiceActivator(inputChannel = "testGateway")
    public MessageHandler testGate() {
        final TcpOutboundGateway gate = new TcpOutboundGateway();
        gate.setConnectionFactory(connectionFactory());
        gate.setReplyChannelName("toString");
        gate.setRemoteTimeout(60_000);
        return gate;
    }

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

    @Bean
    public AbstractClientConnectionFactory connectionFactory() {
        final AbstractClientConnectionFactory connectionFactory = new TcpNetClientConnectionFactory("localhost", 5959);
        connectionFactory.setSoTimeout(300000);
        return connectionFactory;
    }

    @MessagingGateway(defaultRequestChannel = "testGateway")
    public static interface TestGateway {
        public Future<String> sendMessage(String in);
    }

}

Question:


Answer:

You just use a normal int in your program to store the port. When you want to send the int on the wire as a 16-bit value you simply cast it to a short. This just discards the high-order 16-bits (which you weren't using anyway) and the low-order 16-bits are are left unchanged. Example:

public byte[] encode() {
    final int MESSAGE_SIZE = 10;
    int portValue = 54321;
    Bytebuffer buffer = ByteBuffer.allocate(MESSAGE_SIZE);
    buffer.putInt(someInt);
    buffer.putShort((short) portValue);
    buffer.putInt(someOtherInt); 
    return buffer.array();
}

From Narrowing Primitive Conversions:

A narrowing conversion of a signed integer to an integral type T simply discards all but the n lowest order bits, where n is the number of bits used to represent type T.

Question:

I have a server whose port 80 is for occupied by HTTP transactions. I wanted to see the traffic in that port and I tried to use a socket program to listen to that port.

public Server(int serverPort) throws IOException {  
    super(serverPort);  
    try {  
        while (true) {  
            Socket socket = accept();  
            new ServerThread(socket);  
        }  
    } catch (IOException e) {  
        e.printStackTrace();  
    } finally {  
        close();
    }  
}  

// inner-class ServerThread  
class ServerThread extends Thread {  
    private Socket socket;  
    private BufferedReader in;  
    private PrintWriter out;  

    // Ready to conversation  
    public ServerThread(Socket s) throws IOException {  
        this.socket = s;  
        in = new BufferedReader(new InputStreamReader(socket  
                .getInputStream(), "UTF-8"));  
        out = new PrintWriter(socket.getOutputStream(), true);  
        start();  
    }  

    // Execute conversation  
    public void run() {  
        try {  

            // Communicate with client until "bye " received.  
            while (true) {  
                String line = in.readLine();  
                if (line == null || "".equals(line.trim())) {
                    break;  
                }  
                System.out.println("Received   message: " + line);  
                out.println(line);  
                out.flush();  
            }  

            out.close();  
            in.close();  
            socket.close();  

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

}  

public static void main(String[] args) throws IOException {  
    new Server(80);  
} 

However, when I run that java application, it showed a BindException: Address already in use.

So what should I do to my code and make it listen to port 80, or are there any other ways to listen to that port in Java?


Answer:

If I understand you correctly you are trying to sniff the packets that are being passed to your server. If that is the case there are some answers in this post.

Question:


Answer:

A TCP connection is bi-directional. If the device connects to your server to send data, just use that connection to talk back to it.

Question:

I'm currently working on a messaging program in java, and I planned on using UDP to send messages from the user to a central server, and I planned on using possibly TCP for messages from the server going back to the user. My main question is, how can I achieve this without requiring the client to port forward?


Answer:

Very simply, the client has to establish the TCP connection to the server, even if the primary (indeed if not only) data flow is in the opposite direction.

Question:

I'm new to Kafka and Streaming so bear with me.

I have installed and started both zookeeper and Kafka successfully. Created a simple topic and started console consumer that listen and display in console what is being sent to that topic. Producer currently sends info as a result of endpoint call.

I have a device which will be send NMEA format data to a TCP port. How can i expose a TCP port as a Kafka Producer?

If anyone needs any extra info to help, dont hesitate to ask.


Answer:

You will need to write an application that listens to the TCP port, decodes the data into the format you want it, and than hand it over to a KafkaProducer to write it into the topic.

Question:

Refer http://java-buddy.blogspot.com/2016/07/java-example-of-ssl-server-and-client.html

So I have tried the same procedure of running the client and server code by passing the keystore to server and truststore for client as suggested in the above blog link.

Question 1> So i have used the same keystore at server as a truststore at client, which was generated by command 'keytool -genkey -alias signFiles -keystore examplestore'. Whats going on here ?. How does the client pick the Trusted CA from that examplestore(which is keystore for server but truststore for client) file or more appropriately how does the keystore act as truststore and what does that file exactly consist of ?.

So what i know is, the keystore has public and private key pair along with the cert. for cuurent scenario its not yet a signed cert by a CA.

Question 2> So we need to create that .crt file and get it signed by the CA and then again embed it within the keyStore. Embedding the crt file means importing .Is this correct understanding? What does it mean by self signing the cert ? Does the command 'keytool -genkey -alias signFiles -keystore examplestore' create a self signed cert ?

I also tried appending keystore for client and truststore for server which refers the same file generated by command 'keytool -genkey -alias signFiles1 -keystore examplestore1', in the arguments while running respective code. And the code ran successfully.

I also tried playing with the arguments like changing the truststore of server to something that doesn't verify the keystore of client. But still the code worked.

But the code threw following exception "javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_unknown" when i tried changing the truststore of client that doesn't verify the server keystore.

PRIME QUESTION:

Question 3> Does this mean that its not triggering mutual authentication and if so, how to make it trigger ? And does it SUPPORT mutual authentication in first place ?


Answer:

First of all, let's clarify a few points:

  • A JKS file consists of entries where each entry is either a PrivateKeyEntry or trustedCertEntry. (There are other types for symmetric keys, yes, but let's forget about them while talking about public key cryptography.)
  • When you run genkey, you are generating a private key entry. It contains both private & public key, as you guess.
  • You can export only public key from a private key entry, and then import it into another JKS, which turns out to be a trusted cert entry this time, since it only contains public key.
  • Every generated certificate is initially self-signed. It's not self-signed only if another private key entry (of a CA) is used to sign it. A trusted cert entry may be either self-signed or CA-signed. Root CA certificates are always self-signed though.
  • Using a JKS as truststore means you are trusting the entries in it, whether they are self-signed or CA signed. You can create your own CA, import its public key to a JKS file and use it as your truststore. This means that you trust only the certificates that are signed (directly or indirectly) by your CA. (Indirectly means there are intermediate certificates that are signed by your CA and used again for signing other certificates.)

Now for your questions,

Q1

As stated above, using keystore as truststore means "trust the entries in it", so it works. No need to be signed by another party (i.e. CA).

Q2

"Embedding the crt file means importing .Is this correct understanding?"

Yes.

"Does the command 'keytool -genkey -alias signFiles -keystore examplestore' create a self signed cert ?"

Yes.

Regarding your trials with different keystore & truststore configurations: In a typical SSL setup, only the server has a private key and presents its certificate. Only the client verifies the server, not vice versa. If the servers were configured to ask for certificates (it's possible to do that), then you would have to select your private key while browsing https sites. It is quite uncommon to verify clients. That's why, both providing a keystore to the client and a truststore to the server has no effect. It fails only if you give an invalid truststore to the client.

Q3 SSL supports mutual authentication, yes. Check here for a good answer.

Question:

I am making a Curl post curl -X POST -d "dsds" 10.0.0.211:5201 to my Netty socket server but in my ChannelRead when I try to cast Object msg into FullHttpRequest It throws following exception.

java.lang.ClassCastException: io.netty.buffer.SimpleLeakAwareByteBuf cannot be cast to io.netty.handler.codec.http.FullHttpRequest
        at edu.clemson.openflow.sos.host.netty.HostPacketHandler.channelRead(HostPacketHandler.java:42)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:334)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:326)
        at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1320)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:334)
        at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:905)
        at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:123)
        at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:563)
        at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:504)
        at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:418)
        at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:390)
        at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:742)
        at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:145)
        at java.lang.Thread.run(Thread.java:748)

Following is my Socket Handler class

@ChannelHandler.Sharable
public class HostPacketHandler extends ChannelInboundHandlerAdapter {
    private static final Logger log = LoggerFactory.getLogger(HostPacketHandler.class);
    private RequestParser request;

    public HostPacketHandler(RequestParser request) {
        this.request = request;
        log.info("Expecting Host at IP {} Port {}",
                request.getClientIP(), request.getClientPort());
    }

    public void setRequestObject(RequestParser requestObject) {
        this.request = requestObject;
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        // Discard the received data silently.
        InetSocketAddress socketAddress = (InetSocketAddress) ctx.channel().remoteAddress();
        log.info("Got Message from {} at Port {}",
                socketAddress.getHostName(),
                socketAddress.getPort());
        //FullHttpRequest request = (FullHttpRequest) msg;
        log.info(msg.getClass().getSimpleName());
        //((ByteBuf) msg).release();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        // Close the connection when an exception is raised.
        cause.printStackTrace();
        ctx.close();
    }

}

Pipeline:

public class NettyHostSocketServer implements IClientSocketServer {
    protected static boolean isClientHandlerRunning = false;
    private static final Logger log = LoggerFactory.getLogger(SocketManager.class);
    private static final int CLIENT_DATA_PORT = 9877;
    private static final int MAX_CLIENTS = 5;
    private HostPacketHandler hostPacketHandler;

    public NettyHostSocketServer(RequestParser request) {
        hostPacketHandler = new HostPacketHandler(request);
    }

    private boolean startSocket(int port) {
        NioEventLoopGroup group = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(group)
                    .channel(NioServerSocketChannel.class)
                    .localAddress(new InetSocketAddress(port))
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel ch)
                                throws Exception {
                            ch.pipeline().addLast(
                                    hostPacketHandler);
                        }
                    });

            ChannelFuture f = b.bind().sync();
            log.info("Started host-side socket server at Port {}",CLIENT_DATA_PORT);
            return true;
            // Need to do socket closing handling. close all the remaining open sockets
            //System.out.println(EchoServer.class.getName() + " started and listen on " + f.channel().localAddress());
            //f.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            log.error("Error starting host-side socket");
            e.printStackTrace();
            return false;
        } finally {
            //group.shutdownGracefully().sync();
        }
    }

    @Override
    public boolean start() {

        if (!isClientHandlerRunning) {
            isClientHandlerRunning = true;
            return startSocket(CLIENT_DATA_PORT);
        }
        return true;
    }


    @Override
    public int getActiveConnections() {
        return 0;
    }
}

I also used wireshark to check If I am getting valid packets or not. Below is the screenshot of Wireshark dump.


Answer:

Your problem is that you never decode the ByteBuf into an actual HttpRequest object which is why you get an error. You can't cast a ByteBuf to a FullHttpRequest object.

You should do something like this:

@Override
public void initChannel(Channel channel) throws Exception {
    channel.pipeline().addLast(new HttpRequestDecoder()) // Decodes the ByteBuf into a HttpMessage and HttpContent (1)
        .addLast(new HttpObjectAggregator(1048576)) // Aggregates the HttpMessage with its following HttpContent into a FullHttpRequest
        .addLast(hostPacketHandler);
}

(1) If you also want to send HttpResponse use this handler HttpServerCodec which adds the HttpRequestDecoder and HttpResponseEncoder.

Question:

I've looked at other posts, but none are this specific. If its a duplicate, mark it as such and I will delete it.

I am wondering how to confirm if a TCP port is open or not... Obviously, I am creating a socket and calling connect() to the InetAddress and port number specified. My tests show that if the port is not open, there is an IOException thrown, and if the port is open, there is no exception.

Is exception catching the only way to check if the port is open? Also, perhaps more importantly, if there is not exception thrown and the line after connect() is executed, does that mean that the entire TCP connection is complete and successful? I am asking because apparently isConnected() does not always return the expected result in some cases, so I'm not sure it is reliable. Do I need to actually read or write something to the port for confirmation?


Answer:

Java NIO provides asynchronous socket programming which will return the exception as a parameter which implies that an exception will be thrown if the socket isn't open. This may be preferable if you have a lot of nested calls and are concerned about the size of the stack trace.

The low level (kernel) socket connect function doesn't return until the TCP/IP handshake is completed so you can assume the socket is open and ready for use. There is no way to know if the socket is truly open because there could for example be a service outage on the other end of the connection which could prevent the other end from notifying your application that the connection has been closed. It is therefore possible to know if a connection is closed, if you have received a FIN packet but there is no way to know if it is open. If the connection is made you can assume it is open but short of an application layer handshake there is no way to know if the connection was ever open. Some application layer protocols send frequent no-operation messages to ensure that the socket is still open which helps find out if the connection is closed based on not receiving ACK(nowledgement) that the packet was received within a certain timeout period, but network lag could in fact cause timeouts to give false-positives. Using a timeout you are assuming it is closed, and after a connect due to the handshake you are assuming it is open, but the only certainty is if you receive a FIN message at the TCP layer the socket is most-certainly closed.

Question:

I have a java TCP socket listener console application. I get the following error on my console after some 150+ connections. the application works nicely with less no of connections but as the no. of connections increase it starts giving this error quite frequently. Don't know if it happens due to the MS SQL server or its a java caused problem please help.


Answer:

since i found a solution thought i should post it here. The problem was solved by implementing connection pooling.For it i used c3p0

Hope it helps.

Question:

Definitions Well-known Port    Port number in the range [0, 1023] Registered Port    Port number in the range [1024, 49151] Dynamic Port    Port number in the range [49152, 65535]

I am attempting to create a SocketServer object. When I allow SocketServer to select a dynamic port (by binding to port 0), it works as expected. If I explicitly specify a registered port, it works as expected. However, when I specify a dynamic port, it is always throwing a BindException with the message "Address already in use: JVM_Bind". The top of the stack trace for the exception is:

at java.net.DualStackPlainSocketImpl.bind0(Native Method)
at java.net.DualStackPlainSocketImpl.socketBind(DualStackPlainSocketImpl.java:106)
at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:387)
at java.net.PlainSocketImpl.bind(PlainSocketImpl.java:190)
at java.net.ServerSocket.bind(ServerSocket.java:375)
at java.net.ServerSocket.<init>(ServerSocket.java:237)
at java.net.ServerSocket.<init>(ServerSocket.java:128)

I am using JDK 1.8u74 on a Windows 7 Enterprise SP1 x64 machine. The code is as follows:

SocketServer createServer(final int port) throws IOException {
    // Create a new socket server
    SocketServer server;
    try {
        // Try to bind to all interfaces
        server = new ServerSocket(port, 1, null);
    } catch (BindException e) {
        // If that fails, try to bind to the primary IP address
        final InetAddress address = InetAddress.getLocalHost();
        server = new ServerSocket(port, 1, address);
    }
    return server;
}

I have also tried the following alternative:

SocketServer createServer(final int port) throws IOException {
    // Create a new socket server
    final SocketServer server = new SocketServer();
    server.setReuseAddress(true);
    try {
        // Try to bind to all interfaces
        server.bind(new InetSocketAddress(port), 1);
    } catch (BindException e) {
        // If that fails, try to bind to the primary IP address
        final InetAddress address = InetAddress.getLocalHost();
        server.bind(new InetSocketAddress(address, port), 1);
    }
    return server;
}

Both of these alternatives throw a BindException when port is a dynamic port. I have verified that all of the roughly 50 dynamic ports I tested are available according to the results of netstat -an. Is there any way to create a SocketServer for a specific dynamic port?


Answer:

Although not ideal since it involves registry edits, there is an answer provided on Server Fault.

Windows can be setup to exclude ports from its range of dynamic ports. Simply add the range(s) to exclude to the Multi-String value:

HKLM\System\CurrentControlSet\Services\TCPIP\Parameters\ReservedPorts

So, in my case I have a requirement to use ports 55101-55107, so I added that text to the registry value and restarted the computer. While this solution allows me to use those ports, it is disappointing that I have to edit the registry on any Windows machine where I want to use them. In addition, if I have to add another dynamic port in the future, I will have to re-edit the registry.

Question:


Answer:

  1. getInputStream.read() - I have n number of clients, so i dont want to keep threads active waiting for return statement

You should use N threads, one per client, like everybody else does. And a socket read timeout.

  1. isConnected() command is always returning true.

It's not a command, it's a method, otherwise correct. It tells you about the state of the Socket, not of the connection. It becomes true once you've connected or accepted the Socket: it never becomes false.

  1. out.checkError() will throw Exception

No it won't. It will return a boolean if there was an IOException writing to the PrintWriter or PrintStream, but it won't tell you what the exception was, and it doesn't apply to read exceptions, so it isn't all that much use. In fact you shouldn't use PrintWriter at all over a network for that reason, you should use BufferedWriter.

Use a thread per client.

I don't wish to throw any Exception

Bad luck, that's the only way you're going to detect a connection abort.

and get interrupted.

I don't know what this means.

Question:

Server:

int port = 7000
ServerSocket ss;
..
System.out.println("Listening on " + ss.getInetAddress() + ":"
   + ss.getLocalPort());

Socket s = ss.accept();
..
System.out.println("Accepted connection " + s.getInetAddress() + ":"
   + s.getPort());

Client:

Socket s;
..
System.out.println("Connected to " + s.getInetAddress() + ":"
   + s.getPort());

Server starts listening:

Listening on 0.0.0.0/0.0.0.0:7000

Client connects:

Connected to localhost/127.0.0.1:7000

But the server says that the socket is connected on a different port?

Accepted connection /127.0.0.1:54682

Referencing:

Java the difference of Socket and ServerSocket in using port

.. ServerSocket.accept() accepts a connection, and wraps the endpoint in a Socket. The endpoint has the same local port number as the ServerSocket, by definition as per RFC 793, and therefore so does the wrapping Socket.

and

.. each client connection will get a separate Socket to communicate on, all communicating using the same server side TCP port.


Answer:

getPort() returns the remote port of the socket (i.e. other side address) while getLocalPort() returns the local port that the socket is bound to.

If you ran s.getLocalPort()); on server accepted socket, you would get 7000 too.

Question:

I've tried this for listening to open ports..

public class PortCheck {

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

            System.out.println("port open");
        } catch (IOException e) {
            System.out.println("not open");
        }
    }
}

But I want to open a closed port from my java program.Is there any way of doing it?


Answer:

Socket is a client socket for connecting to a server. To open a listening socket to accept clients, you need to use ServerSocket instead, which will open a port if it is not already open, and will fail if the port is already in use.

public class PortCheck {

    public static void main(String[] args) {
        try {
            ServerSocket socket = new ServerSocket(4500, 0, InetAddress.getLocalHost());
            System.out.println("port available");
        } catch (IOException e) {
            System.out.println("port not available");
        }
    }
}

Question:

In my Java program I created two sockets, one of them serversocket and one of them is just the normal socket. I setup the serverSocket at port 1234 and made another normal port to listen at localhost:1234. The socket doesn't recieve any of the messages I'm sending to it though. p.s. It also receives messages on my other Java program listening on the same port. But not from the same program, with both the serversocket and the normal socket.

EDIT: here's my code.

public void initLan(){
    try{
        if(mode == GameMode.TWO_PLAYER_LAN_HOST){
            serverSocket = new ServerSocket(port);
            System.out.println("Waiting for client to connect....");
            socket = serverSocket.accept();
            serverInputSocket = new Socket("localhost",port);
            lanHostInput = new BufferedReader(new InputStreamReader(serverInputSocket.getInputStream()));
            lanHostOutput = new PrintWriter(serverInputSocket.getOutputStream(),true);
        }else if(mode == GameMode.TWO_PLAYER_LAN_CLIENT){
            socket = new Socket("localhost",port);
        }
        lanOutput = new PrintWriter(socket.getOutputStream(),true);
        lanInput = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    }catch(Exception e){
        System.out.println("Could not initialize LAN");
    }
}

and here's the message I send when I press the up key

        if(keyCode == KeyEvent.VK_UP){
            lanOutput.print("UP\n");
            lanOutput.flush();
            lanHostOutput.print("UP\n");
            lanHostOutput.flush();
            //System.out.println("UP");
        }

When I send the message, it is never received later on in the program.

if(lanInput.ready()){
            String message = lanInput.readLine();
            System.out.println(message);
            if(message.contains("UP")){
                snake.move("UP");
                System.out.println("moved up");
            }
        }
        if(mode == GameMode.TWO_PLAYER_LAN_HOST){
            if(lanHostInput.ready()){
                String message = lanInput.readLine();
                System.out.println(message);
                if(message.contains("UP")){
                    snake.move("UP");
                    System.out.println("moved up");
                }
            }
        }

Answer:

There are two classes in java for socket 1) java.net.Socket: for client sockets 2) java.net.ServerSocket: for server sockets

you can only listen on server sockets not client sockets

the problem is these two lines

socket = serverSocket.accept();
serverInputSocket = new Socket("localhost",port);

replace them with this one

serverInputSocket = serverSocket.accept();