Hot questions for Using Transmission Control Protocol in client

Question:

I'm trying to create a server in Spring that's listening on a TCP port and accepts connections. I know how to route incoming requests to my service, and it can respond to those. However I would like to send messages to certain clients without any request received. For example, sometimes I have to inform a client about that it has got a message.

To do this, I think I need a way to identify the clients, e.g. by letting them log in. Is there a way to have a "session" object for each active connection in which I can store login data?

How could I send a message to a client which has logged in with username X?

Is this possible in Spring at all?


Answer:

Starting with version 3.0; the frameworks now emits connection events when there are connection state changes. You can capture these events using an ApplicationListener, or using an <event:inbound-channel-adapter/>.

The TcpConnectionOpenEvent contains a connectionId; you can send arbitrary messages to any connection once you know its id, by populating the IpHeaders.connectionId header (ip_connectionId) in a message and sending it to a <tcp:outbound-channel-adapter/>.

If you need to support request/reply as well as sending arbitrary messages, you need to use a collaborating pair of channel adapters for all communication, not a gateway.

EDIT

Here's a simple Boot app...

package com.example;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.Socket;

import javax.net.SocketFactory;

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.dsl.IntegrationFlow;
import org.springframework.integration.dsl.IntegrationFlows;
import org.springframework.integration.ip.IpHeaders;
import org.springframework.integration.ip.tcp.TcpReceivingChannelAdapter;
import org.springframework.integration.ip.tcp.TcpSendingMessageHandler;
import org.springframework.integration.ip.tcp.connection.TcpConnectionOpenEvent;
import org.springframework.integration.ip.tcp.connection.TcpNetServerConnectionFactory;
import org.springframework.integration.ip.tcp.connection.TcpServerConnectionFactory;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;

@SpringBootApplication
public class So25102101Application {

    public static void main(String[] args) throws Exception {
        ConfigurableApplicationContext context = new SpringApplicationBuilder(So25102101Application.class)
                .web(false)
                .run(args);
        int port = context.getBean(TcpServerConnectionFactory.class).getPort();
        Socket socket = SocketFactory.getDefault().createSocket("localhost", port);
        BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String line = reader.readLine();
        System.out.println(line);
        context.close();
    }

    @Bean
    public TcpReceivingChannelAdapter server(TcpNetServerConnectionFactory cf) {
        TcpReceivingChannelAdapter adapter = new TcpReceivingChannelAdapter();
        adapter.setConnectionFactory(cf);
        adapter.setOutputChannel(inputChannel());
        return adapter;
    }

    @Bean
    public MessageChannel inputChannel() {
        return new QueueChannel();
    }

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

    @Bean
    public TcpNetServerConnectionFactory cf() {
        return new TcpNetServerConnectionFactory(0);
    }

    @Bean
    public IntegrationFlow outbound() {
        return IntegrationFlows.from(outputChannel())
                .handle(sender())
                .get();
    }

    @Bean
    public MessageHandler sender() {
        TcpSendingMessageHandler tcpSendingMessageHandler = new TcpSendingMessageHandler();
        tcpSendingMessageHandler.setConnectionFactory(cf());
        return tcpSendingMessageHandler;
    }

    @Bean
    public ApplicationListener<TcpConnectionOpenEvent> listener() {
        return new ApplicationListener<TcpConnectionOpenEvent>() {

            @Override
            public void onApplicationEvent(TcpConnectionOpenEvent event) {
                outputChannel().send(MessageBuilder.withPayload("foo")
                        .setHeader(IpHeaders.CONNECTION_ID, event.getConnectionId())
                        .build());
            }

        };
    }

}

pom deps:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-integration</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.integration</groupId>
        <artifactId>spring-integration-ip</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

Question:

I'm trying to write a simple echo server with Netty. I'm reading Netty in Action MEAP v8 to get down some theory and learn the core basics of Netty. The client connects successfully, but no messages get through from the client. I am able to telnet a message to the server and receive the response, so I guess the issue is on the client, I just have no idea what is wrong, due to me being new to Netty.

Here is the client:

public class Client {

    private final String host;
    private final int port;

    public Client(String host, int port) {
        this.host = host;
        this.port = port;
    }

    public void start() throws Exception {
        EventLoopGroup group = new NioEventLoopGroup();
        try {
            Bootstrap b = new Bootstrap();
            b.group(group).channel(NioSocketChannel.class)
                          .remoteAddress(new InetSocketAddress(host, port))
                          .handler(new ChannelInitializer<SocketChannel>() {

                              @Override
                              public void initChannel(SocketChannel ch) throws Exception {
                                  ch.pipeline().addLast(new EchoClientHandler());
                              }
                          });

            ChannelFuture f = b.connect().sync();

            f.channel().closeFuture().sync();
        } finally {
            group.shutdownGracefully().sync();
        }
    }


    public static void main (String [] args) throws Exception {
        new Client("127.0.0.1", 11235).start();
    }
}

And the Client handler: (I did try appending '\r\n' to the sent message, but that did not make a difference, which I found here: Netty Client to Server message)

@Sharable 
public class EchoClientHandler extends SimpleChannelInboundHandler<ByteBuf> {

    public void channelActive(ChannelHandlerContext ctx) {
        System.out.println("Connected");
        ctx.write(Unpooled.copiedBuffer("Netty MAY rock!", CharsetUtil.UTF_8));
    }

    protected void channelRead0(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
        System.out.println(
                "Client received: " + in.toString(CharsetUtil.UTF_8));

    }

    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        cause.printStackTrace();
        ctx.close();
    }
}

The server:

public class EchoServer {

    private final int port;

    public EchoServer(int port) {
        this.port = port;
    }

    public void start() throws Exception {
        EventLoopGroup 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 {
                                        System.out.println("New client connected: " + ch.localAddress());

                                        ch.pipeline().addLast(new EchoServerHandler());
                                    }
                                });
            ChannelFuture f = b.bind().sync();
            f.channel().closeFuture().sync();
        } finally {
            group.shutdownGracefully().sync();
        }
    }

    public static void main (String [] args) throws Exception {
        new EchoServer(11235).start();
    }
}

The server handler:

@Sharable
public class EchoServerHandler extends ChannelInboundHandlerAdapter {

    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        ByteBuf in = (ByteBuf) msg;
        System.out.println(
            "Server received: " + in.toString(CharsetUtil.UTF_8));
        ctx.write(in);
    }

    public void channelReadComplete(ChannelHandlerContext ctx) {
        ctx.writeAndFlush(Unpooled.EMPTY_BUFFER)
            .addListener(ChannelFutureListener.CLOSE);
    }

    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        cause.printStackTrace();
        ctx.close();
    }
}

It must be something small I'm missing, so any help will preserve my fleeting sanity and will be much appreciated!


Answer:

Instead of write use writeAndFlush in your ClientHandler:

public void channelActive(ChannelHandlerContext ctx) {
    System.out.println("Connected");
    ctx.writeAndFlush(Unpooled.copiedBuffer("Netty MAY rock!", CharsetUtil.UTF_8));
}

Question:

The Spring framework support tcp connection as well , i wrote code below to setup a simple socket server , i am confused about adding below futures to my socket server :

  • authorizing clients based on a unique identifier ( for example a client secret received from client, maybe using TCP Connection Events )
  • send a message directly to specific client (based on identifier)
  • broadcast a message

UPDATE :

  • Config.sendMessage added to send message to single client

  • Config.broadCast added to broadcast message

  • authorizeIncomingConnection to authorize clients , accept or reject connections

  • tcpConnections static filed added to keep tcpEvent sources

Questions !

  • is using tcpConnections HashMap good idea ?!

  • is the authorization method i implemented a good one ?!

Main.java

@SpringBootApplication
public class Main {

    public static void main(final String[] args) {
        SpringApplication.run(Main.class, args);
    }

}

Config.java

@EnableIntegration
@IntegrationComponentScan
@Configuration
public class Config implements ApplicationListener<TcpConnectionEvent> {

    private static final Logger LOGGER = Logger.getLogger(Config.class.getName());

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

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

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

    @MessageEndpoint
    public class Echo {

        @Transformer(inputChannel = "getMessageChannel")
        public String convert(byte[] bytes) throws Exception {
            return new String(bytes);
        }

    }

    private static ConcurrentHashMap<String, TcpConnection> tcpConnections = new ConcurrentHashMap<>();

    @Override
    public void onApplicationEvent(TcpConnectionEvent tcpEvent) {
        TcpConnection source = (TcpConnection) tcpEvent.getSource();
        if (tcpEvent instanceof TcpConnectionOpenEvent) {

            LOGGER.info("Socket Opened " + source.getConnectionId());
            tcpConnections.put(tcpEvent.getConnectionId(), source);

            if (!authorizeIncomingConnection(source.getSocketInfo())) {
                LOGGER.warn("Socket Rejected " + source.getConnectionId());
                source.close();
            }

        } else if (tcpEvent instanceof TcpConnectionCloseEvent) {
            LOGGER.info("Socket Closed " + source.getConnectionId());
            tcpConnections.remove(source.getConnectionId());
        }
    }

    private boolean authorizeIncomingConnection(SocketInfo socketInfo) {
        //Authorization Logic , Like Ip,Mac Address WhiteList or anyThing else !
        return (System.currentTimeMillis() / 1000) % 2 == 0;
    }

    public static String broadCast(String message) {
        Set<String> connectionIds = tcpConnections.keySet();
        int successCounter = 0;
        int FailureCounter = 0;
        for (String connectionId : connectionIds) {
            try {
                sendMessage(connectionId, message);
                successCounter++;
            } catch (Exception e) {
                FailureCounter++;
            }
        }
        return "BroadCast Result , Success : " + successCounter + " Failure : " + FailureCounter;
    }

    public static void sendMessage(String connectionId, final String message) throws Exception {
        tcpConnections.get(connectionId).send(new Message<String>() {
            @Override
            public String getPayload() {
                return message;
            }

            @Override
            public MessageHeaders getHeaders() {
                return null;
            }
        });
    }
}

MainController.java

@Controller
public class MainController {

    @RequestMapping("/notify/{connectionId}/{message}")
    @ResponseBody
    public String home(@PathVariable String connectionId, @PathVariable String message) {
        try {
            Config.sendMessage(connectionId, message);
            return "Client Notified !";
        } catch (Exception e) {
            return "Failed To Notify Client , cause : \n " + e.toString();
        }
    }


    @RequestMapping("/broadCast/{message}")
    @ResponseBody
    public String home(@PathVariable String message) {
        return Config.broadCast(message);
    }

}

Usage :

  1. Socket Request/Response Mode
  2. notify single client

    http://localhost:8080/notify/{connectionId}/{message}

  3. broadCast

    http://localhost:8080/broadCast/{message}


Answer:

The TcpConnectionOpenEvent contains a connectionId property. Each message coming from that client will have the same property in the IpHeaders.CONNECTION_ID message header.

  1. Add a custom router that keeps track of the logged-on state of each connection.
  2. Lookup the connection id and if not authenticated, route to a challenge/response subflow.
  3. When authenticated, route to the normal flow.

To use arbitrary messaging (rather than request/response) use a TcpReceivingChannelAdapter and TcpSendingMessageHandler instead of an inbound gateway. Both configured to use the same connection factory. For each message sent to the message handler, add the IpHeaders.CONNECTION_ID header to target the specific client.

To broadcast, send a message for each connection id.

Question:

I'm in the process of designing a system that will run using a Spring MVC web application. It will be used to send and receive TCP commands to and from an existing (non-Spring) application which is used to control some network data filters. I'm just playing around with the Spring Integration TCP stuff (I'm new to SI and Spring in general) to try and understand it but I'm struggling to get a basic example to work.

I need the communication to be asynchronous, as the server and client ends could send data at any time, and it may or may not need a reply. So I believe what I need to use are collaborating channel adapters rather than gateways.

My demo program should wait for a client to connect and then receive a series of String messages, to which it echoes a reply. The user can also type stuff to send from the server side.

It's based on the tcp-client-server example in the samples. I would like to do it all via Java config rather than XML.

What I would like the demo below to do is echo the incoming data back to the client.

Here's the server config class:

@Configuration()
@EnableIntegration
@IntegrationComponentScan
public class ServerConfiguration implements ApplicationListener<TcpConnectionEvent> {

private final int port = SocketUtils.findAvailableServerSocket(5000);

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

@Bean
public AbstractServerConnectionFactory serverFactory() {
    System.out.println("serverFactory");
    AbstractServerConnectionFactory connectionFactory = new TcpNetServerConnectionFactory(port);
    return connectionFactory;
}

@Bean MessageChannel toTcp() {
    System.out.println("creating toTcp DirectChannel");
    DirectChannel dc = new DirectChannel();
    dc.setBeanName("toTcp");

    return dc;
}

@Bean
public MessageChannel fromTcp() {
    System.out.println("creating fromTcp DirectChannel");
    DirectChannel dc = new DirectChannel();
    dc.setBeanName("fromTcp");

    return dc;
}

// Inbound channel adapter. This receives the data from the client
@Bean
public TcpReceivingChannelAdapter inboundAdapter(AbstractServerConnectionFactory connectionFactory) {
    System.out.println("Creating inbound adapter");
    TcpReceivingChannelAdapter inbound = new TcpReceivingChannelAdapter();

    inbound.setConnectionFactory(connectionFactory);
    inbound.setOutputChannel("fromTcp");

    return inbound;
}

// Outbound channel adapter. This sends the data to the client
@Bean
@ServiceActivator(inputChannel="toTcp")
public TcpSendingMessageHandler outboundAdapter(AbstractServerConnectionFactory connectionFactory) {
    System.out.println("Creating outbound adapter");
    TcpSendingMessageHandler outbound = new TcpSendingMessageHandler();
    outbound.setConnectionFactory(connectionFactory);
    return outbound;
}

// Endpoint example 
@MessageEndpoint
public static class Echo {

    // Server
    @Transformer(inputChannel="fromTcp", outputChannel="toEcho")
    public String convert(byte[] bytes) {
        System.out.println("convert: " + new String(bytes));
        return new String(bytes);
    }

    // Server
    @ServiceActivator(inputChannel="toEcho", outputChannel="toTcp")
    public String upCase(String in) {
        System.out.println("upCase: " + in.toUpperCase());
        return in.toUpperCase();
    }
}

@Override
public void onApplicationEvent(TcpConnectionEvent event) {
    System.out.println("Got TcpConnectionEvent: source=" + event.getSource() + 
            ", id=" + event.getConnectionId()); 
}   
}

Here's the main class:

@SpringBootApplication
@IntegrationComponentScan
@EnableMessageHistory
public class SpringIntegrationTcpTest {

    @Autowired
    private ServerConfiguration.Gateway gateway;

    public String send(String data) {
        return gateway.send(data);
    }


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

    ConfigurableApplicationContext context = SpringApplication.run(SpringIntegrationTcpTest.class, args);

    SpringIntegrationTcpTest si = context.getBean(SpringIntegrationTcpTest.class);

    final AbstractServerConnectionFactory crLfServer = context.getBean(AbstractServerConnectionFactory.class);

    final Scanner scanner = new Scanner(System.in);
    System.out.print("Waiting for server to accept connections on port " + crLfServer.getPort());
    TestingUtilities.waitListening(crLfServer, 100000L);
    System.out.println("running.\n\n");

    System.out.println("Please enter some text and press <enter>: ");
    System.out.println("\tNote:");
    System.out.println("\t- Entering FAIL will create an exception");
    System.out.println("\t- Entering q will quit the application");
    System.out.print("\n");

    while (true) {

        final String input = scanner.nextLine();

        if("q".equals(input.trim())) {
            break;
        }
        else {
            final String result = si.send(input);
            System.out.println(result);
        }
    }

    scanner.close();
    context.close();
}
}

And here's the dummy client class:

public class TcpClient {

    public TcpClient() {
    }

    private void connect(String host, int port) throws InterruptedException {
        Socket socket = null;
        Writer out = null;
        BufferedReader in = null;

        try {
            System.out.print("Connecting to " + host + " on port " + port + " ... ");
            socket = new Socket(host, port);
            System.out.println("connected.");

            System.out.println("sending 100 messages");

            out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

            for (int i = 1; i < 100; ++i) {
                String msg =  "hello" + i;

                out.write(msg+"\r\n");
                out.flush();
                //System.out.print(msg+"\r\n");

                System.out.println("Waiting for message ...");

                StringBuffer str = new StringBuffer();
                int c;
                while ((c = in.read()) != -1) {
                    str.append((char) c);
                }       

                String response = str.toString();
                System.out.println("got message: " + response);

                Thread.sleep(1000);
            }


        } catch (IOException e) {

            System.err.println("Test ended with an exception: " + port + ", " + e.getMessage());

        } finally {
            try {
                socket.close();
                out.close();
                //in.close();

            } catch (Exception e) {
                // swallow exception
            }

        }       

    }

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

        String host = args[0];
        int port = Integer.parseInt(args[1]);
        new TcpClient().connect(host, port);
    }

}

I've spent a good deal of time playing with gateways, etc. and get it to sort of work with telnet, and to receive messages from the client using a gateway. What I can't do is get it work properly with channel adapters.

When the client is started it will send the string which is received by the server and printed to the console.Nothing appears to be sent back, as the client just sits on "Waiting for message ...". When sending something from the server side, I get the following exception:

Please enter some text and press <enter>:
        Note:
        - Entering FAIL will create an exception
        - Entering q will quit the application

Got TcpConnectionEvent: source=org.springframework.integration.ip.tcp.connection.TcpNetConnection@67162888, id=127.0.0.1:50940:5000:052bf55b-526a-4ea9-bfe3-8ecc573239a3
convert: hello1
upCase: HELLO1
qwe
2017-01-10 12:09:13.995 ERROR 7296 --- [           main] o.s.i.ip.tcp.TcpSendingMessageHandler    : Unable to find outbound socket for GenericMessage [payload=qwe, headers={replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@6b5894c8, history=serverConfiguration$Gateway,toTcp,serverConfiguration.outboundAdapter.serviceActivator.handler,outboundAdapter, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@6b5894c8, id=a4ea72f2-6b12-379b-1b15-f75b821f0b7f, timestamp=1484050153995}]
Exception in thread "main" org.springframework.messaging.MessageHandlingException: Unable to find outbound socket
        at org.springframework.integration.ip.tcp.TcpSendingMessageHandler.handleMessageInternal(TcpSendingMessageHandler.java:123)
        at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:127)

so the problem is that's there's no outbound socket. So where is the outbound socket defined? What else am I doing wrong?


Answer:

  1. You don't need to call setBeanName on the channels - the framework will do that automatically for you.

  2. Your gateway is expecting a reply and the toTcp channel is connected to a channel adapter which returns no reply - use a void return type for this scenario

o.s.i.ip.tcp.TcpSendingMessageHandler : Unable to find outbound socket

To send arbitrary messages to a connected client, you need to tell the adapter which client to send it to by setting the ip_connectionId header (there's a constant IpHeaders.CONNECTION_ID.

You need to set that header - you can capture it via the TcpConnectionOpenEvent and add it to the header via the gateway...

void send(@Payload String data, @Header(IpHeaders.CONNECTION_ID) String connectionId);

Question:

I have a commandsystem to communicate between my TCP Server and Client (Java). I can send specific commands to my Client, if the Client received a command, it will execute something.

Basically, thats working. But sometimes I have to send the command + extra informations. The problem is: The informations will sometimes be sent too fast. So some information will get lost / mixed up and my Client cant execute the request properly. The solution for me was to use Thread.sleep(), but this isn't clean nor efficent. Because there is still a risk that the information will not be received properly.

My Server:

public void sendCommand(Socket socket) throws InterruptedException, IOException {
    writeMsg("CMD_POPUP", socket);
    Thread.sleep(150);
    writeMsg("foo", socket);
    Thread.sleep(150);
    writeMsg("bar", socket);
    Thread.sleep(150);
    writeMsg("baz", socket);
}

public void writeMsg(String message, Socket socket) throws IOException {
    DataOutputStream out = new DataOutputStream(socket.getOutputStream());
    out.writeUTF(message);
}

My Client:

public void interpreteCommand(Socket socket) throws IOException {
    while (true) {
        switch (readMsg(socket)) {
            case "CMD_POPUP":
                System.out.println(readMsg(socket)); 
                System.out.println(readMsg(socket)); //Sometimes it would be 'bar' but also sometimes it would be 'baz'
                System.out.println(readMsg(socket)); //Sometimes it would be 'baz' but also sometimes it would be nothing
                break;
        }
    }
}

public String readMsg(Socket socket) throws IOException {
    DataInputStream in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
    return in.readUTF();
}

Answer:

First of all, I'm not a java programmer. However tcp connections work the same way in other programming languages.

TCP Connections are stream-based, meaning there is no start or end of a message. The only thing TCP guarantees is that the data is arriving in the right order.

If you send "CMD_POPUP" and "foo" immediately after each other, you don't know if you will receive "CMD_POPUP", "CMD_POPUPfoo", "CMD_PO" etc. on the other side. Because you are waiting a specific amount of time between each send, the data usually does arrive one after each other. But that is not guaranteed and I would also consider this a not very clean way of doing it.

The easiest way to get around this is to send a start character in the beginning, separator characters between the parameters and a end-character after each message. e.g. "#CMD_POPUP%foo%bar$" or sth like that. This way, you can write everything you receive to a buffer until you receive the end of a message, and then process it.

Question:

I have a client which can send some information to a server via TCP :

    public class IR {

    private String host; //server IP address indicated here, I deleted it for posting here
    private int port = 6789;

    private String sentence;
    private String reply;

    public IR(String type) {
        try {

            Socket clientSocket = new Socket(host,port); //IP du server ("localhost" pour un server local) et port utilisé

            DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
            BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));


                Gson gson = new GsonBuilder().create();
                FileReader file = new FileReader("data/userInfo.json");
                String json = "";
                int i = 0;
                while ((i = file.read()) != -1)
                    json += (char)i;
                User user = gson.fromJson(json, User.class);
                String user_id = user.getID();
                int bus_id = user.getBusID();

                sentence = "alerte " + type + " " + user_id + " " + bus_id;
                System.out.println("SENTENCE: " + sentence);
                outToServer.writeBytes(sentence + '\n');
                reply = inFromServer.readLine();
                System.out.println("ANSWER: " + reply);

            clientSocket.close();

        }
        catch (Exception io) {
            System.out.println("Connection refusée: arrêt");
        }
    }
}

I am calling this in my android application : I have a button which use this method when I'm clicking on it :

public void signalerComplet(View view)
{
    client = new IR("complet");
    Toast.makeText(this, "envoyé", Toast.LENGTH_SHORT).show();
}

But my server doesn't get anything . Though, I ma sure that my client works when I'm using it not in my android application . Could somebody say to me what I am missing here ?

EDIT after getting Hector's help : the server gets my "bloubloubloub" but I get an android.os.NetworkOnMainThreadException on the "int size = in.read(data);" ...

private Socket socket;

  public void signalerComplet(View view)
{
    PrintWriter out = null;
    InputStream in=null;

    byte[] data = new byte[5120];

    try {
        out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
    }
    catch (IOException e) {
        e.printStackTrace();
    }

    out.println("bloubloubloub" + '\n');
    out.flush();

    try {
        in = socket.getInputStream();
        int size = in.read(data);
    }
    catch (IOException e) {
        e.printStackTrace();
    }

    Log.e("data from server", data.toString());
}

Answer:

type.equals(null) will always be false as if the variable type actually holds a null value it will throw a NullPointerException as there is no method equals for the null value. Therefore the if body will never execute.

The correct way to match if a variable is null is by the == operator.

if (type == null) {
  // do this
} else {
  // do that
}

equals() on a String should be used to compare against another String.

Question:

I've been working on a chat room.

Multi Threaded Server accepts the clients

    btnConnect.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent arg0) {
            try{


                int port = 2345;
                ServerSocket server = new ServerSocket(port);
                System.out.println("Waiting for clients");
                Thread thread = new Thread(){
                    public void run(){
                        while(true){
                            Socket socket;
                            try {
                                socket = server.accept();
                                gui.AddUserToList(socket);
                                ConnectionArray.add(socket);
                                ChatClient chat = new ChatClient(socket,gui);
                                Thread x = new Thread(chat);
                                x.start();
                            } catch (IOException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }

                        }
                    }
                };
                thread.start();
            }
            catch(IOException error){
                System.out.println(error);
            }


        }
    });

When the connect button is pressed it will run an infinite loop to accept clients. For each client it connects, it ads it to a ListArray called AddUserToList.

A ChatClient is made and the object is passed in the Thread constructor.

public void isConnected(){
    if(!socket.isConnected()){

        for(int i = 1; i <= GUI.ConnectionArray.size(); i++){

            if(GUI.ConnectionArray.get(i) == socket){
                GUI.ConnectionArray.remove(i);
                gui.updateList();

            }
        }

    }
}


@Override
public void run() {
    try
    {
        try
        {
            input = new Scanner(socket.getInputStream());
            out = new PrintWriter(socket.getOutputStream());

            while(true)
            {
                isConnected();
                if(!input.hasNext())
                    return;



                message = input.nextLine();


                for(int i = 1; i <= GUI.ConnectionArray.size(); i++){
                    Socket tmpSocket = (Socket) GUI.ConnectionArray.get(i-1);
                    PrintWriter tmpOut = new PrintWriter(tmpSocket.getOutputStream());
                    tmpOut.println(message);
                    tmpOut.flush();
                    //System.out.println("Sent");


                }                   
            }

        }
        finally
        {
            socket.close();
        }
    }
    catch(IOException io){
        System.out.println(io);
    }

}

If there is are no messages coming then it should check the connection. When I disconnect on my client.

            while(true)
            {
                isConnected();
                if(!input.hasNext())
                    return;

This line should go back since nothing is being sent, so why does the program get stuck trying to listen on messages?

Is there really no way to close a socket? Because I need to remove the user/socket from the ArrayList and then update it to show me that there is no client connected.


Answer:

You need to check for the end of stream condition on all your reads and Scanner invocations. You aren't doing that anywhere. The isConnected() method doesn't do that. It only tells you whether you ever connected this socket.. It doesn't magically become false when the peer disconnects. Neither does isClosed() magically become true at that time.

Question:

I have classic http client/server application where the server serves the clients data at their will but also performs some kind of call-backs to the list of clients' addresses it has. My two questions are :

1- How would the server know if a client is down (the client did not disconnect but the connection got suddenly interrupted) ?

2- Is there a way to know from the server-side if the process at client-side listening on the call-back port is still up (i.e. client call-back socket is still open) ?


Answer:

1- How would the server know if a client is down (the client did not disconnect but the connection got suddenly interrupted) ?

  • Option #1: direct communication

    Client tells server "I'm alive" at a periodic interval. You could make your client to ping your server at a configurable interval, and if the server does not receive the signal for a certain time, it'll mark the client as down. Client could even tell server more info(e.g. It's status) in each heartbeat if necessary, this is also the way used in many distributed systems(e.g. Hadoop/Hbase).

  • Option #2: distributed coordination service

    You could treat all clients connected to a server as a group, and use a 3rd party distributed coordination service like Zookeeper to facilitate the membership management. Client registers itself to Zookeeper as a new member of the group right after booting up, and leaves the group if it's down. Zookeeper notifies the server whenever the membership changes.

2- Is there a way to know from the server-side if the process at client-side listening on the call-back port is still up (i.e. client call-back socket is still open) ?

  • I think this can only be done by the way Option #1 listed above. It could be either the way clients tell server "My callback port is OK" at a fixed interval, or the server asks clients "Are your callback port OK?" and wait its response at a fixed interval

Question:

I'm trying to implementing a TCP server-client application. Server is written in C++ and client is in Java.

  1. TCP server is working with CURL and Mozilla browser but not with CHROME as well as Java client.
  2. The client side script is able to hit the server but not able to retrieve the response and print from the server message.

Client.java

//client side 
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.io.UnsupportedEncodingException;

public class Client {

    public static void main(String[] args) {

        URL url = null;
        try {
            url = new URL("http://192.168.1.101:12345");
        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new InputStreamReader(url.openStream(), "UTF-8"));
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        try {
            for (String line; (line = reader.readLine()) != null;) {
                System.out.println(line);
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
}

server.cpp

// Server side C/C++ program to demonstrate Socket programming 
#include <unistd.h> 
#include <stdio.h> 
#include <sys/socket.h> 
#include <stdlib.h> 
#include <netinet/in.h> 
#include <string.h> 
#define PORT 12345
int main(int argc, char const *argv[]) 
{ 
    int server_fd, new_socket, valread; 
    struct sockaddr_in address; 
    int opt = 1; 
    int addrlen = sizeof(address); 
    char buffer[1024] = {0}; 
    char *hello = "Hello from server"; 

    // Creating socket file descriptor 
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) 
    { 
        perror("socket failed"); 
        exit(EXIT_FAILURE); 
    } 

    // Forcefully attaching socket to the port 8080 
    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, 
                                                &opt, sizeof(opt))) 
    { 
        perror("setsockopt"); 
        exit(EXIT_FAILURE); 
    } 
    address.sin_family = AF_INET; 
    address.sin_addr.s_addr = INADDR_ANY; 
    address.sin_port = htons( PORT ); 

    // Forcefully attaching socket to the port 8080 
    if (bind(server_fd, (struct sockaddr *)&address, 
                                sizeof(address))<0) 
    { 
        perror("bind failed"); 
        exit(EXIT_FAILURE); 
    } 
    if (listen(server_fd, 3) < 0) 
    { 
        perror("listen"); 
        exit(EXIT_FAILURE); 
    } 
    if ((new_socket = accept(server_fd, (struct sockaddr *)&address, 
                    (socklen_t*)&addrlen))<0) 
    { 
        perror("accept"); 
        exit(EXIT_FAILURE); 
    } 
    valread = read( new_socket , buffer, 1024); 
    printf("%s\n",buffer ); 
    send(new_socket , hello , strlen(hello) , 0 ); 
    printf("Hello message sent\n"); 
    return 0; 
} 

" Hello from server was not displayed on console and also java giving ERROR MESSAGE :

java.io.IOException: Invalid Http response
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1606)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1492)
    at java.net.URL.openStream(URL.java:1045)
    at com.sri.tcptest.Client.main(Client.java:24)
Exception in thread "main" java.lang.NullPointerException
    at com.srinar.tcptest.Client.main(Client.java:34) "

Answer:

In server.cpp file, change:

char *hello = "HTTP/1.1 200 OK\r\nContent-Length: 17\r\nContent-Type: text/html\r\n\r\nHello from server"; 

Question:

That is my program in java for my android app. I tried to create tcp connection with tcp server. I can connect to server with another applications so that i can send and receive from tcp server. With my code and with my program i can send messages to server very eazy, but i have troubles with receiving messages from server.

private  Socket socket;
private  final int SERVERPORT = 6060;    
private  final String SERVER_IP = "192.168.0.8";
public  TextView tv;
private PrintWriter out;
private InputStream in;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    tv=(TextView)this.findViewById(R.id.textView1);
     new Thread(new ClientThread()).start();

}   

Here is my problem i dont know how to receive strings or bytes from server. When i run my app on phone it closes the open window and say that program stop working. If i delete this section of code(public void ONCLICK2) i can transmit messages to server.

  public void   ONCLICK2(View view)  {

       try {
        in=socket.getInputStream();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
        byte array[]=new byte[1];
        try {
            int i=in.read(array);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }


  }

So please help me with that section of code. How can i receive string send from TCP server.

    public void onClick(View view) {
                try {
                EditText et = (EditText) findViewById(R.id.editText1);
                String str = et.getText().toString();

                    out.println(str);
                    out.flush();

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


class ClientThread implements Runnable {

     @Override
            public void run() {

               try {
                   InetAddress serverAddr = InetAddress.getByName(SERVER_IP);

                    socket = new Socket(serverAddr, SERVERPORT);

                    out = new PrintWriter(new BufferedWriter(
                            new OutputStreamWriter(socket.getOutputStream())),
                                    true);



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

         }

}

Answer:

Simply put, the problem is you are intercepting the byte array of an unknown length and attempting to store them in array the size of one. Furthermore, it is ideal to append the packet size prior to the data in the packet and perhaps create the intercept in a separate thread waiting for incoming packets.

To just fix your ONCLICK2 you should do the following:

byte[] data = new byte[6556];
try {
   in = socket.getInputStream();
   // NOTE: The data byte array will contain empty values if
   // under the size of 6556
   int size = in.read(data);

   // send to LogCat
   Log.e("String", data.toString());
} catch (Exception e) {
   e.printStackTrace();
}

I have not tested this code, but this should fix your problem.

Question:

I have a Spring-Integrations server setup that will accept tcp connection through a DirectChannel And then perform some math on the message and send an new message out to another server with another DirectChannel and it works great. Now I need to have an action take place the first time a connection is established between the server and a new client. I have been looking all week and can't find the right way to do this. All of my Integration configuration is Java (no xml). Can I get some help figuring out how to capture or listen for the first time a new client connection with my server? Thanks for help in advanced


Answer:

The AbstractServerConnectionFactory implementations publish TcpConnectionOpenEvent in that case. That is regular Spring Application Event, although you can handle it with the ApplicationEventListeningMessageProducer.

See more info in the Reference Manual: http://docs.spring.io/spring-integration/docs/4.3.5.RELEASE/reference/html/ip.html#tcp-events

Question:

Using java socket library and what I see is that when the server accepts the tcp connection but not read data from the buffer and in the meantime our client keep pumping heavy data, client side heap size grows to max available and crushes the client application. Is there anyway I can limit the socket buffer size or whatever using that heap and if it is violated, connection is killed? This way client can detect client detect the connection is gone and

Client Side;

  this.socket = new Socket(server, port);
  this.socket.setKeepAlive(true);
  this.outwriter = new OutputStreamWriter(this.socket.getOutputStream());
  this.outwriter.write(o.toString()); 

Server Side;

conn = serverSocket.accept();

Answer:

This is not cause by the socket. You have a memory leak elsewhere in your application. The behaviour you describe will eventually block in the write() method and will not consume any heap memory whatsoever.

Question:

I am trying to send an image from java TCP Client to Node.js TCP Server i have tried to: send binary data, send base64 encoded binary data,send utf-8 encoded strings and at the moment nothing has worked, i always got the data and it creates the image(using fs), but its always corrupted. Here is my code:

JAVA CLIENT:

import java.util.*;
import java.io.*;
import java.net.Socket;

public class client{

    public static void main(String[] args) throws Exception {
        Socket client = new Socket("localhost",8080);
        Scanner scanner = new Scanner(System.in);
        String path= scanner.nextLine();
        FileInputStream fis = new FileInputStream(path);
        byte[] buffer = new byte[fis.available()];
        fis.read(buffer);
        buffer= Base64.getEncoder().encode(buffer);
        System.out.println(buffer.length);
        ObjectOutputStream oos= new ObjectOutputStream(client.getOutputStream());
        oos.writeObject(buffer);
        client.close();
    }
}

Node.js Server:

var fs = require('fs');
var net = require('net');
var sockets = [];
var server=net.createServer().listen(8080,"localhost");

server.on('connection', function(socket){
    console.log('Someone connected.');
    sockets.push(socket);
    var imageData;

    socket.on('data',function(data){
        imageData+= Buffer.from(data, 'base64');
    });

    socket.on('end',function(){
        console.log(imageData.length)
        fs.writeFileSync(new Date()+".png", imageData, function (err) {
          if (err) throw err;
          else  console.log('Saved!');
        });
    });

    socket.on('close',function(){
        console.log("Someone disconnected.");
    });
});

please i need help, its the fourth time i made this question and nobody answers me, or they say something that doesn't help and give me -1.

Here is the image output

UPDATE: I tried working with strings and i first detected that the data length when received is not equal of the data length sent, so i removed the data in excess and still didn't work, i am thinking that fs library is bugged, can someone suggest me a better library that works with file in Node.js?


Answer:

There are a couple of errors that are causing the problem.

First of all, in your sender code, you're using an ObjectOutputStream which, as the name suggests, is made for sending objects. What you need is instead the DataOutputStream, which is made for primitive data types. It's also a lot faster than ObjectOutputStream since it has to handle fewer situations.

So the first change will be something like this:

DataOutputStream oos= new DataOutputStream(client.getOutputStream());
oos.write(buffer);

The next problem is on the receiving side. The socket.on('data') event happens many times during transmission, even if we're receiving the same string! This means that you'll have to wait for the transmission to finish before decoding from base64 to raw data. Another mistake you've made is not initializing the imageData var when creating it.

Let's see the code to make everything more clear. First of all, declaring imageData:

var imageData = "";

Now we know it is for sure an empty string. Next, receiving data:

socket.on('data',function(data){
    imageData += data;
});

As you can see I'm not decoding data here anymore, because it must be done after receiving everything. Last thing, decoding:

socket.on('end',function(){
    console.log(imageData.length)
    var decoded = Buffer.from(imageData, 'base64');
    fs.writeFileSync(new Date()+".png", decoded, function (err) {
        if (err) throw err;
        else  console.log('Saved!');
    });
});

The decoding now is done during the end event, when we have the entire string.

I've tried this and it's working fine now.

Question:

I have the below code to accept multiple client from my Java Server.

private class SocketServerThread extends Thread {
        int count = 0;
        String error_message = null;
        @Override
        public void run() {
            try{
                serverSocket = new ServerSocket(theSocketServerPORT);
                while (true){
                    final Socket socket = serverSocket.accept();
                    count++;
                    runOnUiThread(new Runnable(){
                        @Override
                        public void run() {
                            Toast.makeText(getApplicationContext(),"New Client with IP: " + socket.getInetAddress() + " and PORT: " + socket.getPort(),Toast.LENGTH_LONG).show();
                        }
                    });
                    SocketServerListenToMessage socketServerListenToMessage = new SocketServerListenToMessage(socket); 
                    socketServerListenToMessage.run();// Start to Receive now
                }
            }catch (IOException e){
                Log.e("IO ERROR",e.toString());
                error_message = "IO ERROR";
            }catch (Exception e){

                Log.e("EX ERROR",e.toString());
                error_message = "EX ERROR";
            }
            if(error_message!=null){
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(getApplicationContext(),error_message,Toast.LENGTH_LONG).show();
                    }
                });
            }
        }
    }

Once the client is connected, I call the SocketServerListenToMessage to start listening to client message.

The below code is for SocketServerListenToMessage.

private class SocketServerListenToMessage extends Thread{
        Socket theClientSocket;
        SocketServerListenToMessage(Socket clientSocketListener){
            theClientSocket = clientSocketListener;
            Log.w("SERVER STATUS","Starting to Listen to Clients...");
        }
        @Override
        public void run(){
            try{
                InputStream is = theClientSocket.getInputStream();
                while(true){
                    byte[] lenBytes = new byte[4];
                    is.read(lenBytes, 0, 4);
                    int len = (((lenBytes[3] & 0xff) << 24) | ((lenBytes[2] & 0xff) << 16) |
                           ((lenBytes[1] & 0xff) << 8) | (lenBytes[0] & 0xff));
                    byte[] receivedBytes = new byte[len];
                    is.read(receivedBytes, 0, len);
                    final String received = new String(receivedBytes, 0, len);

                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Toast.makeText(getApplicationContext(),"Client Says: " + received, Toast.LENGTH_LONG).show();
                            Log.w("Client Says", received);
                        }
                    });
                }
            }catch (IOException e){
                Log.e("IO ERR FROM LISTEN MSG", e.toString());
            }
            catch (Exception e){
                Log.e("EX ERR FROM LISTEN MSG", e.toString());
            }
        }
    }

With the above code, I can connect multiple client. I can also receive the Message from my client. But the problem is I am able to receive a message only from the First Client that is become connected to my Server. The second and soon client was not.

The below code is for my Client to Send Message. Note I am using C# for my client.

IPEndPoint serverAddress;
Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);  //I am using Socket

/*********To Send Message to Server**********/

String toSend = txt_v.Text; //The message came from TextBox.
Task f = Task.Factory.StartNew(() => {
     if (clientSocket.Connected)
     {
       int toSendLen = System.Text.Encoding.ASCII.GetByteCount(toSend);
       byte[] toSendBytes = System.Text.Encoding.ASCII.GetBytes(toSend);
       byte[] toSendLenBytes = System.BitConverter.GetBytes(toSendLen);
       clientSocket.Send(toSendLenBytes);
       clientSocket.Send(toSendBytes);

      }
});

I think the problem is in while loop in SocketServerListenToMessage. I tried to remove the while loop and the Server was able to receive the message from all client but it's only one message per client. I want the Server to listen to client's message until they become disconnected. How can I do that?


Answer:

I just make it work. Thanks to this Link.

If I'm not mistaken, from the link, I am using a singlethreaded. So from my SocketServerThread I have to change

SocketServerListenToMessage socketServerListenToMessage = new SocketServerListenToMessage(socket); 
                    socketServerListenToMessage.run();// Start to Receive now

to

new Thread(new SocketServerListenToMessage(socket)).start();

and change the class SocketServerListenToMessage to

private class SocketServerListenToMessage implements Runnable {
        protected Socket clientSocket = null;

        public SocketServerListenToMessage(Socket clientSocket) {
            this.clientSocket = clientSocket;
        }

        @Override
        public void run() {
            try {
                while (true){
                    InputStream is = clientSocket.getInputStream();
                    byte[] lenBytes = new byte[4];
                    is.read(lenBytes, 0, 4);
                    int len = (((lenBytes[3] & 0xff) << 24) | ((lenBytes[2] & 0xff) << 16) |
                            ((lenBytes[1] & 0xff) << 8) | (lenBytes[0] & 0xff));
                    byte[] receivedBytes = new byte[len];
                    is.read(receivedBytes, 0, len);
                    final String received = new String(receivedBytes, 0, len);

                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Toast.makeText(getApplicationContext(), "Client Says: " + received, Toast.LENGTH_LONG).show();
                            Log.w("Client Says", received);

                        }
                    });
                }

            } catch (IOException e) {
                Log.e("IO ERR FROM LISTEN MSG", e.toString());
            } catch (Exception e) {
                Log.e("EX ERR FROM LISTEN MSG", e.toString());
            } finally {
                try{
                    clientSocket.close();
                    Log.w("CLIENT DISCONNECTED", "A client is disconnected.");
                }catch (IOException e){
                    Log.w("IO ERR DISCONNECTION", e.toString());
                }
            }
        }
    }

I just need to implement Runnable instead of Thread to make it Multi.

Question:

Refer to Running the client with SSL/TLS. This explains a scenario where server does a client authentication. I am using Spring Integration to process TLS connections. My spring-context file is:

   <bean id="sslContextSupport"
        class="org.springframework.integration.ip.tcp.connection.DefaultTcpSSLContextSupport">
        <constructor-arg value="file:keystore.jks"/>
        <constructor-arg value="file:truststore.jks"/>
        <constructor-arg value="keystorepass"/>
        <constructor-arg value="trustpass"/>
    </bean>

    <int-ip:tcp-connection-factory id="crLfServer"
            type="server"
            port="${availableServerSocket}"
            single-use="true"
            so-timeout="10000"
            using-nio="false"
            ssl-context-support="sslContextSupport" />

My Server is accepting SSL connections and processing with certificates installed on my server and client. I am not sure whether the above spring configuration is setup for client authentication or not. is the client authentication done at the SSL transaport level or in the Application code?


Answer:

The Spring Integration DefaultTcpSSLContextSupport is fully based on the SSLContext sslContext = SSLContext.getInstance(protocol);. So, what you see in the standard Java SSL/TLS documentation is applied here as well.

Since that your <int-ip:tcp-connection-factory> produces type="server", that is definitely the case of

the server does client authentication

All the hard SSL work is done in the SSLContext layer, not in the TcpNetServerConnectionFactory, if that is the question.

In other words: it doesn't matter that it is Spring Integration or not. Everything works the same way as in any other Java application which users standard SSL/TLS approach.

Question:

This code snippet is from a TCP helper function I made in Android java:

            socket.setSoTimeout(2000);
            InputStream inStream = socket.getInputStream();
            PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),
            true);

            out.println(message);

            BufferedReader input = new BufferedReader(new InputStreamReader(inStream));

            String tcpResult = "";

            if(lastCallMillis >= System.currentTimeMillis() - 100)
                Thread.sleep(100);

            tcpResult = input.readLine();

When the very first line is there, the one with "setSoTimeout", the method fails with an exception. When I do NOT set the timeout it works without a hitch.

Well.. almost I had to insert this part because if the socket was used quickly in a row it failed:

            if(lastCallMillis >= System.currentTimeMillis() - 100)
            Thread.sleep(100);

Anyway am I misunderstanding something about using java sockets or is it just horribly supported?


Answer:

If you don't want a shot read timeout don't set a short read timeout. Adding sleeps to networking code never solves anything. It is just literally a waste of time. What you should have done was added the sleep time to the timeout. But even 2.1 seconds is ludicrously short for a read timeout. Try ten, or thirty.

Question:

I am trying to make a very simple client/server connection. I have Android app as a client and trying to

1) pass message to Java program on PC and then

2) return a message back to the android client.

First part is working fine. The problem is in returning the message from server to client.

Server code (Java):

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;


public class Main {

    private final static Integer IN_PORT = 4444; 

    private static ServerSocket serverSocket = null;
    private static Socket sktIn;
    private static InputStreamReader inputStreamReader;
    private static BufferedReader bufferedReader;
    private static String message;

    private static PrintWriter printWriter;

    public static void main(String[] args) {

        try {
            serverSocket = new ServerSocket(IN_PORT);  //Server socket
            System.out.println("Server started. Listening to the port " + IN_PORT);        
        } catch (IOException e) {
            System.out.println("Could not listen on port: " + IN_PORT);
        }


        while (true) {
         try {
          sktIn = serverSocket.accept();   //accept the client connection
                inputStreamReader = new InputStreamReader(sktIn.getInputStream());
                bufferedReader = new BufferedReader(inputStreamReader); //get the client message
                message = bufferedReader.readLine();

                printWriter = new PrintWriter(sktIn.getOutputStream(), true);
                printWriter.write("Returned back \n");  //write the message to output stream
                printWriter.flush();
                printWriter.close();             
                inputStreamReader.close();               
                sktIn.close();

                System.out.println(message);                               

            } catch (IOException ex) {
                System.out.println("Problem in message reading/sending.");
                ex.printStackTrace();
            }

        }

    }
}

Client main activity (Android):

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

public class SimpleClientActivity extends Activity {

    private final Integer OUT_PORT = 4444;
    private final String S_IP = "192.168.1.104"; 

    private EditText textField;
    private Button button;
    private String message;


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

        textField = (EditText) findViewById(R.id.editText1); //reference to the text field
        button = (Button) findViewById(R.id.button1);   //reference to the send button

        //Button press event listener
        button.setOnClickListener(new View.OnClickListener() {

            public void onClick(View v) {

                message = textField.getText().toString(); //get the text message on the text field
                textField.setText("");      //Reset the text field to blank

                new ConnectClient(message, S_IP, OUT_PORT, getApplicationContext()).execute(); 
            }
         });
    }
}

Separate AsyncTask class for connection:

import android.content.Context;
import android.os.AsyncTask;
import android.widget.Toast;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;

public class ConnectClient extends AsyncTask<String, Void, String> {

    private Socket socket;
    private PrintWriter printWriter;

    private String param;   
    private Context context;
    private Integer PORT;
    private String IP;

    private static InputStreamReader inputStreamReader;
    private static BufferedReader bufferedReader;
    private static String message;


 public ConnectClient(String par, String ip, Integer prt, Context ctx){
  super();
     this.context = ctx;
     this.param = par;
     this.PORT = prt;
     this.IP = ip;
 }

 @Override
    public void onPreExecute() {
        Toast.makeText(context, "start " + param, Toast.LENGTH_SHORT)
           .show();
    }

 @Override
    protected String doInBackground(String... params) {

        try {
                socket = new Socket(IP, PORT);  //connect to server

                printWriter = new PrintWriter(socket.getOutputStream(), true);
                printWriter.write(param);  //write the message to output stream

                printWriter.flush();
                printWriter.close();

                socket = new Socket(IP, PORT); // second connection to server     
                inputStreamReader = new InputStreamReader(socket.getInputStream());
                message = "after isr";
                bufferedReader = new BufferedReader(inputStreamReader); //get the client message
                message = bufferedReader.readLine();
                inputStreamReader.close();          
                socket.close();   //closing the connection

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

        return message;
    }

    @Override
    protected void onPostExecute(String result) {
        Toast.makeText(context, result, Toast.LENGTH_SHORT).show()   
    }

    @Override
    protected void onProgressUpdate(Void... values) {
        Toast.makeText(context, "In progress", Toast.LENGTH_SHORT).show();
    }
}

The java program executes ok and the Android app runs without any problems but the end result is not as desired.

If I remove the second socket = new Socket(IP, PORT); // second connection to server , then server is receiving messages fine. In the java console I get printed whatever I put in the app and send. But the second Toast is empty (the message from the server is not passed). And I get SocketException (closed) in the LogCat:

01-29 06:38:36.039: W/System.err(11547): java.net.SocketException: Socket is closed
01-29 06:38:36.059: W/System.err(11547):  at java.net.PlainSocketImpl.checkNotClosed(PlainSocketImpl.java:134)
01-29 06:38:36.059: W/System.err(11547):  at java.net.PlainSocketImpl.getInputStream(PlainSocketImpl.java:216)
01-29 06:38:36.059: W/System.err(11547):  at java.net.Socket.getInputStream(Socket.java:343)
01-29 06:38:36.059: W/System.err(11547):  at com.example.simpleclient.ConnectClient.doInBackground(ConnectClient.java:63)
01-29 06:38:36.059: W/System.err(11547):  at com.example.simpleclient.ConnectClient.doInBackground(ConnectClient.java:1)
01-29 06:38:36.059: W/System.err(11547):  at android.os.AsyncTask$2.call(AsyncTask.java:287)
01-29 06:38:36.059: W/System.err(11547):  at java.util.concurrent.FutureTask.run(FutureTask.java:234)
01-29 06:38:36.059: W/System.err(11547):  at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
01-29 06:38:36.059: W/System.err(11547):  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
01-29 06:38:36.059: W/System.err(11547):  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
01-29 06:38:36.059: W/System.err(11547):  at java.lang.Thread.run(Thread.java:841)

If I leave socket = new Socket(IP, PORT); // second connection to server line of code in, there are no error messages, but the message is passed only once to the server. 2nd, 3rd, end so forth don't go through (nothing displaying in the console). Though if I leave the console running and shut down the app, another null comes through.

In any case, the second Toast (on the client side) is either empty (the message from the server is not passed) or not displayed at all (message = bufferedReader.readLine(); blocks further execution). For instance, If I comment out the line message = bufferedReader.readLine(); , then I get "after isr" in the second Toast. Or, in the case when the second socket = new Socket(IP, PORT); // second connection is present the second Toast does not display at all.

What am I missing. How do I send a message from server back to the client?


Answer:

The instructions of client and server must be symmetric.

If the client writes, the server must read and viceversa

If the client opens an inputStream, the server must open an outputStream.

Now in the first connection you open only the outputStream but in the server you have both of them.

Also you open two connections (client) that are handled as one in the server, so the first printing operations work fine because there are reading operations on server, but the others can't work because you create another connection that the server can't handle because:

1)the server is not multithread

2)the server have to work on the first connection

Question:

I am experimenting with a file transfer program in Java and I wanted to create a server that would handle creating P2P connection between two clients.

Don't know how that should work, exchanging sockets? I don't want to exchange IP address... Seen some questions similar (ev. Connecting two clients via server java) but I have no idea how to achieve that. Thanks for your time


Answer:

It sounds like you are looking for nat traversal techniques. There is no single solution because there are many different network setups. Most p2p software employs a combination of different solutions, such as using IPv6 where available, negotiating with home routers and operating system firewalls or NAT hole punching. Servers can assist in the last point.

Question:

I'm having some troubles while trying to visualize the message send from the TCP Server as response to my TCP Client

Here is my Client.java code

public class Client {


public static String SERVER_IP; //server IP address
public static String ipp;
public static final int SERVER_PORT = 4444;
// 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 Client(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);
}

}

While here is the MainActivity :

public class MainActivity extends AppCompatActivity {
Server server;
static Client client;
settings Settings;
public static TextView terminale, indr, msg;
TextView log;
static String ipp;
static String trm;
static DataBaseHandler myDB;
allert Allert;
SharedPreferences prefs;
String s1 = "GAB Tamagnini SRL © 2017 \n" +
        "Via Beniamino Disraeli, 17,\n" +
        "42124 Reggio Emilia \n" +
        "Telefono: 0522 / 38 32 22 \n" +
        "Fax: 0522 / 38 32 72 \n" +
        "Partita IVA, Codice Fiscale \n" +
        "Reg. Impr. di RE 00168780351 \n" +
        "Cap. soc. € 50.000,00 i.v. \n" + "" +
        "REA n. RE-107440 \n" +
        "presso C.C.I.A.A. di Reggio Emilia";
ImageButton settings, helps, allerts, home;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Utils.darkenStatusBar(this, R.color.colorAccent);
    server = new Server(this);
    myDB = DataBaseHandler.getInstance(this);

    msg = (TextView) findViewById(R.id.msg);
    log = (TextView) findViewById(R.id.log_avviso);
    settings = (ImageButton) findViewById(R.id.impo);
    helps = (ImageButton) findViewById(R.id.aiut);
    allerts = (ImageButton) findViewById(R.id.msge);
    home = (ImageButton) findViewById(R.id.gab);
    terminale = (TextView) findViewById(R.id.terminal);
    indr = (TextView) findViewById(R.id.indr);

    final Cursor cursor = myDB.fetchData();
    if (cursor.moveToFirst()) {
        do {
            indr.setText(cursor.getString(1));
            terminale.setText(cursor.getString(2));
            Client.SERVER_IP = cursor.getString(1);
            trm = cursor.getString(2);
        } while (cursor.moveToNext());
    }



    WifiManager wm = (WifiManager) getSystemService(WIFI_SERVICE);
    ipp = Formatter.formatIpAddress(wm.getConnectionInfo().getIpAddress());


    startConnection.postDelayed(runnableConnection,5000);
    startMessage.postDelayed(runnableMessage,5500);

    cursor.close();
    server.Parti();


    home.setOnClickListener(new View.OnClickListener() {
                                int counter = 0;
        @Override
        public void onClick(View view) {
                                    counter++;
                                    if (counter == 10) {
                                        AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
                                        builder.setCancelable(true);
                                        builder.setMessage(s1);
                                        builder.show();
                                        counter = 0;
                                    }
        }
    });

    settings.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent impostazioni = new Intent(getApplicationContext(), settingsLogin.class);
            startActivity(impostazioni);
        }
    });

    helps.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent pgHelp = new Intent(getApplicationContext(), help.class);
            startActivity(pgHelp);
        }
    });

    allerts.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Server.count = 0;
            SharedPreferences prefs = getSharedPreferences("MY_DATA", MODE_PRIVATE);
            SharedPreferences.Editor editor = prefs.edit();
            editor.clear();
            editor.apply();
            msg.setVisibility(View.INVISIBLE);
            Intent pgAlert = new Intent(getApplicationContext(), allert.class);
            startActivity(pgAlert);
        }
    });

}

@Override
protected void onDestroy() {

    super.onDestroy();
    server.onDestroy();
}

public static class ConnectTask extends AsyncTask<String, String, Client> {

    @Override
    protected Client doInBackground(String... message) {


        client = new Client(new Client.OnMessageReceived() {
            @Override

            public void messageReceived(String message) {

                messageReceived(message);
            }
        });
        client.run();

        return null;
    }

    @Override
    protected void onProgressUpdate(String... values) {
        super.onProgressUpdate(values);

        Log.d("test", "response " + values[0]);


    }
}

static Handler startConnection = new Handler();
static Runnable runnableConnection = new Runnable() {
    @Override
    public void run() {

        new ConnectTask().execute("");
    }
};

static Handler startMessage = new Handler();
static Runnable runnableMessage = new Runnable() {
    @Override
    public void run() {
        final Cursor cursor = myDB.fetchData();
        if (cursor.moveToFirst()) {
            do {
                Client.SERVER_IP = cursor.getString(1);
                trm = cursor.getString(2);
            } while (cursor.moveToNext());
        }
        if (client != null) {
            client.sendMessage(ipp + "#" + trm);
        }
    }
};

}

So what i'm trying to do is receive message from the server and visualize it in help.java activity in a TextView called msgServer set as static. Actually i don't know which value i have to attribute to the help.msgServer.setText() and where to put it in MainActivity.


Answer:

Fixed by setting in AsyncTask in MainActivity following code:

msgServer.setTextColor(Color.parseColor("#00FF00"));
msgServer.setText("ONLINE");

in the onProgressUpdate method. So i identified the right place from where i can get the message sent by the server, the message is contained in:

values

.

Question:

I am going for the simplest explanation. My Java TCP project has a server and three clients.

The server has a ClientThread. The clients each has a ServerThread and a UserThread.

The workflow is: 1. The UserThread of a client (say, client_0) gets user input and then sends a message to the server. 2. The ClientThread of the server captures the message from client_0 and sends another message to the ServerThread of a different client (say, client_1). 3. The ServerThread of client_1 then sends back another message to the ClientThread running in the server;

The message of step 3 is not reaching the server.

There are total 3 clients, say client_0, client_1 and client_2. The original idea is that if client_0 requests the server then the server communicates with client_1 and client_2. That's why the line if(i==cid) continue; in the for loop in the server. But, if i comment out this line, the server communicates with the client_0 (which is unnecessary semantically) and the messaging problem doesn't happen. After that the server communicates with client_1 and the problem appears again.

The server can receive message from the ServerThread of the client (client_0) that sent the original request (msgToServer.println("get list");) from it's UserThread to initiate the whole process. But Server cannot get message from any other client's ServerThread even though it can send message to others and all the client programs are identical and all the ServerThreads and UserThreads should work the same eway. How is it even possible?

Server:

package serverftp;
import java.io.*;
import java.net.*;

public class ServerFTP {

    static String[] id = {"cp 1","cp 2","cp 3"};
    static String[] pass = {"123","456","789"};

    static BufferedReader[] msgFromClient = new BufferedReader[3];
    static PrintWriter[] msgToClient = new PrintWriter[3];
    static InputStream[] fileFromClient = new InputStream[3];
    static OutputStream[] fileToClient = new OutputStream[3];

    public static void main(String[] args) throws Exception {
        ServerSocket welcome = new ServerSocket(6789);

        // connecting the three clients
        for(int i=0; i<3; i++) {
            System.out.println("Waiting for Client "+i);
            Socket clientSocket;
            clientSocket = welcome.accept();

            while(true) {
                System.out.println("Connecting Client "+i);

                BufferedReader fromClient = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
                PrintWriter toClient = new PrintWriter(clientSocket.getOutputStream(),true);

                // get id pass from client
                String clientId = fromClient.readLine();
                System.out.println(clientId);
                String clientPass = fromClient.readLine();
                System.out.println(clientPass);

                // check id pass and feedback
                if(clientId.equals(id[i]) && clientPass.equals(pass[i])) {
                    toClient.println("ok");

                    msgFromClient[i] = fromClient;
                    msgToClient[i] = toClient;
                    fileFromClient[i] = clientSocket.getInputStream();
                    fileToClient[i] = clientSocket.getOutputStream();

                    break;
                } else {
                    toClient.println("error");
                }
            }

            ClientThread ct = new ClientThread(i);
            ct.start();
            System.out.println("Client "+i+" connected!");
        }

        welcome.close();
    }

}

class ClientThread extends Thread {
    int cid;
    String msg;

    public ClientThread(int client_id) {
        cid = client_id;

        try {
            // telling client it's serial
            ServerFTP.msgToClient[cid].println(Integer.toString(cid));
        } catch(Exception ex) {
            ex.printStackTrace();
        }
    }

    @Override
    public void run() {
        while(true) {
            try {
                // get request from receiver
                msg = ServerFTP.msgFromClient[cid].readLine();
                if(msg.equals("get list")) {
                    System.out.println(cid+" "+msg);

                    msg = ServerFTP.msgFromClient[cid].readLine();
                    System.out.println(cid+" "+msg);

                    for(int i=0; i<3; i++) {
                        if(i==cid) continue;

                        // send sender request for file list
                        ServerFTP.msgToClient[i].println("give list");
                        System.out.println("request sent to client "+i);

                        // get file count from sender
                        msg = ServerFTP.msgFromClient[i].readLine();
                        System.out.println("file count caught!!!"); // THIS LINE NEVER EXECUTES
                        System.out.println("File count "+msg);
                    }
                }
            } catch(Exception ex) {
                ex.printStackTrace();
            }
        }
    }
}

The line System.out.println("file count caught!!!"); is never called.

Client:

package clientftp_1;
import java.io.*;
import java.net.*;

public class ClientFTP_1 {

    static String[] allPaths = {   "...path...\\client_1_folder",
                            "...path...\\client_2_folder",
                            "...path...\\client_3_folder"};

    public static void main(String[] args) throws Exception {
        InetAddress inetAddress = InetAddress.getLocalHost();
        Socket server = new Socket(inetAddress,6789);
        int myId;

        // login phase
        BufferedReader fromUser = new BufferedReader(new InputStreamReader(System.in));
        BufferedReader fromServer = new BufferedReader(new InputStreamReader(server.getInputStream()));
        PrintWriter toServer = new PrintWriter(server.getOutputStream(),true);
        InputStream getFile = server.getInputStream();
        OutputStream sendFile = server.getOutputStream();
        while(true) {
            System.out.println("id: ");
            String msg = fromUser.readLine();
            toServer.println(msg);            

            System.out.println("password: ");
            msg = fromUser.readLine();
            toServer.println(msg);

            msg = fromServer.readLine();
            if(msg.equals("ok")) {
                System.out.println("Connection Successful!");
                myId = Integer.parseInt(fromServer.readLine());
                System.out.println("Client serial is: "+myId);
                System.out.println("Folder path is: "+allPaths[myId]);
                break;
            } else {
                System.out.println("Error! Try again please.");
            }
        }

        ServerThread st = new ServerThread(allPaths[myId],fromUser,fromServer,toServer,getFile,sendFile);
        st.start();
        UserThread ut = new UserThread(allPaths[myId],fromUser,fromServer,toServer,getFile,sendFile);
        ut.start();
    }
}

class ServerThread extends Thread {
    String folderPath;
    String msg;
    BufferedReader msgFromServer,msgFromUser;
    PrintWriter msgToServer;
    InputStream fileFromServer;
    OutputStream fileToServer;
    public ServerThread(String path,BufferedReader fromUser,BufferedReader fromServer,PrintWriter toServer,InputStream getFile,OutputStream sendFile) throws Exception {
        folderPath = path;
        msgFromUser = fromUser;
        msgFromServer = fromServer;
        msgToServer = toServer;
        fileFromServer = getFile;
        fileToServer = sendFile;
    }

    @Override
    public void run() {
        System.out.println("Server Thread Started");
        while(true) {
            try {
                // receive request
                msg = msgFromServer.readLine();
                System.out.println("request received from server");
                if(msg.equals("give list")) {
                    // get filenames
                    File folder = new File(folderPath);
                    File[] fileList = folder.listFiles();
                    int cnt = fileList.length;
                    System.out.println("count calculated");

                    // sned file count to server
                    msgToServer.println(Integer.toString(cnt));
                    System.out.println("count sent to server"); // THIS LINE PRINTS
                }
            } catch(Exception ex) {
                ex.printStackTrace();
            }
        }
    }
}

class UserThread extends Thread {
    String folderPath;
    String msg;
    BufferedReader msgFromServer,msgFromUser;
    PrintWriter msgToServer;
    InputStream fileFromServer;
    OutputStream fileToServer;
    public UserThread(String path,BufferedReader fromUser,BufferedReader fromServer,PrintWriter toServer,InputStream getFile,OutputStream sendFile) throws Exception {
        folderPath = path;
        msgFromUser = fromUser;
        msgFromServer = fromServer;
        msgToServer = toServer;
        fileFromServer = getFile;
        fileToServer = sendFile;
    }

    @Override
    public void run() {
        System.out.println("USer Thread Started");
        while(true) {
            try {
                // input from user
                msg = msgFromUser.readLine();
                if(msg.equals("get list")) {
                    // send request to server
                    msgToServer.println("get list");
                    msgToServer.println("fahim list");
                }
            } catch(Exception ex) {
                ex.printStackTrace();
            }
        }
    }
}

The line System.out.println("count sent to server"); is printed. That means the message sending line before that has executed with no problem.

I know the login system in the server is stupid. But it is 'ok' for this work. Everything explained above happens after all the clients have connected and logged in to the server.


Answer:

I think I have found the problem. I was using the same socket for a client program's ServerThread and UserThread. So while the ServerThread is trying to response to the server, most probably the message is going to another different thread in the server that is listening for message (thinking the message comes from UserThread) through the same socket.

Question:

Client:

import java.io.*;
import java.net.*;
class Cliente {

    private boolean loop = true; 
    private int delay = 3000;
    private int id;

    public Cliente(int id){
        this.id = id; 
    }
    public void execute() throws IOException, InterruptedException{
        int nMsg = 0;
        String msg = "Enviou a seguinte mensagem: "; 
        while (loop){ 
            Socket client = new Socket("host",53300); 
            DataOutputStream fromClientOutPut = new DataOutputStream(client.getOutputStream());
            fromClientOutPut.writeBytes("Cliente " + this.id +  ": " + msg + " " + nMsg + " " );
            client.close(); 
            Thread.sleep(this.delay);
        }
    }
    public static void main(String argv[]) throws IOException, InterruptedException{
        BufferedReader readClientId = new BufferedReader(new InputStreamReader(System.in));
        System.out.println("Digite o ID do cliente: ");
        int id = Integer.parseInt(readClientId.readLine());
        Cliente cliente = new Cliente(id);
        cliente.execute();
    }
}

Server:

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

public class Servidor {

    public static void main(String[] args) throws IOException {
        new Servidor(12345).executa();
    }

    private int porta;
    private List<PrintStream> clientes;

    public Servidor(int porta) {
        this.porta = porta;
        this.clientes = new ArrayList<PrintStream>();
    }

    public void executa() throws IOException {

        double num1, num2, total = 0.0;
        char opr = '\n';

        ServerSocket servidor = new ServerSocket(this.porta);
        System.out.println("Porta " + porta + " aberta!");

        while (true) {
            Socket cliente = servidor.accept();

            System.out.println("Nova conexao com o cliente " + cliente.getInetAddress().getHostAddress());
            PrintStream ps = new PrintStream(cliente.getOutputStream());
            this.clientes.add(ps);

            ObjectOutputStream resultado = new ObjectOutputStream(cliente.getOutputStream());
            ObjectInputStream dados = new ObjectInputStream(cliente.getInputStream());

            num1 = dados.readDouble();
            num2 = dados.readDouble();
            opr = '+';
            total = (num1 + num2);

            resultado.writeDouble(total);
            resultado.writeChar(opr);
            resultado.flush();

            resultado.close();
            dados.close();
            System.out.println("operacao realizada");
        }

    }

}

I can execute the server code and start the connection, but after that, i get this error:

Exception in thread "main" java.net.ConnectException: Conexão recusada
    at java.net.PlainSocketImpl.socketConnect(Native Method)
    at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)
    at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
    at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
    at java.net.Socket.connect(Socket.java:579)
    at java.net.Socket.connect(Socket.java:528)
    at java.net.Socket.<init>(Socket.java:425)
    at java.net.Socket.<init>(Socket.java:208)
    at Cliente.execute(Cliente.java:16)
    at Cliente.main(Cliente.java:28)

What error this could possible be? Is it something on the Client or Server Code? Thanks for the answers.


Answer:

Socket client = new Socket("host",53300); 

Here you are connecting to port 53300.

public static void main(String[] args) throws IOException { new Servidor(12345).executa(); }

private int porta;
private List<PrintStream> clientes;

public Servidor(int porta) {
    this.porta = porta;
    this.clientes = new ArrayList<PrintStream>();
}

public void executa() throws IOException {

    double num1, num2, total = 0.0;
    char opr = '\n';

    ServerSocket servidor = new ServerSocket(this.porta)

The net effect of all this is to listen at port 12345.

The port numbers need to agree.

Question:

I got a Server with a ClientHandle which accepts requests if there are some and i'd like to send data from Java to it. (the C++ client does work without any issues)

I have read the other posts about this but they didnt help me in any way. Post1,Post2,Post3

bool ClientHandle::getData(std::shared_ptr<std::string> ptr)
{
    int n;
    ptr->clear();

    char size[4];
    n = recv(m_sock, size, sizeof(size), 0);

    //check if retval passed
    if (!checkRetValRecv(n))
        return false;

    //calc how much data
    auto msgLen = atoi(size);
    LOG_INFO << "recv a message with size: " << msgLen;

    //create buffer for the data
    auto buffer = new char[msgLen];

    //read buffer
    n = recv(m_sock, buffer, msgLen, 0);

    //check retval if it passes
    if (!checkRetValRecv(n))
        return false;
    ptr->append(buffer, msgLen);
    LOG_INFO << "Message: " << *ptr;

    delete[] buffer; 
    return true;
}
bool ClientHandle::checkRetValRecv(const int& n)
{
    if (n == SOCKET_ERROR)
    {
        size_t err = WSAGetLastError();
        if (err == WSAECONNRESET)
        {
            LOG_ERROR << "Failed to recv! Disconnecting from client: " << "Connection reset by peer.";
        }
        else
        {
            LOG_ERROR << "Disconnecting from client. WSAError: " << err;
        }
        m_connected = false;
        return false;
    }

    if (n == 0)
    {
        LOG_INFO << "Client disconnected.";
        m_connected = false;
        return false;
    }
    return true;
}

Now i would like to write a Java client for this to send data but i cant even send the size of the incoming data.

public class JClient{
    String m_host;
    int m_port;
    Socket m_sock;
    OutputStreamWriter m_out; 
    BufferedReader m_in;

    public JClient(String host, int port)
    {
        m_host = host;
        m_port = port;
    }

    private void connect() throws IOException
    {
        m_sock = new Socket(m_host, m_port);
        m_out = new OutputStreamWriter(m_sock.getOutputStream());
        m_in = new BufferedReader(new InputStreamReader(m_sock.getInputStream()));
    }

    private void close() throws IOException
    {
        m_sock.close();
    }

    public void send(String json) throws IOException {
        this.connect();
        m_out.write(json.length());
        m_out.flush();
        m_out.write(json);
        m_out.flush();

        //wait for result
        m_in.read();
        this.close();
    }
}

If i try to send Data like so:

JClient client = new JIMClient("localhost", 6060);
String toSend = "{\"hello\":\"someJson\"}";
try {
    client.send(toSend);
} catch (IOException e) {
    e.printStackTrace();
}

I do not receive anything usefull. recv a message with size: 0 , Client disconnected.

The send method does not work. I already tried other Streams and using a different encoding, which i guess is the reason for this. So the Question is how do i resolve this issue with the encoding here? I'd like to leave the C++ client as it is if possible or get it to some kind of standart.


Answer:

Java code is only sending only a single character for the length but C++ expects a 4 byte string. You might try

m_out.write(String.format("%4d%s",json.length(),json));
m_out.flush();

Question:

I am trying to use this example to send and receive the data to and from a Mainframe machine that uses HEX data to communicate. So I have the following in my configuration:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:int="http://www.springframework.org/schema/integration"
       xmlns:int-ip="http://www.springframework.org/schema/integration/ip"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
        http://www.springframework.org/schema/integration/ip http://www.springframework.org/schema/integration/ip/spring-integration-ip.xsd">

    <context:property-placeholder />

    <!-- Client side -->

    <int:gateway id="gw"
                 service-interface="org.springframework.integration.samples.tcpclientserver.SimpleGateway"
                 default-request-channel="input"/>

    <int-ip:tcp-connection-factory id="client"
                                   type="client"
                                   host="<ip>"
                                   serializer="CustomSerializerDeserializer"
                                   deserializer="CustomSerializerDeserializer"
                                   port="${availableServerSocket}"
                                   single-use="false"
                                   so-timeout="1800000"
                                   using-nio="false" />

    <bean id="CustomSerializerDeserializer" class="org.springframework.integration.samples.tcpclientserver.CustomSerializerDeserializer" />


    <int:channel id="input" />

    <int-ip:tcp-outbound-gateway id="outGateway"
                                 request-channel="input"
                                 connection-factory="client"
                                 request-timeout="1800000"
                                 reply-timeout="1800000"/>

    <!-- Server side -->

    <int-ip:tcp-connection-factory id="crLfServer"
                                   type="server"
                                   port="${availableServerSocket}"/>

    <int-ip:tcp-inbound-gateway id="gatewayCrLf"
                                connection-factory="crLfServer"
                                request-channel="serverBytes2StringChannel"
                                error-channel="errorChannel"/>

    <int:channel id="toSA" />

    <int:service-activator input-channel="toSA"
                           ref="echoService"
                           method="test"/>

    <bean id="echoService"
          class="org.springframework.integration.samples.tcpclientserver.EchoService" />

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

</beans>

And in my Serializer/Deserializer, I have the following content:

public void serialize(String input, OutputStream outputStream) throws IOException {
    outputStream.write(buildmsg(input));
    outputStream.flush();
}

public String deserialize(InputStream inputStream) throws IOException {
    String data = "";
    logger.info("inside deserialize");
    DataInputStream dis = new DataInputStream(inputStream);
    int len = dis.readInt();
    if (len > 0) {
        logger.info("len: " + decimaltohex(len));
        logger.info("data: " + data);
        byte[] b = new byte[dis.available()];
        dis.readFully(b);
        data += decimaltohex(len);
        data += byteArrayToHex(b);
    }
    logger.info("full data:" + data);
    return data;
}

public byte[] buildmsg(String body) throws UnsupportedEncodingException {
    String header = "00000000";
    String totMsg = header + body;
    header = massageheader(decimaltohex(totMsg.length() / 2));
    totMsg = header + body;
    logger.info("sending data : " + totMsg);
    return hexStringToByteArray(totMsg);
}

public String decimaltohex(int data) {
    return Integer.toHexString(data);
}

public static String massageheader(String data) {
    String str = String.format("%8s", data).replace(' ', '0').toUpperCase();
    return str;
}

public static byte[] hexStringToByteArray(String s) {
    int len = s.length();
    byte[] data = new byte[len / 2];
    for (int i = 0; i < len; i += 2) {
        data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                + Character.digit(s.charAt(i + 1), 16));
    }
    return data;
}

public static String byteArrayToHex(byte[] a) {
    StringBuilder sb = new StringBuilder(a.length * 2);
    for (byte b : a) {
        sb.append(String.format("%02x", b));
    }
    return sb.toString();
}

The input in itself is a hex string(assume so). So the message is being sent and the response also is being received properly but the output is not being passed back to the Echo Service. Why is that not happening? Is there anything wrong in my configuration?


Answer:

This is not a DEBUG log, only INFO; your log4j configuration must be wrong.

inside deserialize

This is simply the receiving thread waiting for data; it is stuck in your for loop waiting for the mainframe to close the connection - I suggest you add some debug inside the loop.

EDIT

Commons-logging is missing from your POM...

<dependency>
    <groupId>commons-logging</groupId>
    <artifactId>commons-logging</artifactId>
    <version>1.2</version>
</dependency>

or switch to log4j2

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.7</version>
</dependency>

and create a log4j2 config file.

Spring Framework 5 now uses its own implementation of commons-logging that does not support log4j 1.x.

Question:

I am building a tcp client to receive and sending messages. I followed the steps on Netty user guide and wrote a simple tcp client with a custom handler extending the ChannelInboundHandlerAdapter.

In the hander I store the ChannelHandlerContext:

 @Override
 public void channelActive (ChannelHandlerContext ctx) throws Exception {
   super.channelActive (ctx);
   this.ctx = ctx;
 }

Then I have a send method which uses the ChannelHandlerContext to send messages:

 public void sendMessage (String msg) {
  if (ctx == null) {
    return;
  }
  ChannelFuture cf = ctx.write (Unpooled.copiedBuffer (msg, CharsetUtil.UTF_8));
  ctx.flush ();
}

The other option I have found is to use the Channel object in your client class

 channel.writeAndFlush (msg);

I need to call the send method from a different thread. What is the best way to do it ?

Thanks in advance.


Answer:

Both ChannelHandlerContext and Channel are thread safe, so you can write from any thread without worrying.

If you use Channel.write(), message will have to travel through the complete pipeline. But if you use ChannelHandlerContext.write() it will only have to travel through the upstream handlers in the pipeline. Therefore writing to ChannelHandlerContext is more efficient.

And also note that most of the time its better to use writeAndFlush() instead of write().

Have a look at this presentation for more details.

Question:

I have a TCP server and client, but the client never prints the last system.out and disconnects from server socket.

My client message loop:

for (int i = 1; i <= Integer.parseInt(args[2]); i++) {
    long messageTimeStart = System.currentTimeMillis();

    outToServer.write(MSG.getBytes());
    outToServer.flush();

    Thread.sleep((long) messageTimePerSecond);
    long messageTimeEnd = System.currentTimeMillis();
    long totalMessageTime = messageTimeEnd - messageTimeStart; //Meassure total packet transfer time.
    System.out.println("Message " + i + ": '" + MSG + "' sent in: " + totalMessageTime);

    elapsedTime += totalMessageTime;
}

while (true) {
    try {
        int msgLength = serverEcho.read(buf);
        if (msgLength == -1) {
            break;
        }
        String echoMessage = new String(buf);
        System.out.println("ECHO MESSAGE: " + echoMessage);
    } catch (IOException e) {
        System.out.println("Hot damn");
    }
}

System.out.printf(args[2] + " Messages sent in: " + elapsedTime + " milliseconds.");
outToServer.close();
serverEcho.close();
socket.close();

It never gets to the four last lines for some reason. And I have no Idea why.

If it matters, here is my Server class run method:

public void run() {
    try {
        while (true) {
            try {
                inFromClient = new DataInputStream(clientSocket.getInputStream());
                outToClient = new DataOutputStream(clientSocket.getOutputStream());

                //InputStream in = clientSocket.getInputStream();
                //DataInputStream dis = new DataInputStream(in);
                int msgLength = 0;

                msgLength = inFromClient.read(dataBuffer);

                String message = new String(dataBuffer);
                System.out.println("Message recieved: " + message);

                outToClient.write(message.getBytes(), 0, msgLength);
                outToClient.flush();
                System.out.println("Echo message sent: " + message);

            } catch (SocketException e) {
                System.out.println("Connection terminated by client.");
                break;
            }
        }

        clientSocket.close();
    } catch (IOException e) {
        System.out.println("Could not listen on port: " + clientSocket.getLocalPort());
        System.out.println("Client thread terminated.");
    }
}

Answer:

You already know the amount of data that the server will return to you since the server is returning the same information that the client is sending to him.

Therefore, you could try this approach:

Server

@Override
public void run() {
    ServerSocket serverSocket = null;
    Socket clientSocket = null;
    DataInputStream inFromClient = null;
    DataOutputStream outToClient = null;

    try {
        serverSocket = new ServerSocket(4321);
    } catch (IOException ioe) {
        System.out.println("Could not listen on port 4321. Cause: " + ioe);
        System.exit(-1);
    }

    System.out.println("#Server#listening on port 4321!");

    try {
        clientSocket = serverSocket.accept();
    } catch (IOException ioe) {
        System.out.println("Accept failed on port: 4321. Cause: " + ioe);
        System.exit(-1);
    }

    System.out.println("#Server#accepting connections on port 4321!");

    try {
        inFromClient = new DataInputStream(clientSocket.getInputStream());
        outToClient = new DataOutputStream(clientSocket.getOutputStream());
    } catch (IOException ioe) {
        System.out.println("Input and output streams creation failed. Cause: " + ioe);
        System.exit(-1);
    }

    System.out.println("#Server#created input and output streams!");

    byte[] dataBuffer = new byte[1024];

    try {
        while (true) {
            try {
                int msgLength = 0;

                msgLength = inFromClient.read(dataBuffer);

                String message = new String(dataBuffer);
                System.out.println("Message recieved: " + message);

                outToClient.write(message.getBytes(), 0, msgLength);
                outToClient.flush();
                System.out.println("Echo message sent: " + message);

            } catch (SocketException e) {
                System.out.println("Connection terminated by client.");
                break;
            }
        }

        clientSocket.close();
    } catch (IOException e) {
        System.out.println("Could not listen on port: " + clientSocket.getLocalPort());
        System.out.println("Client thread terminated.");
    } finally {
        try {
            outToClient.close();
            inFromClient.close();
            clientSocket.close();
            serverSocket.close();
        } catch (IOException ioe) {
            System.out.println("Unable to close streams and sockets. Cause: " + ioe);
            System.exit(-1);
        }
    }
}

Client

@Override
public void run() {
    String MSG = "Hello from client, mister server!";
    Socket socket = null;
    DataOutputStream outToServer = null;
    DataInputStream inFromServer = null;

    try {
        socket = new Socket("localhost", 4321);
    } catch (IOException ioe) {
        System.out.println("Unable to connect with host: localhost. Cause: " + ioe);
        System.exit(1);
    }

    System.out.println("@Client@connected with server localhost on port 4321!");

    try {
        outToServer = new DataOutputStream(socket.getOutputStream());
        inFromServer = new DataInputStream(socket.getInputStream());
    } catch (IOException ioe) {
        System.out.println("Input and output streams creation failed. Cause: " + ioe);
        System.exit(-1);
    }

    System.out.println("@Client@created input and output streams!");

    long messageTimePerSecond = 3000;
    long elapsedTime = 0;

    try {
        for (int it = 0; it < 5; it++) {
            long messageTimeStart = System.currentTimeMillis();

            outToServer.write(MSG.getBytes());
            outToServer.flush();

            Thread.sleep((long) messageTimePerSecond);
            long messageTimeEnd = System.currentTimeMillis();
            // Measure total packet transfer time.
            long totalMessageTime = messageTimeEnd - messageTimeStart;
            System.out.println("Message " + it + ": '" + MSG + "' sent in: " + totalMessageTime);

            elapsedTime += totalMessageTime;
        }

        byte[] dataBuffer = new byte[1024];
        String echoMessage = "";
        int msgLength = 0;
        int totalData = MSG.length();
        boolean finish = false;

        while (!finish) {
            try {
                msgLength = inFromServer.read(dataBuffer);
                echoMessage += new String(dataBuffer, 0, msgLength);

                if (echoMessage.length() == totalData) {
                    finish = true;
                }

                System.out.println("ECHO MESSAGE: " + echoMessage);
            } catch (IOException e) {
                System.out.println("Hot damn");
            }
        }
    } catch (IOException | InterruptedException e) {
        System.out.println("Something bad happened. Cause: " + e);
        System.exit(-1);
    } finally {
        System.out.printf("5 Messages sent in: " + elapsedTime + " milliseconds.");
        try {
            inFromServer.close();
            outToServer.close();
            socket.close();
        } catch (IOException ioe) {
            System.out.println("Unable to close streams and socket. Cause: " + ioe);
            System.exit(-1);
        }
    }
}

Both Server and Client implement Runnable and your main class can be like this:

public class ClientServerMain {

    public static void main(String[] args) {
        Thread server = new Thread(new Server());
        server.start();
        Thread client = new Thread(new Client());
        client.start();
    }
}

Question:

code to send data to server

BufferedReader keyRead = new BufferedReader(new InputStreamReader(System.in));
OutputStream ostream = sock.getOutputStream(); 
 PrintWriter pwrite = new PrintWriter(ostream, true);
 // receiving from server ( receiveRead  object)
 InputStream istream = sock.getInputStream();
 BufferedReader receiveRead = new BufferedReader(new InputStreamReader(istream));

 String receiveMessage, sendMessage;               
 while(true)
 {
    sendMessage = keyRead.readLine();  // keyboard reading
    String enc = crypt.encrypt(sendMessage, serverPublicKey);
    System.out.println("sending to server: "+enc);
    pwrite.println(enc);       // sending to server
    pwrite.flush();                    // flush the data
    if((receiveMessage = receiveRead.readLine()) != null) //receive from server
    {
        //System.out.println(crypt.decrypt(receiveMessage, clientPrivateKey)); // displaying at DOS prompt
        System.out.println(receiveMessage);
    }         
  }

output after encryption looks like below on console

sending to server: YRJ7ZNgqSQ56nGc8ff7ktoybYEohQJS2R+Vh3YN1YfHipUS64MyFrrYAzL4CiTPv2WF7zvaJst1A
qsiPsv3/1Q==

code to receive on server

      BufferedReader keyRead = new BufferedReader(new InputStreamReader(System.in));
      // sending to client (pwrite object)
      OutputStream ostream = sock.getOutputStream(); 
      PrintWriter pwrite = new PrintWriter(ostream, true);

      // receiving from server ( receiveRead  object)
      InputStream istream = sock.getInputStream();
      BufferedReader receiveRead = new BufferedReader(new InputStreamReader(istream));

      String receiveMessage, sendMessage;               
      while(true)
      {
        if((receiveMessage = receiveRead.readLine()) != null)  
        {
           //System.out.println(crypt.decrypt(receiveMessage, serverPrivateKey));
            System.out.println(receiveMessage);
        }         
        sendMessage = keyRead.readLine(); 
        String enc = crypt.encrypt(sendMessage, clientPublicKey);
        System.out.println("sending to clinet: "+enc);
        pwrite.println(enc);             
        pwrite.flush();
      }  

but data is received like

YRJ7ZNgqSQ56nGc8ff7ktoybYEohQJS2R+Vh3YN1YfHipUS64MyFrrYAzL4CiTPv2WF7zvaJst1A

rest of

qsiPsv3/1Q==

is received when i send something from server to client, please help me locate the problem, due to truncated data the decryption fails


Answer:

You do not only encrypt the input but you also Base64 encode the encrypted bytes. Your Base64 encoder inserts line breaks every 76 characters, which is the standard for Base64 transfer encoding for MIME (RFC 2045). That is why on the server side your readLine() only reads in the first 76 characters.

You need to configure your Base64 encoder to not add line breaks.

Question:

I'm trying to create a simple Java Chatting application, but have ran into some problems.

Here is my code below for both Classes:

Serveur.java :

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

class Serveur{

    private String msgClient, msgServeur;
    private ServerSocket serverSocket;
    private DataOutputStream out;
    private Socket socket;
    private int port;
    private BufferedReader in;

    public Serveur() throws IOException{
        System.out.println("Serveur OK...");
        this.port = 21;
        this.serverSocket = new ServerSocket(this.port);
        while(true){
            this.socket = serverSocket.accept();
            this.in = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
            this.out = new DataOutputStream(this.socket.getOutputStream());
            this.msgClient = this.in.readLine();
            System.out.println("Received: " + this.msgClient);
            this.msgServeur = this.msgClient.toUpperCase() + '\n';
            send(this.msgServeur);
        }
    }

    public void send(String msg) throws IOException{
        this.out.writeBytes(msg);
    }

    public static void main(String argv[]) throws Exception {
        Serveur serveur = new Serveur();
    }
}

Client.java :

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

class Client{

    private String sentence;
    private String modifiedSentence;
    private int port;
    private BufferedReader inUser;
    private BufferedReader inServeur;
    private Socket socket;
    private DataOutputStream out;

    public Client() throws UnknownHostException, IOException{
        this.sentence = "";
        this.modifiedSentence = "";
        this.port = 21;
        this.inUser = new BufferedReader(new InputStreamReader(System.in));
        this.socket = new Socket("localhost", this.port);
        this.out = new DataOutputStream(this.socket.getOutputStream());
        this.inServeur = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
        sentence = this.inUser.readLine();
        this.out.writeBytes(sentence + '\n');
        modifiedSentence = this.inServeur.readLine();
        System.out.println("FROM SERVER: " + modifiedSentence);
        this.socket.close();
    }

    public static void main(String argv[]) throws Exception{
        Client client = new Client();
    }
}

I have 2 problems : - The client sends a message, and the server returns the same message in uppercase. How can I allow the client to send messages without instantly closing it's socket connection? - The server looks OK, but when I have multiple clients, will anything change having more than one connected client? How could I broadcast messages, and messages to specific clients?


Answer:

The client send a message, the server return the same message in uppercase. How can i allow the client to send infinite message and don't destroy itself after sending the first message ?

just have the client use a loop

boolean quit = false;
while (!quit) {
    sentence = this.inUser.readLine();
    quit = sentence.trim().equals("quit");
    this.out.writeBytes(sentence + '\n');
    modifiedSentence = this.inServeur.readLine();
    System.out.println("FROM SERVER: " + modifiedSentence);
}
this.socket.close();

The server looks ok, but when i will have multiple client, will it make difference between multiple client ? How can i broadcast ? send message to focused client ?

Yes, this server blocks reading the first client so any other client would have to wait. You probably want to put the code for blocking on each client in a separate thread or submit it to an ExecutiveService. And all of the variables that are specific to a client can not be in the single server class since you need one set for each client.

while (true) {
    final Socket socket = serverSocket.accept();
    new Thread(() -> {
        try {
            BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            DataOutputStream out = new DataOutputStream(socket.getOutputStream());
            boolean quit = false;
            while (!quit) {
                String msgClient = in.readLine();
                quit = msgClient.trim().equals("quit");
                System.out.println("Received: " + msgClient);
                String msgServeur = msgClient.toUpperCase() + '\n';
                out.writeBytes(msgServeur);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }).start();
}

Question:

I want to check if any of my client has disconnected.From my research, a possible way is that I could keep writing messages to the clients. If the client fails to receive the message, it means it has disconnected. I send a message "Checking Connection: Client" + clientNo" to the respective clients.

I connect clientNo 1 to the server and it receive

Client1

"Checking Connection: Client1" <-- output every 10secs
"Checking Connection: Client1" <-- output every 10secs
"Checking Connection: Client1" <-- output every 10secs

but when I connect another client to the server, my clientNo1 stops receiving the message from the server and my clientNo2 will now receive

Client2

"Checking Connection: Client2"  <-- output every 10secs    
"Checking Connection: Client1"  <-- output every 10secs
"Checking Connection: Client2"  <-- output every 10secs    
"Checking Connection: Client1"  <-- output every 10secs

Desired output

Client1

"Checking Connection: Client1" <-- output every 10secs 
"Checking Connection: Client1" <-- output every 10secs 
"Checking Connection: Client1" <-- output every 10secs 

Client2

"Checking Connection: Client2" <-- output every 10secs 
"Checking Connection: Client2" <-- output every 10secs 
"Checking Connection: Client2" <-- output every 10secs 

Please help. Thank you.

Server.java

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    private int portNo = 0;
    private ObjectOutputStream out;
    private ObjectInputStream in;
    private boolean clientAlive = true;

    @SuppressWarnings("resource")
    public Server(int portNo) {
        Socket socket = null;
        this.portNo = portNo;
        ServerSocket sSocket = null;
        int clientNo = 1;
        try {
            sSocket = new ServerSocket(this.portNo);
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        while(true) {
            try {
                socket = sSocket.accept();
            } catch (IOException e) {
                e.printStackTrace();
            }
             new Thread(new acceptClient(socket,clientNo)).start();
             clientNo += 1;
        }
    }

    class acceptClient implements Runnable {
        Socket socket;
        int clientNo = 1;
        String writeToClient = "";

        public acceptClient(Socket socket, int clientNo) {
            this.socket = socket;
            this.clientNo = clientNo;
        }

        public void run() {
            try {
                out = new ObjectOutputStream(socket.getOutputStream());
                in = new ObjectInputStream(socket.getInputStream());
            } catch(IOException exception) {
                System.out.println("Error: " + exception);
            }

            while(clientAlive) {
                writeToClient = "Checking Connection: Client" + clientNo;
                sendData(out, writeToClient.getBytes());

                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                if(!clientAlive) {
                    break;
                }

            }
        }
    }

    public synchronized void sendData(ObjectOutputStream os, byte[] byteData) {
        if (byteData == null) {
            return;
        }
        try {
            os.write(byteData);
            os.flush();
        }
        catch (Exception e) {
            System.out.println("Client Disconnected");
            clientAlive = false;
        }
    }

    public static void main(String[] args) {
        System.out.println("Server started");
        new Server(5550);
    }
}

Client.java

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

import javax.swing.JDialog;
import javax.swing.JOptionPane;


public class Client {
    public static void main(String args[]) {
        clientConnection();
    }

    public static void clientConnection() {
        Socket clientSocket = null;
        ObjectOutputStream out = null;
        ObjectInputStream in = null;

        try {
            clientSocket = new Socket("localhost", 5550);
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } 

        try {
            out = new ObjectOutputStream(clientSocket.getOutputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }   

        try {
            in = new ObjectInputStream(clientSocket.getInputStream());

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

        byte[] byteData = null;
        while(true) {
            try {
                byteData = receive(in);
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println(new String(byteData));
        }
    }

    public static byte[] receive(ObjectInputStream is) throws Exception {
        try {
            byte[] inputData = new byte[1024];
            is.read(inputData);
            return inputData;
        }
        catch (Exception exception) {
            throw exception;
        }
    }
}

Answer:

Your ObjectInputStream and ObjectOutputStream are part of the Server class. Make them members of acceptClient class and it should be OK.

Question:

I'm building a program that will interact between a client and server:

client sends an object, server manipulates it and sends back to client.

The ip that delivered through command line is 121.0.0.1 (same computer).

However when I press the "go" button, it seems like there is a deadlock that I can't spot.

What am I doing wrong?

All my classes are here:

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.Socket;

import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;

    @SuppressWarnings("serial")
    public class ClientPanel extends JPanel {

        JTextArea textArea;
        JTextField textField;
        JButton goButton;

        InetAddress ip;

        public ClientPanel(InetAddress ip) {
            this.ip=ip;

            setLayout(new BorderLayout());
            setSize(200, 200);

            textArea = new JTextArea();
            textArea.setSize(50, 50);
            add(textArea, BorderLayout.NORTH);

            textField = new JTextField();
            textField.setSize(100, 100);
            add(textField, BorderLayout.CENTER);


            goButton = new JButton("Go");
            add(goButton, BorderLayout.PAGE_END);
            goButton.addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    // TODO Auto-generated method stub
                    IntData intData=new IntData(Integer.parseInt(textField.getText()));
                    textArea.append("Go button pressed. Text in field: " + textField.getText() + "\n "
                            + "sending to server:"+intData);
                    Socket socket;
                    try {
                        socket = new Socket(ip,4444);
                        new GetBinaryThread(socket, intData);
                    } catch (IOException e1) {e1.printStackTrace();}


                }
            });

            repaint();
        }


        private class GetBinaryThread extends Thread {

            private Socket socket;
            private ObjectOutputStream out;
            private ObjectInputStream in;
            private IntData dataToSend;

            public GetBinaryThread(Socket socket, IntData data) {
                this.socket = socket;
                try {
                    out = new ObjectOutputStream(socket.getOutputStream());
                    out.flush();
                    in = new ObjectInputStream(socket.getInputStream());

                    dataToSend = data;
                } catch (IOException e) {
                    e.printStackTrace();
                }


            }

            public void run() {
                try {

                    out.writeObject(dataToSend);
                    Object recievedObject = in.readObject();

                    // TODO show the object in text area
                    ClientPanel.this.textArea.append(", recieved" + ((IntData)recievedObject).getBinary());
                    out.close();
                    in.close();
                    socket.close();

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

    }

import java.net.InetAddress;
import java.net.UnknownHostException;

import javax.swing.JFrame;

public class LaunchClient {
    static final int FRAME_WIDTH = 500, FRAME_HEIGHT = 500;

public static void main(String[] args) {

        InetAddress ip = null;
        if (args.length==0){
            System.out.println("No args so no IP!");
        }

        try {
            ip = InetAddress.getByName(args[0]);
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        System.out.println(ip);
        JFrame frame = new JFrame();
        frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);

        frame.add(new ClientPanel(ip));
        frame.setVisible(true);


    }


}

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class BinaryServer {

    public static void main(String[] args) {

        Socket socket;
        ServerSocket serverSocket;
        try {
            serverSocket = new ServerSocket(4444);
            boolean listening = true;
            System.out.println("server ready...");

            while (listening) {
                socket = serverSocket.accept();
                System.out.println("got socket");
                new BinaryServerThread(socket).start();

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

    }

}

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;

public class BinaryServerThread extends Thread {
    Socket socket = null;
    ObjectInputStream in;
    ObjectOutputStream out;

    public BinaryServerThread(Socket socket) {
        this.socket = socket;
        try {
             in = new ObjectInputStream(socket.getInputStream());
             out = new ObjectOutputStream(socket.getOutputStream());

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

    public void run() {
        IntData dataFromClient;
        try {
            dataFromClient = ((IntData) in.readObject());
            dataFromClient.generateBinary();
            System.out.println("got data: "+dataFromClient);
            out.writeObject(dataFromClient);

            in.close();
            out.close();
            socket.close();
        } catch (ClassNotFoundException | IOException e) {
            e.printStackTrace();
        }


    }

}

public class IntData {
    private Integer integer;
    private String binary = "Not set";

    public IntData(int x){
        integer=x;
    }
    public void generateBinary() {
        binary = Integer.toBinaryString(integer);
    }

    public int getInteger() {
        return integer;
    }

    public void setInteger(int integer) {
        this.integer = integer;
    }

    public String getBinary() {
        return binary;
    }

    public void setBinary(String binary) {
        this.binary = binary;
    }
    public String toString(){
        return integer.toString();
    }

}

Answer:

If I understand your question, the issue is the IP Address you supply on the command line

121.0.0.1

is not a loopback address. You need

127.0.0.1

or

localhost

Question:

There is an echo server and an echo client. When I use kill -9 <client_pid> to kill client process, the channelInactive on server is called.

The client is killed by SIGKILL, so it should have no time to actively close this socket. As a result, the channelInactive on server should not be trigged, which did happen.

Why channelInactive on server is called when the client is killed by SIGKILL?

The EchoServer class

public class EchoServer {
  private final int port;

  public EchoServer(int port) {
    this.port = port;
  }

  public static void main(String[] args) throws InterruptedException {
    int port = 9001;
    new EchoServer(port).start();
  }

  public void start() throws InterruptedException {
    EventLoopGroup group = new NioEventLoopGroup();

    try {
      ServerBootstrap bootstrap = new ServerBootstrap();
      bootstrap
          .group(group)
          .channel(NioServerSocketChannel.class)
          .childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel ch) throws Exception {
              ch.pipeline()
                .addLast(new ChannelInboundHandlerAdapter() {
                  @Override
                  public void channelInactive(ChannelHandlerContext ctx) throws Exception {
                    System.out.println("channelInactive()");
                  }
                });
            }
          });

      ChannelFuture future = bootstrap.bind(new InetSocketAddress(port)).sync();
      future.channel().closeFuture().sync();
    } finally {
      group.shutdownGracefully().sync();
    }
  }
}

The EchoClient class

public class EchoClient {
  private final String host;
  private final int port;

  public EchoClient(String host, int port) {
    this.host = host;
    this.port = port;
  }

  public void start() throws InterruptedException {
    EventLoopGroup group = new NioEventLoopGroup();
    try {
      Bootstrap bootstrap = new Bootstrap();
      bootstrap
          .group(group)
          .channel(NioSocketChannel.class)
          .handler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel ch) throws Exception {
            }
          });

      ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port)).sync();
      future.channel().closeFuture().sync();
    } finally {
      group.shutdownGracefully().sync();
    }
  }

  public static void main(String[] args) throws InterruptedException {
    new EchoClient("localhost", 9001).start();
  }
}

Answer:

The client is killed by SIGKILL, so it should have no time to actively close this socket.

The client application does not actively close the socket. The clients OS kernel implicitly closes a socket if no local application is having it open anymore.

Question:

This is code provided to me for a class. I am trying trying to fix a connection problem between the client and server. Even when both are started they do not connect.

This is for a Java based game of Battleship that will allow two users on separate devices to play one another. I'm not sure why the two do not connect and even the debugger has not been much help in directing me to the problem.

public class GameClient
{
    private Socket clientSocket;
    private PrintWriter out;
    private BufferedReader in;

    public void openConnection(String ip, int port)
    {
        try
        {
            clientSocket = new Socket(ip, port);
            out = new PrintWriter(clientSocket.getOutputStream(), true);
            in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));

        }
        catch (Exception e)
        {
            System.out.println("Error opening client socket");
        }
    }

    public String sendMessage(String msg)
    {
        String resp = "";
        try
        {
            out.println(msg);
            resp = in.readLine();
        }
        catch (Exception e)
        {
            System.out.println("Error sending message from Client");
        }

        return resp;
    }

    public void stop()
    {
        try
        {
            in.close();
            out.close();
            clientSocket.close();
        }
        catch (Exception e)
        {
            System.out.println("Error stopping client");
        }
    }

    public static void main(String[] args)
    {
        GameClient client = new GameClient();

        client.openConnection("10.7.232.200", 3333);
        String response = client.sendMessage("1,2");
        System.out.println(response);
        client.stop();
    }
}

public class GameServer
{
    private ServerSocket serverSocket;
    private Socket clientSocket;
    private PrintWriter out;
    private BufferedReader in;

    public void start(int port)
    {
        try
        {
            serverSocket = new ServerSocket(port);
            clientSocket = serverSocket.accept();
            out = new PrintWriter(clientSocket.getOutputStream(), true);
            in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));

            String move = in.readLine();

            System.out.println(move);

            out.println("6,1");

        }
        catch (Exception e)
        {
            System.out.println("Socket opening error");
        }

    }

    public void stop()
    {
        try
        {
            in.close();
            out.close();
            clientSocket.close();
            serverSocket.close();
        }
        catch (Exception e)
        {
            System.out.println("Error closing sockets");
        }
    }


    public static void main(String [] args)
    {
        GameServer server = new GameServer();
        server.start(3333);
        server.stop();
    }
}

public class PlayBattleship
{
    public static void main(String[] args)
    {
        GameClient client = new GameClient();

        client.openConnection("10.7.232.200", 3333);

        //System.out.println(response);


        BattleshipGame game = new BattleshipGame();

        while (!game.checkEndgame())
        {
            game.getGuess(client);
        }

        client.stop();
    }
}

The client and server should connect and stay connected till the game has reached completion EDIT: I have thoroughly read the API documentation but still cannot understand the problem.


Answer:

The Server in your code isn't waiting for the incoming requests, it only serves a single incoming request and then kills itself due to the nature of the main method which starts it.

You need to have the server wait for the requests and do not die. Check the code snippet below to understand the logic.

Plus, always try to throw the exceptions if you can't do anything meaningful with it within the method it is caught in. In your code the main method of the server will anyway execute even if there is an exception caught in the start method

public class GameServer {
    private ServerSocket serverSocket;
    private Socket clientSocket;
    private PrintWriter out;
    private BufferedReader in;

    public ServerSocket start(int port) throws IOException {
        serverSocket = new ServerSocket(port);
        return serverSocket;
    }

    public void stop() throws IOException {
        in.close();
        out.close();
        clientSocket.close();
        serverSocket.close();
    }

    // This method accepts and serves the incoming requests
    public void acceptConnection(ServerSocket serverSocket) throws IOException {
        clientSocket = serverSocket.accept();
        out = new PrintWriter(clientSocket.getOutputStream(), true);
        in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));

        String move = in.readLine();

        System.out.println(move);

        out.println("6,1");
    }

    public static void main(String[] args) throws IOException {
        GameServer server = new GameServer();
        ServerSocket serverSocket = server.start(3333);
        System.out.println("Server Started");

        // The effective change you need to make
        // Loop through the incoming requests
        while(true) {
            server.acceptConnection(serverSocket);
        }
    }
}


public class GameClient {
    private Socket clientSocket;
    private PrintWriter out;
    private BufferedReader in;

    public void openConnection(String ip, int port) throws IOException {
        clientSocket = new Socket(ip, port);
        out = new PrintWriter(clientSocket.getOutputStream(), true);
        in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
    }

    public String sendMessage(String msg) throws IOException {
        String resp = "";
        out.println(msg);
        resp = in.readLine();

        return resp;
    }

    public void stop() throws IOException {
        in.close();
        out.close();
        clientSocket.close();
    }

    public static void main(String[] args) throws IOException {
        GameClient client = new GameClient();

        client.openConnection("10.7.232.200", 3333);
        String response = client.sendMessage("1,2");
        System.out.println(response);
        client.stop();
    }
}

Question:

I am designing a Netty based solution to transfer a file from Server to the Client over TCP. The client specifies the location of the file and then the server sends the file to the client.

Currently, the solution works fine for files with small size (< 2MB of data).

If the file to be sent is larger than ~5MB only partial data is sent and this varies (every time not the same amount of data is sent). Also, it is seen from the log that the Server has sent the complete amount of data (file).

The issue is the client is not receiving complete data sent by the server. What is wrong in my below code? or Can someone point me to right direction.

Below is my client, server and their handlers: (For brevity I have listed only the methods that is of importance)

Client:

 public class FileClient {

        private final static int PORT = 8992;
        private final static String HOST = "127.0.0.1";

        public class ClientChannelInitializer extends ChannelInitializer<SocketChannel> {

            private SslContext sslContext = null;
            private String srcFile = "";
            private String destFile = "";

            public ClientChannelInitializer(String srcFile, String destFile, SslContext sslCtx) {
                this.sslContext = sslCtx;
                this.srcFile = srcFile;
                this.destFile = destFile;
            }

            @Override
            protected void initChannel(SocketChannel socketChannel) throws Exception {
                ChannelPipeline pipeline = socketChannel.pipeline();
                pipeline.addLast(sslContext.newHandler(socketChannel.alloc(), HOST, PORT));
                pipeline.addLast("clientHandler", new FileClientHandler(srcFile, destFile));
            }

        }

        private void startUp(String srcFile, String destFile) throws Exception {
            SslContext sslCtx = SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build();
            EventLoopGroup workerGroup = new NioEventLoopGroup();

                Bootstrap clientBootstrap = new Bootstrap();
                clientBootstrap.group(workerGroup);
                clientBootstrap.channel(NioSocketChannel.class);
                clientBootstrap.option(ChannelOption.TCP_NODELAY, true);
                clientBootstrap.handler(new LoggingHandler(LogLevel.INFO));
                clientBootstrap.handler(new ClientChannelInitializer(srcFile, destFile, sslCtx));

Channel channel = clientBootstrap.connect(new InetSocketAddress(HOST, PORT)).sync().channel();
                channel.closeFuture().sync();
            } 
        }

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

            String src = "/Users/home/src/test.mp4";
            String dest = "/Users/home/dest/test.mp4";
            new FileClient().startUp(src, dest);
        }

    }

ClientHandler:

public class FileClientHandler extends SimpleChannelInboundHandler<ByteBuf> {


    private final String sourceFileName;
    private OutputStream outputStream;
    private Path destFilePath;
    private byte[] buffer = new byte[0];



    public FileClientHandler(String SrcFileName, String destFileName) {
        this.sourceFileName = SrcFileName;
        this.destFilePath = Paths.get(destFileName);
        System.out.println("DestFilePath-" + destFilePath);
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        ctx.writeAndFlush(ToByteBuff(this.sourceFileName));
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, ByteBuf byteBuff) throws Exception {
        if (this.outputStream == null) {
            Files.createDirectories(this.destFilePath.getParent());
            if (Files.exists(this.destFilePath)) {
                Files.delete(this.destFilePath);
            }
            this.outputStream = Files.newOutputStream(this.destFilePath, StandardOpenOption.CREATE,
                    StandardOpenOption.APPEND);
        }

        int size = byteBuff.readableBytes();
        if (size > this.buffer.length) {
            this.buffer = new byte[size];
        }
        byteBuff.readBytes(this.buffer, 0, size);
        this.outputStream.write(this.buffer, 0, size);

    }   

FileServer:

public class FileServer {
    private final int PORT = 8992;

    public void run() throws Exception {
        SelfSignedCertificate ssc = new SelfSignedCertificate();
        final SslContext sslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()).build();
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).option(ChannelOption.SO_BACKLOG, 100)
                    .handler(new LoggingHandler(LogLevel.INFO)).childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel ch) throws Exception {
                            ChannelPipeline pipeline = ch.pipeline();
                            pipeline.addLast(sslCtx.newHandler(ch.alloc()));

                            pipeline.addLast(new ChunkedWriteHandler());
                            pipeline.addLast(new FilServerFileHandler());
                        }
                    });
            ChannelFuture f = b.bind(PORT).sync();

            f.channel().closeFuture().sync();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

    public static void main(String[] args) throws Exception {
        new FileServer().run();
    }
}

FileServerHandler:

public class FilServerFileHandler extends SimpleChannelInboundHandler<ByteBuf> {

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, ByteBuf buff) throws Exception {
        String filePathStr = byteBuf.toString(CharsetUtil.UTF_8);

        File file = new File(filePathStr);
        RandomAccessFile raf = null;
        ChannelFuture sendFileFuture;
        try {
            raf = new RandomAccessFile(file, "r");

            sendFileFuture = ctx.writeAndFlush(new ChunkedNioFile(raf.getChannel()),
                    ctx.newProgressivePromise());

            sendFileFuture.addListener(new ChannelProgressiveFutureListener() {
                public void operationComplete(ChannelProgressiveFuture future) throws Exception {
                    System.err.println("Transfer complete.");
                }

                public void operationProgressed(ChannelProgressiveFuture future, long progress, long total)
                        throws Exception {
                    if (total < 0) { // total unknown
                        System.err.println("Transfer progress: " + progress);
                    } else {
                        System.err.println("Transfer progress: " + progress + " / " + total);
                    }
                }
            });

        } catch (FileNotFoundException fnfe) {
        } finally {
            if (raf != null)
                raf.close();
        }
    }

I have checked SO Q1 and SO Q2


Answer:

Fixed your problem by a little tweak in FilServerFileHandler:

public class FileServerHandler extends SimpleChannelInboundHandler<ByteBuf> {
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, ByteBuf buff) throws Exception {
        String filePathStr = buff.toString(CharsetUtil.UTF_8);

        File file = new File(filePathStr);
        RandomAccessFile raf = new RandomAccessFile(file, "r");
        ChannelFuture sendFileFuture;
        try {
            sendFileFuture = ctx.writeAndFlush(new ChunkedNioFile(raf.getChannel()), ctx.newProgressivePromise());
            sendFileFuture.addListener(new ChannelProgressiveFutureListener() {
                public void operationComplete(ChannelProgressiveFuture future) throws Exception {
                    System.err.println("Transfer complete.");
                    if (raf != null) {
                        raf.close();
                    }
                }
                public void operationProgressed(ChannelProgressiveFuture future, long progress, long total)
                        throws Exception {
                    if (total < 0) { // total unknown
                        System.err.println("Transfer progress: " + progress);
                    } else {
                        System.err.println("Transfer progress: " + progress + " / " + total);
                    }
                }
            });
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
}

I moved raf.close() into operationComplete method.

The partial transportation is caused by the closing of raf during write operation. Note that ctx.writeAndFlush is an async call, so the raf.close() in finally block might be triggered before the write operation complete, especially when the size of the file is large enough.

Question:

I have following code for server and client. Client is able to send data to Server successfully but when Client tries to read data from server, code keeps on running without any output.

Server:

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

    ServerSocket s = new ServerSocket(9898);

    while(true) {

        Socket recv = s.accept();

        InputStream inp = recv.getInputStream();
        OutputStream out = recv.getOutputStream();

        String data = null;
        BufferedReader in = new BufferedReader(new InputStreamReader(inp));
        while ( (data = in.readLine()) != null ) {
            System.out.println("\r" + data);
        }

        out.write("sampleSendToClient".getBytes());
    }

}

Client:

public static void main(String[] args) throws Exception{
    Socket clientSocket = new Socket("localhost", 9898);
    OutputStream out = clientSocket.getOutputStream();
    InputStream inp = clientSocket.getInputStream();

    out.write("sampleSendToServer".getBytes());

    String data = null;
    //if I dont write next 4 lines then client exits gracefully 
    //but now it is stuck infinitely
    BufferedReader in = new BufferedReader(new InputStreamReader(inp));
    while ( (data = in.readLine()) != null ) {
        System.out.println("\r" + data);
    }

    clientSocket.close();
}

I am unable to understand what is wrong in above code.


Answer:

Quick but painless your server writes directly on the output stream by calling OutputStream#write(byte[] data) but your clients reads with a BufferedReader and BufferedReader#readLine() is a blocking I/O operation which will suspend his thread until a \n or \r character arrives on the InputStream (or the stream is closed in which case the method gets intererrupted an null is returned).

The String your server is sending does not end with \n or \r so the data may be sent already and linger in the buffere of the client's BufferedReader but without either of those terminating characters readLine() will never return.

Simply change

out.write("sampleSendToClient".getBytes());

to

out.write("sampleSendToClient\n".getBytes());

should do the trick.

Update:
while ( (data = in.readLine()) != null ) {
        System.out.println(data);
    }

This while loop will only exit if readLine() returns null this will only be the case if the stream is clsoed. However since you can't close the streams without losing the connection you will have to find another way to terminate the loop because now it will run forever.

Even after adding the \n your server wouldn't respond because he wil be infinitely loop at that point.


On a side note: For each new connection you're overwriting the previous socket without closing it's resources (primarly focused on the data stream and sockets themselves) and therefore creating ressource leaks. Consider to close every object when they are no longer needed.

Question:

I am trying to implement a TCP Server and Client in Java. The Client should send a message to the Server and the Server should send the same message back to the Client. I get the connection between both, but there is not any message. I have already searched a lot in the internet and my code is so simliar to other code, but my solution is still not working. I am pretty new to this topic so I am happy about every advice. Here is my Client code:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;

public class Client 
{
    public static void main(String[] args) 
    {
    final int PORT = 5000;
    Socket socket = null;
    try
    {
        socket = new Socket("localhost", PORT);
        OutputStream os = socket.getOutputStream();
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
        String message = "Hello World";
        bw.write(message);
        bw.flush();

        InputStream is = socket.getInputStream();
        BufferedReader br = new BufferedReader(new InputStreamReader(is));
        String echo = br.readLine();
        System.out.println(echo);
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }
    finally
    {
        try
        {
        socket.close();
        } catch (IOException e)
        {
        e.printStackTrace();
        }
    }
    }
}

Server code:

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

public class Server
{
    public static void main(String[] args)
    {
        final int PORT = 5000;
        ServerSocket serverSocket = null;
        Socket socket = null;
        try
        {
            serverSocket = new ServerSocket(PORT);
            socket = serverSocket.accept();
            InputStream is = socket.getInputStream();
            BufferedReader br = new BufferedReader(new 
            InputStreamReader(is));
            String message = br.readLine();
            System.out.println(message);
            OutputStream os = socket.getOutputStream();
            BufferedWriter bw = new BufferedWriter(new 
            OutputStreamWriter(os));
            bw.write("ECHO: " + message);
            bw.flush();
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        finally
        {
            try
            {
                serverSocket.close();
            } catch (IOException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }



    }
}

Answer:

It's because you're using readLine() to receive the message and you never terminate the message with an end of line.

Add a new line to your messsage and the readLine() method will see it and return a value to you. String message = "Hello World\n";

Note you're going to have the same problem on the return path, because you're also using readLine() on the client. Add a new line to the server's reply: bw.write("ECHO: " + message + '\n');

Question:

I followed this example for setting up a TCP Client in Spring. Below is my tcpClientServerDemo-context.xml file where the transformer lies. Can someone help me remove the transformer and send the data as it is without any modifications? If I try to remove the line reply-channel='clientBytes2StringChannel' or even make it null, I get exceptions when building the project.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:int="http://www.springframework.org/schema/integration"
       xmlns:int-ip="http://www.springframework.org/schema/integration/ip"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
        http://www.springframework.org/schema/integration/ip http://www.springframework.org/schema/integration/ip/spring-integration-ip.xsd">

    <context:property-placeholder />

    <!-- Client side -->

    <int:gateway id="gw"
                 service-interface="hello.SimpleGateway"
                 default-request-channel="input"/>

    <int-ip:tcp-connection-factory id="client"
                                   type="client"
                                   host="192.86.33.61"
                                   serializer="CustomSerializerDeserializer"
                                   deserializer="CustomSerializerDeserializer"
                                   port="${availableServerSocket}"
                                   single-use="true"
                                   so-timeout="10000"/>

    <bean id="CustomSerializerDeserializer" class="hello.CustomSerializerDeserializer" />

    <int:channel id="input" />

    <int-ip:tcp-outbound-gateway id="outGateway"
                                 request-channel="input"
                                 connection-factory="client"
                                 request-timeout="10000"
                                 reply-timeout="10000"/>

    <!-- Server side -->
    <!-- When creating the socket factory on the server side, we specify both the serializer and deserializer
    which deals with both accepting a stream formatted with the Stx-Etx bytes as well as sending a stream
    formatted with the Stx-Etx bytes. -->
    <int-ip:tcp-connection-factory id="serverConnectionFactory"
                                   type="server"
                                   port="${availableServerSocket}"
                                   single-use="true"
                                   so-linger="10000"
                                   serializer="Custom1SerializerDeserializer"
                                   deserializer="Custom1SerializerDeserializer"/>


    <bean id="Custom1SerializerDeserializer" class="hello.CustomSerializerDeserializer1" />

    <int-ip:tcp-inbound-gateway id="gatewayCrLf"
                                connection-factory="serverConnectionFactory"
                                request-channel="incomingServerChannel"
                                error-channel="errorChannel"/>

    <!-- We leave a message listener off of this channel on purpose because we hook
    one up before the test actually runs (see the unit test associated with this
    context file) -->
    <int:channel id="incomingServerChannel" />

</beans>

EDIT:

Now I am able to send the messages using a custom serializer/deserializer. But unfortunately, I am unable to receive the responses. Here is my serializer/deserializer:

public class CustomSerializerDeserializer implements Serializer<String>, Deserializer<String> {
protected final Log logger = LogFactory.getLog(this.getClass());

public void serialize(String input, OutputStream outputStream) throws IOException {
    logger.info("inside serialize");
    outputStream.write(buildSampleMsg(input));
    outputStream.flush();
}

public String deserialize(InputStream inputStream) throws IOException {
    logger.info("inside deserialize");
    final int bufferSize = 1024;
    final char[] buffer = new char[bufferSize];
    final StringBuilder out = new StringBuilder();
    Reader in = new InputStreamReader(inputStream, "UTF-8");
    for (;;) {
        int rsz = in.read(buffer, 0, buffer.length);
        if (rsz < 0) {
            break;
        }
        out.append(buffer, 0, rsz);
    }
    logger.info(out.toString());
    return out.toString();
}

public byte[] buildSampleMsg(String body){
    logger.info("inside buildsamplemsg");
    ......
    return hexStringToByteArray(data);
}

I have some logging done on the first line of the serializer/deserializer but the log is never printed. Which in turn means, we don't get any response. Any help will be appreciated.


Answer:

Removing the reply-channel is correct. You don't give any indication of the error, but the gateway interface method return type must be changed to byte[].

EDIT

Clearly you are doing something wrong if the mainframe is getting junk. You should do the EBCDIC conversion after you convert your "ABCD" to a byte[] (with getBytes()); if you have EBCDIC chars in a String, that won't work. Also, bear in mind the default serializer will add CRLF (ascii) to the output. If that mainframe can determine the end of message from the data itself, you can use a ByteArrayRawSerializer in the serializer attribute. However, you will need a custom deserializer because the framework won't know how to construct a message from the stream; unless the mainframe closes the socket after sending the reply, in which case a ByteArrayRawSerializer will work as the deserializer attribute.

A common technique used to communicate with mainframes (and others) is to use a 1, 2, or 4 byte length header (network byte order). The ByteArrayLengthHeaderSerializer does just that.

If the mainframe is expecting EBCDIC delimiters, you'll need a custom serializer/deserializer - it might make more sense to do the EBCDIC conversion there, separating it from your application logic.

You can read about serializers/deserializers here.

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.

The ByteArrayCrlfSerializer, converts a byte array to a stream of bytes followed by carriage return and linefeed characters (\r\n). This is the default (de)serializer and can be used with telnet as a client, for example.

Question:

I would like to make a chat application. The client will be written with java and the server will be written with C. On the server side, the message will be sent as struct. On the client side, how do I read and separate the message with Java?

Here is a sample packet structure:

struct s_packet{
 int   text_color;
 char  text[TEXTSIZE];
 char  alias[ALIASIZE];
};

Here is a sample server(in C) send function:

send(iter->client.sockfd, (void *)se_packet, sizeof(s_packet), 0);

Here is a sample client recv function in C:

recv(m_sockfd, (void *)&se_packet, sizeof(s_packet),0);

printf("\x1b[3%dm <%s>: %s \x1b[0m\n", se_packet.text_color, se_packet.alias, se_packet.text);

I can read s_packet and separate in C, but How can I do it in java?

How can i separate like that in Java:

printf("\x1b[3%dm <%s>: %s \x1b[0m\n", se_packet.text_color, se_packet.alias, se_packet.text);

Answer:

The definite answer is that it won't be so easy. The first thing you should understand is how tcp works. It's a stream oriented protocol and there's no such thing as a "message" in tcp. You just send and receive a stream of bytes.

In your snippet of code recv can finish after reading a part of message sent from the server. Instead you should keep a local buffer in java and drop all the data you've received so far. In a while loop you can detect if a message that is ready for processing was received. If your message is not very big (less than the MTU), then you may get lucky and always receive the whole 'message'. If you are not concerned with that then you may just use java.io.InputStream.read(byte[]) method.

The other thing to consider is how you interpret a message you received. Well you have no other choise but to process it as byte[] in Java. First you may want to read s_packet.text_color. It probably will be placed as first 4 bytes in a message. You can construct int from thoes bytes (see Convert 4 bytes to int for example). But this is not a good practice. This is because you send a binary data that is depends on how your s_packet is represented in memory. In real life you usually don't know what will be the size of int or char, it's platform dependent. Or sometimes the order of bytes inside int itself can differ. Instead you should declare your own serialization protocol and how your message is converted to binary data and vice versa. Hope it helps.

Question:

I want to create a three way communication system in which every party has equal rights, with two communication channels to his partners. The program is decentralized and every machine runs the same code, in which there is a list of three IP addresses, with every one representing one of the machines. For each machine the partners' IP addresses are determined by looking at it's own IP address and using the other two from the list.

Now there is no predetermined order in which the machines are being turned on, is there any way to control the TCP communication other than setting it something like 'if the IP address you want to speak to is higher than your own, connect to a server, otherwise you are the server and accept sockets'?

In the end I want a TCPread(port) which fires every time a message from any IP comes in and a TCPwrite(port, ip, message) which sents a message.

My idea was a TCPhandler which stores all sockets it's got for every port I plan on using in the programm with one thread per port. Then everytime a read or write is performed it checks if there is a socket for the port and IP address in the handler, if not it sends a socket to the IP and waits for a response... I don't think i've understood that whole TCP thing entirely though.


Answer:

If you don't care about number of connections you can do following:

  • Each peer open port and listen for incoming connections
  • Try to establish connections to each peer with some period of time

As result you will get two connection between each peer. Now you can use them following way:

  • Outgoing connections are used for sending messages
  • Incoming connections are used for receiving messages

Question:

For class I am required to build a program using a TCP connection.

We are given the sample code below to work with and understand how to build a connection. The server and client communicate properly when I have only one client running. When I attempt to start a new instance of the client to simulate two people using the client with one server, the second client can not send or receive and never displays the message "Got I/O Connection". Why is this?

Here is the sample code.

// Fig. 27.5: Server.java
// Server portion of a client/server stream-socket connection. 
import java.io.EOFException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class Server extends JFrame 
{
   private JTextField enterField; // inputs message from user
   private JTextArea displayArea; // display information to user
   private ObjectOutputStream output; // output stream to client
   private ObjectInputStream input; // input stream from client
   private ServerSocket server; // server socket
   private Socket connection; // connection to client
   private int counter = 1; // counter of number of connections

   // set up GUI
   public Server()
   {
      super( "Server" );

      enterField = new JTextField(); // create enterField
      enterField.setEditable( false );
      enterField.addActionListener(
         new ActionListener() 
         {
            // send message to client
            public void actionPerformed( ActionEvent event )
            {
               sendData( event.getActionCommand() );
               enterField.setText( "" );
            } // end method actionPerformed
         } // end anonymous inner class
      ); // end call to addActionListener

      add( enterField, BorderLayout.NORTH );

      displayArea = new JTextArea(); // create displayArea
      add( new JScrollPane( displayArea ), BorderLayout.CENTER );

      setSize( 300, 150 ); // set size of window
      setVisible( true ); // show window
   } // end Server constructor

   // set up and run server 
   public void runServer()
   {
      try // set up server to receive connections; process connections
      {
         server = new ServerSocket( 12345, 100 ); // create ServerSocket

         while ( true ) 
         {
            try 
            {
               waitForConnection(); // wait for a connection
               getStreams(); // get input & output streams
               processConnection(); // process connection
            } // end try
            catch ( EOFException eofException ) 
            {
               displayMessage( "\nServer terminated connection" );
            } // end catch
            finally 
            {
               closeConnection(); //  close connection
               ++counter;
            } // end finally
         } // end while
      } // end try
      catch ( IOException ioException ) 
      {
         ioException.printStackTrace();
      } // end catch
   } // end method runServer

   // wait for connection to arrive, then display connection info
   private void waitForConnection() throws IOException
   {
      displayMessage( "Waiting for connection\n" );
      connection = server.accept(); // allow server to accept connection            
      displayMessage( "Connection " + counter + " received from: " +
         connection.getInetAddress().getHostName() );
   } // end method waitForConnection

   // get streams to send and receive data
   private void getStreams() throws IOException
   {
      // set up output stream for objects
      output = new ObjectOutputStream( connection.getOutputStream() );
      output.flush(); // flush output buffer to send header information

      // set up input stream for objects
      input = new ObjectInputStream( connection.getInputStream() );

      displayMessage( "\nGot I/O streams\n" );
   } // end method getStreams

   // process connection with client
   private void processConnection() throws IOException
   {
      String message = "Connection successful";
      sendData( message ); // send connection successful message

      // enable enterField so server user can send messages
      setTextFieldEditable( true );

      do // process messages sent from client
      { 
         try // read message and display it
         {
            message = ( String ) input.readObject(); // read new message
            displayMessage( "\n" + message ); // display message
         } // end try
         catch ( ClassNotFoundException classNotFoundException ) 
         {
            displayMessage( "\nUnknown object type received" );
         } // end catch

      } while ( !message.equals( "CLIENT>>> TERMINATE" ) );
   } // end method processConnection

   // close streams and socket
   private void closeConnection() 
   {
      displayMessage( "\nTerminating connection\n" );
      setTextFieldEditable( false ); // disable enterField

      try 
      {
         output.close(); // close output stream
         input.close(); // close input stream
         connection.close(); // close socket
      } // end try
      catch ( IOException ioException ) 
      {
         ioException.printStackTrace();
      } // end catch
   } // end method closeConnection

   // send message to client
   private void sendData( String message )
   {
      try // send object to client
      {
         output.writeObject( "SERVER>>> " + message );
         output.flush(); // flush output to client
         displayMessage( "\nSERVER>>> " + message );
      } // end try
      catch ( IOException ioException ) 
      {
         displayArea.append( "\nError writing object" );
      } // end catch
   } // end method sendData

   // manipulates displayArea in the event-dispatch thread
   private void displayMessage( final String messageToDisplay )
   {
      SwingUtilities.invokeLater(
         new Runnable() 
         {
            public void run() // updates displayArea
            {
               displayArea.append( messageToDisplay ); // append message
            } // end method run
         } // end anonymous inner class
      ); // end call to SwingUtilities.invokeLater
   } // end method displayMessage

   // manipulates enterField in the event-dispatch thread
   private void setTextFieldEditable( final boolean editable )
   {
      SwingUtilities.invokeLater(
         new Runnable()
         {
            public void run() // sets enterField's editability
            {
               enterField.setEditable( editable );
            } // end method run
         }  // end inner class
      ); // end call to SwingUtilities.invokeLater
   } // end method setTextFieldEditable
} // end class Server

// Fig. 27.7: Client.java
// Client portion of a stream-socket connection between client and server.
import java.io.EOFException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

--

public class Client extends JFrame 
{
   private JTextField enterField; // enters information from user
   private JTextArea displayArea; // display information to user
   private ObjectOutputStream output; // output stream to server
   private ObjectInputStream input; // input stream from server
   private String message = ""; // message from server
   private String chatServer; // host server for this application
   private Socket client; // socket to communicate with server

   // initialize chatServer and set up GUI
   public Client( String host )
   {
      super( "Client" );

      chatServer = host; // set server to which this client connects

      enterField = new JTextField(); // create enterField
      enterField.setEditable( false );
      enterField.addActionListener(
         new ActionListener() 
         {
            // send message to server
            public void actionPerformed( ActionEvent event )
            {
               sendData( event.getActionCommand() );
               enterField.setText( "" );
            } // end method actionPerformed
         } // end anonymous inner class
      ); // end call to addActionListener

      add( enterField, BorderLayout.NORTH );

      displayArea = new JTextArea(); // create displayArea
      add( new JScrollPane( displayArea ), BorderLayout.CENTER );

      setSize( 300, 150 ); // set size of window
      setVisible( true ); // show window
   } // end Client constructor

   // connect to server and process messages from server
   public void runClient() 
   {
      try // connect to server, get streams, process connection
      {
         connectToServer(); // create a Socket to make connection
         getStreams(); // get the input and output streams
         processConnection(); // process connection
      } // end try
      catch ( EOFException eofException ) 
      {
         displayMessage( "\nClient terminated connection" );
      } // end catch
      catch ( IOException ioException ) 
      {
         ioException.printStackTrace();
      } // end catch
      finally 
      {
         closeConnection(); // close connection
      } // end finally
   } // end method runClient

   // connect to server
   private void connectToServer() throws IOException
   {      
      displayMessage( "Attempting connection\n" );

      // create Socket to make connection to server
      client = new Socket( InetAddress.getByName( chatServer ), 12345 );

      // display connection information
      displayMessage( "Connected to: " + 
         client.getInetAddress().getHostName() );
   } // end method connectToServer

   // get streams to send and receive data
   private void getStreams() throws IOException
   {
      // set up output stream for objects
      output = new ObjectOutputStream( client.getOutputStream() );      
      output.flush(); // flush output buffer to send header information

      // set up input stream for objects
      input = new ObjectInputStream( client.getInputStream() );

      displayMessage( "\nGot I/O streams\n" );
   } // end method getStreams

   // process connection with server
   private void processConnection() throws IOException
   {
      // enable enterField so client user can send messages
      setTextFieldEditable( true );

      do // process messages sent from server
      { 
         try // read message and display it
         {
            message = ( String ) input.readObject(); // read new message
            displayMessage( "\n" + message ); // display message
         } // end try
         catch ( ClassNotFoundException classNotFoundException ) 
         {
            displayMessage( "\nUnknown object type received" );
         } // end catch

      } while ( !message.equals( "SERVER>>> TERMINATE" ) );
   } // end method processConnection

   // close streams and socket
   private void closeConnection() 
   {
      displayMessage( "\nClosing connection" );
      setTextFieldEditable( false ); // disable enterField

      try 
      {
         output.close(); // close output stream
         input.close(); // close input stream
         client.close(); // close socket
      } // end try
      catch ( IOException ioException ) 
      {
         ioException.printStackTrace();
      } // end catch
   } // end method closeConnection

   // send message to server
   private void sendData( String message )
   {
      try // send object to server
      {
         output.writeObject( "CLIENT>>> " + message );
         output.flush(); // flush data to output
         displayMessage( "\nCLIENT>>> " + message );
      } // end try
      catch ( IOException ioException )
      {
         displayArea.append( "\nError writing object" );
      } // end catch
   } // end method sendData

   // manipulates displayArea in the event-dispatch thread
   private void displayMessage( final String messageToDisplay )
   {
      SwingUtilities.invokeLater(
         new Runnable()
         {
            public void run() // updates displayArea
            {
               displayArea.append( messageToDisplay );
            } // end method run
         }  // end anonymous inner class
      ); // end call to SwingUtilities.invokeLater
   } // end method displayMessage

   // manipulates enterField in the event-dispatch thread
   private void setTextFieldEditable( final boolean editable )
   {
      SwingUtilities.invokeLater(
         new Runnable() 
         {
            public void run() // sets enterField's editability
            {
               enterField.setEditable( editable );
            } // end method run
         } // end anonymous inner class
      ); // end call to SwingUtilities.invokeLater
   } // end method setTextFieldEditable
} // end class Client

Answer:

Issue is in Server class. This class is single threaded (main thread). Main thread is being used for both accepting new connection and reading from socket. Main thread after accepting connection goes to processConnection method and blocks on following call.

message = ( String ) input.readObject(); // read new message

This call is made in a loop which terminates only if you receive 'TERMINATE' from client

   } while ( !message.equals( "CLIENT>>> TERMINATE" ) );

until above loop is running code can't return to 'runServer' method, which can accept connection using 'waitForConnection'.

You need to separate threads to accept connection and read from connected sockets.

Question:

I have TCP server-client application. It works but sometime something happens. Client connects to server but server says he doesn't accepted him.

Server side code:

while(!stopped){
            try {
                AcceptClient();
            } catch(SocketTimeoutException ex){
                continue;
            } catch (IOException ex) {
                System.err.println("AppServer: Client cannot be accepted.\n"+ex.getMessage()+"\n");
                break;
            }
...

private void AcceptClient() throws IOException {
    clientSocket = serverSocket.accept();
    clientSocket.setSoTimeout(200);
    out = new ObjectOutputStream(clientSocket.getOutputStream());
    in = new ObjectInputStream(clientSocket.getInputStream());
    System.out.println("Accepted connection from "+clientSocket.getInetAddress());
}

Client side code:

    try {
        socket = new Socket(IPAddress, serverPort);
        socket.setSoTimeout(5000);
        out = new ObjectOutputStream(socket.getOutputStream());
        in = new ObjectInputStream(socket.getInputStream());
    } catch (IOException e1) {
        sendSystemMessage("DISCONNECTED");
        sendSystemMessage(e1.getMessage());
        return;
    }
    sendSystemMessage("CONNECTED");

If client connects the message:

Accepted connection from ... appears. But sometimes it doesn't appear even if client sends message "CONNECTED"

Server is still runing the loop trying to get client and it is catching socketTimeoutException. Client is connected, sends message and waits for response.


Answer:

I suspect a missing 'flush' inside your client's 'sendSystemMessage()'. Unfortunately the constructor of ObjectInputStream attempts to read a header from the underlying stream (which is not very intuitive IMHO). So if the client fails to flush the data - the server may remain stuck on the line "in = new ObjectInputStream(socket.getInputStream())"...

As a side note it's usually better for a server to launch a thread per incoming client, but that's just a side remark (plus it obviously depends on requirements).

Question:

I need help in socket programming again. Now I want to write the value of my textfield to my remote server log file in linux after a button is clicked by using the command.

"echo '" +textfieldValue+"' >> filename"

I made two threads in the Server.java

  • Thread one is to output the values of tail -f /root/log.txt to my client
  • Thread two is to read the command "echo '" +textfieldValue+"' >> filename" sent from the client.

My thread one is running but my thread two is not executing.

Please help.

Client.java

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;

public class Client
{
    Socket sock;
    String server = "XXX.XXX.XX.XX";
    int port = 5550;
    String filename = "/root/log.txt";
    String command;
    UI gui;

    public static void main(String[] args)
    {
        new Client();
    }

    public Client()
    {
        gui = new UI();
        gui.btnListner(new BtnListener());
        openSocket();
        try {
            // read incoming text from server
            BufferedReader rd = new BufferedReader(new InputStreamReader(sock.getInputStream()));
            String str;
            while ((str = rd.readLine()) != null) {
                System.out.println(str);
            }
            //rd.close();
        } 
        catch (IOException e) 
        {
            System.err.println(e);
        }
    }

    //after the button is being pressed. send command to server
    class BtnListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent arg0) {
            String textfieldValue = gui.getTextFieldValue();
            command = "echo '" +textfieldValue+"' >> filename";
            BufferedWriter wr;
            try {
                wr = new BufferedWriter(new OutputStreamWriter(sock.getOutputStream()));
                wr.write(command);
                wr.flush();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }   
        }
    }
    private void openSocket()
    {
        // open a socket and connect with a timeout limit
        try
        {
            InetAddress addr = InetAddress.getByName(server);
            SocketAddress sockaddr = new InetSocketAddress(addr, port);
            sock = new Socket();

            // this method will block for the defined number of milliseconds
            int timeout = 2000;
            sock.connect(sockaddr, timeout);
        } 
        catch (UnknownHostException e) 
        {
            e.printStackTrace();
        }
        catch (SocketTimeoutException e) 
        {
            e.printStackTrace();
        }
        catch (IOException e) 
        {
            e.printStackTrace();
        }
    }
}

Server.java

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

public class Server  {
    private int portNo = 0;
    private Socket socket = null;

    @SuppressWarnings("resource")
    public Server(int portNo) {
        this.portNo = portNo;
        ServerSocket sSocket = null;
        try {
            sSocket = new ServerSocket(portNo);
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        while(true) {
            try {
                socket = sSocket.accept();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            Thread t = new Thread(new acceptClient());
            t.start();
        }
    }

    class acceptClient implements Runnable {
        public void run() {

            Thread one = new Thread(new t1());
            one.start();

            //thread two not executing!
            Thread two = new Thread(new t2());
            two.start();
        }
    }

    //reading and writing the log file output to client
    class t1 implements Runnable {

        @Override
        public void run() {
            BufferedWriter wr = null;
            Process p = null;
            System.out.println("A client has connected!");
            try {
                p = Runtime.getRuntime().exec("tail -f /root/log.txt");
            } catch (IOException e1) {
                e1.printStackTrace();
            }

            try {
                wr = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            BufferedReader rd = new BufferedReader(new InputStreamReader(p.getInputStream()));
            try {   
                //rd.close();
                String s = null;
                while ((s = rd.readLine()) != null) {
                    System.out.println(s);
                    wr.write(s+"\n");
                    wr.flush();
                }

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

        }
    }

    //reading and getting the command "echo 'gui.getTextFieldValue()' >> filename" from client
    class t2 implements Runnable {
        @Override
        public void run() {
            //Process p2 = null;
            try {
                BufferedReader rd2 = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                String s2 = null;
                while ((s2 = rd2.readLine()) != null) {
                    System.out.println(s2);
                    //p2 = Runtime.getRuntime().exec(s2);
                    //new BufferedReader(new InputStreamReader(p2.getInputStream()));
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }

    }
    public static void main(String[] args) {
        int portNo = 5550;
        new Server(portNo);
    }
}

Answer:

The server is reading lines but the client isn't writing lines. Add a line terminator to the message, or use BufferedWriter.newLine().

Question:

I would like to open a TCP connection to send data to an ip address in an android application. Every socket programming article/thread I find shows both client and server side code (often the chat program). Is it possible to just have the client code running on an android device and send arbitrary data to, for example, google's IP address? Right now I am using the code from this thread (highest upvoted answer) Android Client socket , how to read data? in a class that extends AsynchTask like this:

public class InternetTask extends AsyncTask<Void, Integer, Void> {
    public static final int BUFFER_SIZE = 2048;
    private Socket socket = null;
    private PrintWriter out = null;
    private BufferedReader in = null;
    private int port = 80;
    private String host = null;
    private static final String TAG="sure2015test";

    public InternetTask(String host,int port) {
        this.host=host;
        this.port=port;
    }

    @Override
    protected Void doInBackground(Void... args) {


        connectWithServer();
        Log.i(TAG, "Connected");
        sendDataWithString("hello");
        Log.i(TAG, "Sent data");
        String response=receiveDataFromServer();
        Log.i(TAG,response);
        disConnectWithServer();
        return null;
    }


    private void connectWithServer() {
        try {
            if (socket == null) {
                socket = new Socket(this.host, this.port);
                out = new PrintWriter(socket.getOutputStream());
                in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            }
        } catch (IOException e) {
            Log.i(TAG,"IO Exeception");
            e.printStackTrace();
        }
    }

    private void disConnectWithServer() {
        if (socket != null) {
            if (socket.isConnected()) {
                try {
                    in.close();
                    out.close();
                    socket.close();
                } catch (IOException e) {
                    Log.i(TAG,"IO exception disconnecting");
                    e.printStackTrace();
                }
            }
        }
    }

    public void sendDataWithString(String message) {
        if (message != null) {
            connectWithServer();
            out.write(message);
            out.flush();
        }
    }

    public String receiveDataFromServer() {
        try {
            String message = "";
            int charsRead = 0;
            char[] buffer = new char[BUFFER_SIZE];
            Log.i(TAG,"Message before: "+message);
            while ((charsRead = in.read(buffer)) != -1) {
                message += new String(buffer).substring(0, charsRead);
                Log.i(TAG,message);
            }
            Log.i(TAG,"Message after: "+message);
            disConnectWithServer(); // disconnect server
            return message;
        } catch (IOException e) {
            Log.i(TAG,"IO Error in receiving message");
            return "Error receiving response:  " + e.getMessage();
        }
    }
}

And my onCreate method in MainActivity.java

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    InternetTask task=new InternetTask("74.125.226.159",80);
    task.execute();
}

When I run this I get this in the logs:

05-16 00:01:04.368      622-637/? I/sure2015test﹕ Connected
05-16 00:01:04.369      622-637/? I/sure2015test﹕ Sent data
05-16 00:01:04.369      622-637/? I/sure2015test﹕ Message before:
05-16 00:03:04.405      622-637/com.example.connorstein.sockethelloworld I/sure2015test﹕ Message after:

So there were no exceptions when opening a socket on port 80 with the IP of google and no exceptions sending or receiving the data. It looks like I just have no response. Is this expected because the data I sent ("hello") is meaningless? I would think that at least I would get a response saying invalid request or something like that. I also tried sending "GET / HTTP/1.0", but also no response.


Answer:

Google is responding blank because you aren't sending it a proper HTTP request. Mimic the request of a normal web browser, and you will get a response. HTTP is a protocol built on top of TCP. You need to follow the protocol to get anything useful out of servers.

Example minimal browser header that gets a response:

GET / HTTP/1.1\r\nUser-Agent: curl/7.37.1\r\nHost: www.google.com\r\nAccept: */*\r\n\r\n

Instead of using a web server, consider using an SSH server. An SSH server will send something like...

SSH-2.0-OpenSSH_5.3\r\n

...when you connect. A server that always responds is a lot easier to troubleshoot client code. Note that you might make a sysadmin mad constantly connecting to their ssh server. You may want to set up your own to test against.

Question:

I am facing a strange problem, local client tcp-connections (python) to my tcp-server (java, on windows 8 64-bit) are working. For example

Python client.py

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("192.168.2.108", 30000))
s.sendall('Hello, server')
s.close()

successfully connects to 192.168.2.108 at port 30000, and the server prints "Hello, server" on eclipse's console.

If I change the interface to loopback interface, it works too.

If I use the same script on my remote Linux machine (Arch with 3.18.6 kernel, 32-bit, ip: 192.168.2.104) the server won't print out anything.

If I try to connect via nc 192.168.2.108 30000 on my client -> same problem

If I try to connect via telnet 192.168.2.108 30000 on my client -> same problem (telnet: connection timed out)

Here a piece of code which might be important for the problem. The backstory is, the server creates 3 serverSockets with ports 30000, 40000, 50000 each in its own thread.

TCP.java

[...]

// pseudo-code: List<ServerSocket> serverSockets = {serverSocket1 port 30000,   
// serverSocket2 port 40000, serverSocket3 port 50000}

[...]

for(ServerSocket serverSocket : serverSockets){
new Thread(new TCPRunnable(serverSocket)).start();
}

[...]

TCPRunnable.java

[...]

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

public void run() {
    long threadId = Thread.currentThread().getId();
    System.out.println(threadId + ": " + serverSocket);
    // output: 20: ServerSocket[addr=0.0.0.0/0.0.0.0,localport=30000]
    try {
        System.out.println("before accept()");

        while(true){
            System.out.println("before accept() in while-loop");
            Socket socket = serverSocket.accept();
            String message = readMessage(socket);
            System.out.println(threadId + ": " + message );
        }
    } catch (IOException e) {
        e.printStackTrace();
    }  catch (SecurityException e) {
        e.printStackTrace();
    }
    System.out.println("leaving run");
}

[...]

output of `netstat -a | find "30000" to see that the port(s) are listening

TCP    0.0.0.0:30000          be-dsktp:0             LISTENING
TCP    [::]:30000             be-dsktp:0             LISTENING

I hope someone can help. Thanks in advance.


Answer:

Firewall was in the way. javaw.exe has to be allowed in firewall.cpl. Thanks Zielu!

Question:

this are my first java steps with a socket connection. I like to code a tcp client that connects to a server and read all data that the server will ever send. Each message from the server will be terminated by 0x00.

First question: How can i read this variable message length?

Secont question: if the user enters text via the keyboard this text should be send to the server, while i am receiving. But how can i send data while i am reading from the server?

This is my code till now:

import java.io.*;

 public class Client {
     public static void main(String[] args) {
    Client client = new Client();
    try {
        client.test();
    } catch (IOException e) {
        e.printStackTrace();
    }
     }
     void test() throws IOException {
    String ip = "127.0.0.1"; // localhost
    int port = 12345;
    java.net.Socket socket = new java.net.Socket(ip,port); // verbindet sich mit Server
    String zuSendendeNachricht = "Hello World0x00";
    schreibeNachricht(socket, zuSendendeNachricht);
    while (true){
        String empfangeneNachricht = leseNachricht(socket);
        System.out.println(empfangeneNachricht);
        }
     }
     void schreibeNachricht(java.net.Socket socket, String nachricht) throws IOException {
     PrintWriter printWriter =
        new PrintWriter(
        new OutputStreamWriter(
            socket.getOutputStream()));
    printWriter.print(nachricht);
    printWriter.flush();
    }
    String leseNachricht(java.net.Socket socket) throws IOException {
    BufferedReader bufferedReader =
        new BufferedReader(
        new InputStreamReader(
            socket.getInputStream()));
    char[] buffer = new char[200];
        int anzahlZeichen = bufferedReader.read(buffer, 0, 200); // blockiert bis Nachricht empfangen
        String nachricht = new String(buffer, 0, anzahlZeichen);
        System.out.println(nachricht);
    }
 }

And how can i read a variable message length


Answer:

First question: How can i read this variable message length?

Just read the incoming data with size of 1 byte and check every byte on 0x00.

Secont question: if the user enters text via the keyboard this text should be send to the server, while i am receiving. But how can i send data while i am reading from the server?

Start two independent threads. One for reading and one for writing. Pseudo code:

Thread readingThread = new Thread(new Runnable() {
  @Override
  public void run() {
    //do reading here...
  }
});
readingThread.start();

Thread writingThread = new Thread(new Runnable() {
  @Override
  public void run() {
    //do writing here...
  }
});
writingThread.start();

Find a working example below for reading every byte and check on 0x00. There are no threads used here.

Content of Client.java:

package tcpserverclient;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Client {

    private static final Logger LOG = Logger.getLogger(Client.class.getName());

    private String getData(InputStream stream2server) {
        BufferedInputStream inputStream = new BufferedInputStream(stream2server);

        StringBuilder incomingData = new StringBuilder("");
        try {
            int c;
            LOG.info("reading incoming data...");
            while ((c = inputStream.read()) != -1) {
                if (c == 0) {
                    break;
                } else {
                    incomingData.append((char) c);
                    System.out.print((char) c);
                }
            }
            LOG.info("\ndata complete.");
        } catch (IOException ex) {
            ex.printStackTrace();
        }

        return incomingData.toString();
    }

    private void startListen(int port) {
        try {
            ServerSocket serverSocket = new ServerSocket(port);
            while (true) {
                LOG.info("\nListening on port " + port);
                Socket socket = serverSocket.accept();
                LOG.info("incoming call...");

                InputStream incoming = socket.getInputStream();
                OutputStream outgoing = socket.getOutputStream();
                String data = getData(incoming);
                LOG.info(data);

                outgoing.close();
                incoming.close();
                socket.close();
            }

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

    public static void main(String[] args) {
        new Client().startListen(9999);
    }
}

Content of Server.java:

package tcpserverclient;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public class Server {

    public void sendCommand(String ip, int port, String cmd) {
        try {
            Socket socket = new Socket(ip, port);
            InputStream fromServer = socket.getInputStream();
            OutputStream toServer = socket.getOutputStream();
            socket.setSoTimeout(0);

            byte[] ba = cmd.getBytes();
            byte[] ba0 = new byte[ba.length + 1];
            System.arraycopy(ba, 0, ba0, 0, ba.length);
            ba0[ba.length] = 0;

            toServer.write(ba0);

            fromServer.close();
            toServer.close();
            socket.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    public static void main(String[] args) {
        new Server().sendCommand("127.0.0.1", 9999, "Hal, can you read me?");
    }
}

Start the Client.java first then the Server.java. Output is something like this:

run:
Jan 06, 2015 9:19:42 AM tcpserverclient.Client startListen
Information: 
Listening on port 9999
Jan 06, 2015 9:19:44 AM tcpserverclient.Client startListen
Information: incoming call...
Jan 06, 2015 9:19:44 AM tcpserverclient.Client getData
Information: reading incoming data...
Jan 06, 2015 9:19:44 AM tcpserverclient.Client getData
Information: 
data complete.
Jan 06, 2015 9:19:44 AM tcpserverclient.Client startListen
Information: Hal, can you read me?
Jan 06, 2015 9:19:44 AM tcpserverclient.Client startListen
Information: 
Listening on port 9999
Hal, can you read me?

Question:


Answer:

Your server was blocking on readLine(). It blocks for a line terminator. The client was only sending a raw string. The solution is to send a line terminator with each raw string. The same applies when the server responds to the client.

As Simon has pointed out a printwriter would be a good choice if your message protocol is to pass line terminated strings.

Question:

Hi I'm having a small problem with my program which is a simple client/server. The client sends the contents of a textfile to the server. The text file is just ints and then the server is suppose to send back the largest prime number less than each int in the text file(if its prime it should just send back the prime number and do nothing). So for instance lets say the text file is 5 15 28. The result after running the program should be 5 13 23.

Here's my code for the Client side:

public class TCPClient {



        public static void main(String[] args) throws Exception{
            try{ 
                Socket mySock = new Socket("127.0.0.1", 12001);
                BufferedReader in = new BufferedReader(
                        new InputStreamReader(mySock.getInputStream()));
                PrintStream out = new PrintStream( mySock.getOutputStream());
                Scanner scan = new Scanner(new File(args[0]));
                String msg = scan.nextLine();
                out.println(msg);
                System.out.println(in.readLine());
                mySock.close();

            }catch (Exception e){
            }
        }
    }

Here's my code for the server side:

public class TCPServer {
    public static void main(String[] args) throws Exception {
        try{
            ServerSocket mySock = new ServerSocket(12001);
            Socket client = mySock.accept();
            BufferedReader in = new BufferedReader(
                    new InputStreamReader(client.getInputStream()));
            PrintStream out = new PrintStream( client.getOutputStream());

            String[] arr = in.readLine().split(" ");
            int[] intarr = new int[arr.length];

            for(int i = 0; i <arr.length; i++){
             intarr[i] = Integer.parseInt(arr[i]);
             if (prim(intarr[i]) == true){
                 out.println(intarr[i]);

                }else{

                    while (!prim(--intarr[i])){

                    }

                    out.println(intarr[i]);
                }

            }           


            client.close();
            mySock.close();

        }catch (Exception e){

        }
    }

    public static boolean prim(int m){
        int n=m;
        for(int i=2;i<n;i++){
            if(n%i == 0){
                return false;
            }

        }   
        return true;
    }

}

When I run this program my output is only the first number in the text file. So if my text file is 1 3 5. My output is just 1. However, my prime algorithm is at least working because if my text file is 8 for instance, my program will return 7. Does anyone know why this is happening?


Answer:

By change your server code to a simple test and printing to System.out

    String[] arr = "1 3 5 6".split(" ");
    int[] intarr = new int[arr.length];

    for(int i = 0; i <arr.length; i++){
     intarr[i] = Integer.parseInt(arr[i]);
     if (prim(intarr[i]) == true){
         System.out.println(intarr[i]);

        }else{
            while (!prim(--intarr[i])){
            }
            System.out.println(intarr[i]);
        }
    }     

you can see that it works OK, but in your code, your output in writing using println, so your client needs to loop System.out.println(in.readLine()); or change your server to write using one line and some delimiter

Question:

I was asking before this Question...

I want to test the TCP Socket Behaviour in my Network, beacuse I need to test my Java Applications...

I created a Server Client Model Example, using Threads...

Here the ConsumerServer

  public class ConsumerServer extends Thread {
    private ServerSocket SrvrScktConsumer;
    Socket clientSocket = null;
    private boolean isConsumerRunning = false;

    public ConsumerServer(int ConsPort) {
      try {
        SrvrScktConsumer = new ServerSocket(ConsPort);
        System.out.println(NL + "ConsumerServer Listening on port number: " + ConsPort);
      } catch (IOException e) { }
    }

    @Override public void run() {
      try {
        clientSocket = SrvrScktConsumer.accept();
        InputStream input;
        byte[] innerBytes = new byte[1024];
        try {
          input  = clientSocket.getInputStream();
          Integer iRemotePort = clientSocket.getPort();
          String sRemoteHost = clientSocket.getInetAddress().getHostAddress();
          System.out.println("ConsumerServer: Remote Connection\n\tPort:" + iRemotePort+ " Host:" + sRemoteHost);
          isConsumerRunning = true;
          while (isConsumerRunning) {
            try {
              byte[] incomingBytes = Arrays.copyOf(innerBytes, input.read(innerBytes));
              jtaMessages.append(NL + "Consumer GET " + new String(incomingBytes));
              jtfLastReceived.setText(new String(incomingBytes));
            } catch (IOException | NegativeArraySizeException | IndexOutOfBoundsException e) {
              isConsumerRunning = false;
            }
          }
          System.out.println(NL + "ConsumerClient closing from Host " + sRemoteHost + " Port " + iRemotePort);
          try {  if (input != null) input.close(); } catch (IOException e) { }
        } catch (IOException e) {
          System.out.println(NL + "Error Creating ConsumerClient\n\t:" + e.toString());
        }
      } catch (IOException | NullPointerException e) {
          System.out.println(NL + "ConsumerServer Stopped: " + e.toString()) ;
      }
      System.out.println(NL + "Exiting ConsumerServer...");
    }

    public void stopServer() {
      try {
        SrvrScktConsumer.close();
      } catch (IOException | NullPointerException e) { }
      try {
        clientSocket.close();
      } catch (IOException | NullPointerException e) { }
      isConsumerRunning = false;
    }
  };

Here the ProducerClient

  public class ProducerClient extends Thread {
    private Socket clientSocket = null;
    private OutputStream output = null;
    private boolean isProducerRunning = false;

    public ProducerClient(String ConsHost , int ConsPort) {
      try {
        clientSocket = new Socket(ConsHost, ConsPort);
        output = clientSocket.getOutputStream();
        System.out.println(NL + "ProducerClient Connected to port number: " + ConsPort);
      }
      catch (IOException e) { }
    }

    @Override public void run() {
      if (!(clientSocket == null)) {
        Integer iLocalPort = clientSocket.getLocalPort();
        String sLocalHost = clientSocket.getLocalAddress().getHostAddress();
        System.out.println("ConsumerServer: Local Connection\n\tPort:" + iLocalPort+ " Host:" + sLocalHost);
        int ctrlPrintOut = 0, ctrlPrintIn = 0;
        isProducerRunning = true;
        while (isProducerRunning) {
          try {
            if (bProducerReady) {
              bProducerReady = false;
              output.write(jtfSendMessage.getText().getBytes());
              jtaMessages.append(NL + "Producer PUT " + jtfSendMessage.getText());
              jtfSendMessage.setText("");
            }
//            // Ini Code Block to delete
//            else {
//              try {
//                Thread.sleep(1);
//              } catch (InterruptedException ex) { }
//              if (ctrlPrintOut == 1000000 /*Integer.MAX_VALUE*/) {
//                if (ctrlPrintIn == 2) {
//                  System.out.println("ProducerClient Waiting!");
//                  ctrlPrintIn = 0;
//                }
//                ctrlPrintIn++; ctrlPrintOut = 0;
//              }
//              ctrlPrintOut++;
//            }
//            // End Code Block to delete
          } catch (IOException e) {
            System.out.println("ProducerClient: " + e.toString());
            isProducerRunning = false;
          }
        }
        try { output.close(); } catch (IOException e) { }
        try { clientSocket.close(); } catch (IOException e) { }
        System.out.println(NL + "Exiting ProducerClient...");
      }
    }

    public void stopClient() {
      try {
        clientSocket.close();
      } catch (IOException | NullPointerException e) { }
      isProducerRunning = false;
    }
  };

I want to remove the indicated block code, but when I remove.. My Test doesn't work properly.

Here the Class using before Classes

public class ClientServerShort extends JFrame {

  private JButton jbSendMessage = new JButton("Send Message");
  private JLabel jlLastReceived = new JLabel("Last Received");
  private JTextArea jtaMessages = new JTextArea(5,20);
  private JScrollPane jspMessages = new JScrollPane(jtaMessages);
  private JToggleButton jtbConsumer = new JToggleButton("Launch Consumer Server");
  private JToggleButton jtbProducer = new JToggleButton("Launch Producer Client");
  private JTextField jtfLastReceived = new JTextField();
  private JTextField jtfSendMessage = new JTextField();

  static boolean bProducerReady = false;
  static final String NL = System.getProperty("line.separator");
  ConsumerServer thrdConsumerServer = null;
  ProducerClient thrdProducerClient = null;

  public ClientServerShort() {
    setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

    jbSendMessage.addActionListener((ActionEvent evt) -> {
      if (!jtfSendMessage.getText().isEmpty()) {
        bProducerReady = true;
      }
    });

    jlLastReceived.setBorder(BorderFactory.createEtchedBorder());
    jlLastReceived.setHorizontalAlignment(SwingConstants.CENTER);

    jtbConsumer.addActionListener((ActionEvent evt) -> {
      if (jtbConsumer.isSelected()) {
        if (thrdConsumerServer == null) {
          thrdConsumerServer = new ConsumerServer(1027);
          thrdConsumerServer.start();
        }
      } else {
        if (thrdConsumerServer != null) {
          thrdConsumerServer.stopServer();
          thrdConsumerServer = null;
        }
      }
    });
    jtbProducer.addActionListener((ActionEvent evt) -> {
      if (jtbProducer.isSelected()) {
        if (thrdProducerClient == null) {
          thrdProducerClient = new ProducerClient("192.168.0.49", 1027);
          thrdProducerClient.start();
        }
      } else {
        if (thrdProducerClient != null) {
          thrdProducerClient.stopClient();
          thrdProducerClient = null;
        }
      }
    });

    jtfLastReceived.setEditable(false);

    JPanel jpMessagesUp = new JPanel();
    jpMessagesUp.setLayout(new GridLayout(2, 2, 6, 6));
    jpMessagesUp.add(jbSendMessage);
    jpMessagesUp.add(jtfSendMessage);
    jpMessagesUp.add(jlLastReceived);
    jpMessagesUp.add(jtfLastReceived);

    getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.PAGE_AXIS));
    add(jtbProducer);
    add(jtbConsumer);
    add(jpMessagesUp);
    add(jspMessages);
    pack();
  }

  public static void main(String args[]) {
    EventQueue.invokeLater(() -> {
      new ClientServerShort().setVisible(true);
    });
  }

}

Question:

What is the reason, why I remove the indicate snippet code (in ProducerClient), my Single App doesn't work?


Answer:

The reason is exactly what I told you in your other question. bProducerReady needs to be volatile, as you are reading and writing it from different threads. Your strange delay code accomplishes the same memory flush just via elapse of time.

NB It does not need to be static.

Why you reposted this answered question remains a mystery.

Question:

I am building a multithreaded chat server application which broadcasts a message sent by one client to all the clients.On most of the examples on internet and on Oracle's website too broadcasting is done using udp (Multicast Socket)but i am using tcp . Does anyone know how to send a message to all the connected clients in a tcp conection? Here is my current code which works fine and sends the message receieved from a client to that client only:

EchoServer

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

public class EchoServer 
{
    public static void main(String[] args)
        throws IOException
    {
        if (args.length != 1) {
            System.err.println("Usage: java EchoServer <port number>");
            System.exit(1);
        }

        int portNumber = Integer.parseInt(args[0]);

        ServerSocket serverSocket = new ServerSocket(Integer.parseInt(args[0]));

        while (true) {
            try {
                Thread t = new Thread(new MultiServer(serverSocket.accept()));
                t.start();
            } catch(IOException e) {
                System.out.println("Accept Failed:");
                System.exit(-1);
            }
        }
    }
}

EchoClient

import java.io.*;
import java.util.Scanner;
import java.net.*;

public class EchoClient 
{
    public static void main(String[] args) throws IOException 
    {
        if (args.length != 2) {
            System.err.println("Usage: java EchoClient <host name><portnumber>");
            System.exit(1);
        }

        String hostName = "localhost";

        int portNumber = Integer.parseInt(args[1]);

        try (
            Socket echoSocket = new Socket(hostName, portNumber);
            PrintWriter out = new PrintWriter(echoSocket.getOutputStream(), true);
            BufferedReader in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
            BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
        ) {
            String userInput;

            while ((userInput = stdIn.readLine()) != null)  {
                out.println(userInput);
                System.out.println("echo::" + in.readLine());
            }
        } catch (UnknownHostException e) {
            System.err.println("Don't know about host " + hostName);
            System.exit(1);
        } catch (IOException e) {
            System.err.println("Couldn't get I/O for the connection to " + hostName);
            System.exit(1);
        } 
    }
}

MultiServer

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

public class MultiServer implements Runnable
{
    private Socket client;

    public MultiServer(Socket m)
    {
        this.client = m;
    }

    @Override
    public void run()
    {
        BufferedReader in = null;
        PrintWriter out = null;
        try {
            out = new PrintWriter(client.getOutputStream(), true);
            in = new BufferedReader(new InputStreamReader(client.getInputStream()));
        } catch(IOException ignored) {
        }

        while (true) {
            String line;
            try {
                while ((line = in.readLine()) != null)
                    out.println(line);
            } catch (IOException e) {
                System.out.println("Read Failed");
                System.exit(-1);
            }
        }
    }
}

Answer:

Use the concurrent hashmap and maintain your list of clients in that. The concurrent hashmap is safe and you won't need to use synchronization while adding / iterating / removing

// Create and main list of active clients based on their host name / ip address
ConcurrentHashMap<String, Socket> activeClients = new ConcurrentHashMap<String, Socket>();

// message received
activeClients.put(clientsocket.getInetAddress().getHostAddress(), clientsocket);

// broadcast message to all available clients
for(String clientHost : activeClients.keySet()) {
      // get each socket here and send a message to them.
}

Vector is basically a thread safe one so you don't need to worry about that one.

Question:

i have an implementation to do in a college project, and i dont know how to avchive it!. my problem its like the title say, conect android with c++ via sockets.

c++ must manage at least a pair of sockets clients (android Devices) or more. so i try ...

#include <iostream>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<stdlib.h>
#include<unistd.h>

using namespace std;

int main()
{
    int client, server;
    int portnum = 1500;
    bool isExit = false;
    int bufsize = 1024;
    char buffer[bufsize];

    struct sockaddr_in server_addr;
    socklen_t size;

    //init socekt

    client = socket(AF_INET, SOCK_STREAM, 0);

    if(client < 0){
        cout << "Error Estableciendo la conexion" << endl;
    }

    cout <<"server Socket conexion creada" << endl;

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


    //biding soket

    if(bind(client,(struct sockaddr*)&server_addr,sizeof(server_addr)) < 0){
        cout << "Error Biding Socket" << endl;
        exit(1);
    }

    size= sizeof(server_addr);
    cout << "buscando clientes" << endl;

    //escuchando sokets

    listen(client,1);

    //accept client

    server = accept(client, (struct sockaddr*)&server_addr, &size);

    if(server < 0){
        cout<< "Error al Aceptar" << endl;
        exit(1);
    }

    while(server >0){
        strcpy(buffer,"server conectado---\n");
        send(server,buffer,bufsize,0);

        cout <<"conectado con el cliente" << endl;
        cout << "Ingresad # paara terminar la conexion" << endl;

        cout <<"client: ";
        do{
            recv(server,buffer,bufsize,0);
            cout << "buffer" << " ";
            if(*buffer == '#'){
                *buffer = '*';
                isExit=true;
            }
        }while(*buffer != '*');

        do{
            cout << "\n server: ";
            do{
                cin >> buffer;
                send(server,buffer,bufsize,0);
                if(*buffer == '#'){
                    send(server,buffer,bufsize,0);
                    *buffer = '*';
                    isExit=true;
                }
            }while(*buffer != '*');

            cout << "Client: ";

            do{
                recv(server,buffer,bufsize,0);
                cout << buffer << " ";
                if(*buffer == '#'){
                    *buffer = '*';
                    isExit = true;
                }
            }while(*buffer != '*');
        }while(isExit);

        cout << "Conection Terminated..." << endl;
        cout << "Goodbye..." << endl;
        isExit =false;
        exit(1);
    }
    close(client);
    return 0;
}

to listen every conection (please if you see bad logic in my code let me know it and what i need to do to fix it)

and in android i make something like this in a class that its called from an activity only for testing...

import java.net.Socket;
import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Socktest {

    public void prueba() {
        try {
            Socket sock = new Socket("127.0.0.1",1234);

            // Your Java Code Verbatim:
            BufferedReader br = new BufferedReader(new InputStreamReader(sock.getInputStream()));
            String test = br.readLine();

            System.out.println(test);
            sock.close();
        } catch (Exception ex) {
            System.out.println(ex.getCause().toString());
        }
    }
}

(please if you see bad logic let me knowit because i want to learn more from my failures)

and the server goes fine when i compiled, its standing by to recive a new conection but when a luch the android activity and i run the "conection class" it says access denied, i am working on linux mint if that afect...

i am going to be gratfull with you coments, suggestions and advices.


Answer:

Socket sock = new Socket("127.0.0.1",1234); this line is your problem right here, 127.0.0.1 is the local loop IP, its actually an IP address that maps to the device the code is on, so your android client is never connecting to the machine where the c++ code is running, instead what you need to do is find the IP address of the machine your c++ code is running on then change 127.0.0.1 to that IP address.

If you're mobile is connected to a wifi router to which your c++ server is connected to, then this IP address will be the local IP address, and everything is simple

If you're mobile is connected to some mobile network, and your server is on a different network, then you need to find out the IP address of your machine exposed to the world (depending on Internet service providers configuration you might have an IP address that remains static, or an IP address that changes every time your connection to the ISP server resets) You can find your machines exposed IP address by going to websites like http://whatismyipaddress.com/ , then if your machine is behind a router, you need to do port forwarding (in this case forward your port 1234 to your machines local IP address) you can take a look at this guide to understand how to do that.

So to avoid the complexity in the 2nd step I advise you to connect your mobile and your server in same local network (i.e your LAN) using a wifi router.

Ways to find the IP address of your machine:

In linux based machines just open a terminal and type ifconfig and look at eth0 your IP address will be right after inet addr:, for example like this inet addr:10.99.123.23

Question:

I need to build a client that initiates a TCP connection with a server and upon response it sends a hand shake request every 10 seconds and gets a response from the server. The server will be able to send another type of request which my client needs to read and act upon. I am using netty 4.0.26.Final.

I have built a client and a dummy server but I am facing an issue which possibly means that there is something I have not understood.

My Client:

    String host = "localhost";
    int port = 9884;
    EventLoopGroup workerGroup = new NioEventLoopGroup();

    try {
        Bootstrap b = new Bootstrap();
        b.group(workerGroup);
        b.channel(NioSocketChannel.class);
        b.option(ChannelOption.SO_KEEPALIVE, true);
        b.handler(new MyChannelPipeline());

        // Start the client.
        ChannelFuture f = b.connect(host, port).sync();

        String line = "line";
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        while (!line.equals("exit")) {
            line = in.readLine();
            if (line == null) {
                break;
            }
        }

        // Wait until the connection is closed.
        f.channel().closeFuture().sync();

    } finally {
        workerGroup.shutdownGracefully();
    }

The ChannelPipleline:

    @Override
public void initChannel(Channel ch) throws Exception {

    ChannelPipeline channelPipeline = ch.pipeline();

    //Encodes every request send from the client to the server
    channelPipeline.addLast("clientRequestEncoder", new ClientRequestEncoder());

    //Implements channelActive and exceptionCaught
    channelPipeline.addLast("initialRequestHandler", new InitialRequestHandler());

    channelPipeline.addLast("byteArrayDecoder", new ByteArrayDecoder());

    channelPipeline.addLast("serverResponseDecoder", new ServerResponseDecoder());
    channelPipeline.addLast("serverRequestDecoder", new ServerRequestDecoder());

    //Reads the responses from the client requests AND
    //reads the inbound requests from the server - Implements channelRead 
    //and exceptionCaught
    channelPipeline.addLast("myResponseHandler", new MyResponseHandler());


}

The problem is that when I flush the response to the server (in MyResponseHandler) and exception is caught in InitialRequestHandler:

ERROR=java.lang.UnsupportedOperationException:unsupported message type: ServerResponse (expected: ByteBuf, FileRegion)

I don't see why the response is not flushed back to the server while the hand shake request is always properly flushed. In both write and flush I have used a ChannelFuture and onOperationComplete this listener f.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); is fired on failure.

Can I use two handlers in the same pipeline or is it bad practise? Moreover how should I fire an unregister event triggered by user input?


Answer:

I solved this using one Handler that overrides channelActive and channelRead and I rearranged the encoders and decoders properly. I also solved the "unregister event triggered by user input" this way:

    String line = "line";
    BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    do {
        logger.info("You typed: " + line + ". Please type 'exit' to terminate the program!");
        line = in.readLine();
    } while (!line.equals("exit"));
    logger.info("You typed: " + line + ". Please wait until the application is successfully shutdown...");

    f.addListener(new ChannelFutureListener() {
        public void operationComplete(ChannelFuture future) throws Exception {
            myChannelPipeline.getMyClientHandler().sendDisconnectRequest(future);
        }
    });

In sendDisconnectReqeust I send the final request and when I get the final response (in channelRead of MyHandler) I call disconnect on the pipeline:

    ChannelPromise cp = new DefaultChannelPromise(ctx.channel());
    ctx.channel().pipeline().disconnect(cp);

However I still have other issues with inbound requests that are never received by my client.

Question:

I have been working with TCP server/client stuff for a while. I am actully good at UDP programming when it comes to connecting more than one user that is multiple clients. I tried to do the same on a TCP server that i made using Threads but whenever the Thread gets to this piece of code

String reader = (String)in.readObject();

an error is generated and the thread stops executing the code but the thread still runs the program keeping it alive. Anyway here is the entire source code :

public class TestServer implements Runnable {

private Thread run, streams, connect, receive, send;

private ServerSocket socket;
private Socket conn;
private ObjectInputStream in;
private ObjectOutputStream out;

private boolean running, incomingMessage = false;
private int port;

public TestServer(int port) throws IOException {

    this.port = port;

    socket = new ServerSocket(port);

    console("Server stated on : " + InetAddress.getLocalHost() + " : " + port);

    run = new Thread(this, "Run");
    run.start();

}

public void run() {

    running = true;
    connect();
    receive();
}

private void connect() {

    connect = new Thread("Connect") {

        public void run() {

            while(running) {

                try {
                    conn = socket.accept();
                } catch (IOException e) {

                    e.printStackTrace();
                }

                console("You are now connected" + conn.getInetAddress().toString() + " : " + conn.getPort());

                try {
                    setupStreams();
                } catch (IOException e) {

                    e.printStackTrace();
                }

            }


        }

    }; connect.start();

}

private void setupStreams() throws IOException {

    streams = new Thread("Streams") {

        public void run() {

            try {

                console("Setting up Streams");

                out = new ObjectOutputStream(conn.getOutputStream());
                out.flush();

                in = new ObjectInputStream(conn.getInputStream());

                console("Streams are now setup");

                incomingMessage = true;
                receive.start();

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

    }; streams.start();



}

private void receive() {

    receive = new Thread("Receive") {

        public void run() {

            while(incomingMessage) {

                String message = "";

                try {

                    message = (String) in.readObject();
                    //This is the only flaw the program

                } catch (ClassNotFoundException | IOException e) {

                    e.printStackTrace();
                }

                console("Client : " + message);
            }
        }

    };
}

private void console(String message) {
    System.out.println(message);
}

public static void main(String[] args) {
    try {
        new TestServer(1234);
    } catch (IOException e) {

        e.printStackTrace();
    }
}

}

FYI am not new to this. The error is caused because the server starts receiving packets even when there are no packets to be received. But because the thread forces it to receive it, i generates the error in the thread and dont know any other way to counter this. So please help. Thanks in Advance.


Answer:

You shouldn't need 2 threads per connection. One thread is all that's required. After the connection is accepted, pass it to a worker thread to start reading. This can be done in a while loop in the worker thread.

Even though the socket's input stream can be read, the ObjectInputStream() class is more sensitive. If there is any error, its state is corrupted and it can't be used.

    while (true) {
        try {
            Object input = in.readObject();
            message = (String) input;
        } catch (IOException e) {
            e.printStackTrace();
            break; //unrecoverable
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            break; //unrecoverable
        }

        console("Client : " + message);
    }

It's a better design to use a specific message protocol instead of sending serialized Java objects. For example if you are sending Strings like your sample, an InputStreamReader can be used to convert bytes to characters more easily and with less error handling.

These resources would be helpful to you:

https://docs.oracle.com/javase/tutorial/networking/sockets/clientServer.html#later

Java - Listening to a socket with ObjectInputStream

ObjectInputStream(socket.getInputStream()); does not work

Question:

I made an app which sends the accelerometer coordinates to my pc.The code for android side client is:

public class MainActivity extends Activity implements SensorEventListener{
private SensorManager senSensorManager;
private Sensor senAccelerometer;
private long lastUpdate = 0;
float x ;
float y ;
float z;
TextView xt,yt,zt;
String st="left";
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    senSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
    senAccelerometer = senSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    senSensorManager.registerListener(this,senAccelerometer,SensorManager.SENSOR_DELAY_NORMAL);
    xt= (TextView) findViewById(R.id.xc);
    yt= (TextView) findViewById(R.id.yc);
    zt= (TextView) findViewById(R.id.zc);
    new SendMsg().execute();
}

public void onSensorChanged(SensorEvent sensorEvent) {
    Sensor mySensor = sensorEvent.sensor;

    if (mySensor.getType() == Sensor.TYPE_ACCELEROMETER) {
      x = sensorEvent.values[0];
      y = sensorEvent.values[1];
      z = sensorEvent.values[2];
        long curTime = System.currentTimeMillis();

        if ((curTime - lastUpdate) > 100) {
            long diffTime = (curTime - lastUpdate);
            lastUpdate = curTime;
            xt.setText(String.valueOf(x));
            yt.setText(String.valueOf(y));
            zt.setText(String.valueOf(z));

         }
    }
}


public void onAccuracyChanged(Sensor sensor, int accuracy) {

}
protected void onPause() {
    super.onPause();
    senSensorManager.unregisterListener( this);
}
protected void onResume() {
    super.onResume();
    senSensorManager.registerListener( this, senAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
}

private class SendMsg extends AsyncTask<String, Void, String> {
    Socket s= null;
    OutputStream os;
    PrintWriter pw;
    @Override
    protected String doInBackground(String... params) {

        try {
            s = new Socket("192.168.0.102",2345);
            os=s.getOutputStream();
            pw=new PrintWriter(os);
            while(true){
                pw.println(x+" "+y+" "+z);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "executed";
    }
    protected void onPostExecute(String result) {

    }
}

and the pc side server code is:

public static void main(String[] args) throws IOException, AWTException {
    ServerSocket ss = new ServerSocket(2345);
    Socket s = ss.accept();
    InputStream is = s.getInputStream();
    InputStreamReader isr = new InputStreamReader(is);
    BufferedReader br = new BufferedReader(isr);
    System.out.println("message received from server is :");
    for (;;) {
        String ms = br.readLine();
        System.out.println("" + ms);

    }

}

Instead of sending the accelerometer coordinates it seems that the app is sending NULL and the same is being printed at the server side.

Despite trying hard i was not able to figure out what the problem is.


Answer:

You are mistaken. TCP cannot 'send null'. The readline() method is returning null, * instead of you receiving data.

The reason is simpy that readLine() returns null at end of stream, and you aren't checking for it. This is clearly stated in the Javadoc. When it returns null, the peer has closed the connection, so you must stop reading and typically close the socket. The usual way to write this is:

while ((line = br.readLine()) != null)
{
    // ...
}

Question:

I'm trying get byte data from tcp client applications, following the documentation of netty project I found this code and I'm implement it into my system:

ServerBootstrap b = new ServerBootstrap();
      b.group(bossGroup, workerGroup)
            .channel(NioServerSocketChannel.class)
            .option(ChannelOption.SO_KEEPALIVE, true)
            .handler(new LoggingHandler(LogLevel.INFO))
            .childHandler(new ChannelInitializer<SocketChannel>() {

                 @Override
                 public void initChannel(SocketChannel ch) throws Exception {
                   ChannelPipeline p = ch.pipeline();
                   p.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(1048576, 0, 4, 0, 4));
                   p.addLast("bytesDecoder", new ByteArrayDecoder());
                   p.addLast(new ServerHandler());

                   }
        }); 

But in my ServerHandler class I'm unable to find and call the method:

void channelRead (ChannelHandlerContext ctx, byte[] bytes){}

instead of the typical:

void channelRead (ChannelHandlerContext ctx, Object msg){}

Thnx in advance!


Answer:

Just do cast...

void channelRead (ChannelHandlerContext ctx, Object msg){
    byte[] bytes = (byte[]) msg;
}

Question:

UPDATE: ok so I kept trying to press send until I received the java.net.SocketException: sendto failed: EPIPE (Broken pipe) exception as a toast message once and then there was no activity once again when I pressed the send button. Meaning I didn't get the exception again.

I have two apps where one acts as the server and the other as a client. I was able to send a message from the server to the client like this

dataOutputStream.writeUTF("hello");

basically as a hardcoded string

but when I added a textfield and a button to the server app and tried listening to the onClick like this

sendChatbtn.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {

                    try {
                        dataOutputStream.writeUTF(chatMsg);
                    } catch (IOException e) {
                        e.printStackTrace();
                        Toast.makeText(ServerActivity.this, "An exception occurred: " + e.toString(), Toast.LENGTH_SHORT).show();
                        // TODO Auto-generated catch block

                    }

                }

                });

Absolutely NOTHING happened when I press the SEND button and the client did not receive any message, I don't even get any exception as a toast. By the way I am able to send messages from the client to the server and the server receives the client's messages but the client doesn't get any messages from the server.

The logcat although shows this:

08-09 04:13:45.694: E/LocSvc_adapter(761): E/virtual loc_api_adapter_err LocApiV02Adapter::injectPosition(double, double, float):632]: error! status = eLOC_CLIENT_FAILURE_INVALID_PARAMETER, inject_pos_ind.status = UNKNOWN

08-09 04:15:25.220: A/ActivityManager(761): Service ServiceRecord{42e78d58 u0 com.estrongs.android.pop/com.estrongs.android.ui.notification.ESTaskService} in process ProcessRecord{449c4320 9734:com.estrongs.android.pop/u0a245} not same as in map: null

08-09 04:16:06.444: E/AudioStreamOutALSA(269): PCM_Write set_amp_mode,1

Here's my Server code:

public class ServerActivity extends Activity {

TextView info, infoip, msg;
String message = "";
ServerSocket serverSocket;
EditText chatBoxText;
Button sendChatbtn, startGameBtn;

Socket socket = null;
DataInputStream dataInputStream = null;
DataOutputStream dataOutputStream = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_server_socket);
    info = (TextView) findViewById(R.id.info);
    infoip = (TextView) findViewById(R.id.infoip);
    msg = (TextView) findViewById(R.id.msg);
    chatBoxText=(EditText) findViewById(R.id.chatBox);
    sendChatbtn=(Button) findViewById(R.id.sendChatButton);
    startGameBtn=(Button) findViewById(R.id.startGamebutton);
    infoip.setText(getIpAddress());

    Thread socketServerThread = new Thread(new SocketServerThread());
    socketServerThread.start();
}

@Override
protected void onDestroy() {
    super.onDestroy();

    if (serverSocket != null) {
        try {
            serverSocket.close();
            closeSockets();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            Toast.makeText(ServerActivity.this, "An exception occurred: " + e.toString(), Toast.LENGTH_SHORT).show();
        }
    }
}

private class SocketServerThread extends Thread {

    static final int SocketServerPORT = 8080;
    int count = 0;

    String chatMsg = chatBoxText.getText().toString();
    @Override
    public void run() {


        try {
            serverSocket = new ServerSocket(SocketServerPORT);
            ServerActivity.this.runOnUiThread(new Runnable() {

                @Override
                public void run() {
                    info.setText("I'm waiting here: "
                            + serverSocket.getLocalPort());
                }
            });

            while (true) {
                socket = serverSocket.accept();
                dataInputStream = new DataInputStream(
                        socket.getInputStream());
                dataOutputStream = new DataOutputStream(
                        socket.getOutputStream());

                String messageFromClient = "";

                //If no message sent from client, this code will block the program
                messageFromClient = dataInputStream.readUTF();

                count++;
                message += "#" + count + " from " + socket.getInetAddress()
                        + ":" + socket.getPort() + "\n"
                        + "Msg from client: " + messageFromClient + "\n";

                ServerActivity.this.runOnUiThread(new Runnable() {

                    @Override
                    public void run() {
                        msg.setText(message);

                    }
                });

                sendChatbtn.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {

                    try {
                        dataOutputStream.writeUTF(chatMsg);
                    } catch (IOException e) {
                        e.printStackTrace();
                        Toast.makeText(ServerActivity.this, "An exception occurred: " + e.toString(), Toast.LENGTH_SHORT).show();
                        // TODO Auto-generated catch block

                    }

                }

                });

            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            Toast.makeText(ServerActivity.this, "An exception occurred: " + e.toString(), Toast.LENGTH_SHORT).show();
            final String errMsg = e.toString();
            ServerActivity.this.runOnUiThread(new Runnable() {

                @Override
                public void run() {
                    msg.setText(errMsg);
                }
            });

        }           

    }




}

private String getIpAddress() {
    String ip = "";
    try {
        Enumeration<NetworkInterface> enumNetworkInterfaces = NetworkInterface
                .getNetworkInterfaces();
        while (enumNetworkInterfaces.hasMoreElements()) {
            NetworkInterface networkInterface = enumNetworkInterfaces
                    .nextElement();
            Enumeration<InetAddress> enumInetAddress = networkInterface
                    .getInetAddresses();
            while (enumInetAddress.hasMoreElements()) {
                InetAddress inetAddress = enumInetAddress.nextElement();

                if (inetAddress.isSiteLocalAddress()) {
                    ip += "SiteLocalAddress: "
                            + inetAddress.getHostAddress() + "\n";
                }

            }

        }

    } catch (SocketException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        ip += "Something Wrong! " + e.toString() + "\n";
        Toast.makeText(ServerActivity.this, "An exception occurred: " + e.toString(), Toast.LENGTH_SHORT).show();
    }

    return ip;
}

public void closeSockets()
{
            try {
                socket.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                Toast.makeText(ServerActivity.this, "An exception occurred: " + e.toString(), Toast.LENGTH_SHORT).show();
            }
            try {
                dataInputStream.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                Toast.makeText(ServerActivity.this, "An exception occurred: " + e.toString(), Toast.LENGTH_SHORT).show();
            }
            try {
                dataOutputStream.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                Toast.makeText(ServerActivity.this, "An exception occurred: " + e.toString(), Toast.LENGTH_SHORT).show();
            }
}

}

Here's the Client Code:

public class ClientActivity extends Activity {

TextView textResponse;
EditText editTextAddress, editTextPort;
Button buttonConnect, buttonClear;

EditText welcomeMsg;
private MyClientTask myClientTask;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_client);
    editTextAddress = (EditText) findViewById(R.id.address);
    editTextPort = (EditText) findViewById(R.id.port);
    buttonConnect = (Button) findViewById(R.id.connect);
    buttonClear = (Button) findViewById(R.id.clear);
    textResponse = (TextView) findViewById(R.id.response);

    welcomeMsg = (EditText)findViewById(R.id.welcomemsg);

    buttonConnect.setOnClickListener(buttonConnectOnClickListener);

    buttonClear.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            textResponse.setText("");
        }
    });
}

OnClickListener buttonConnectOnClickListener = new OnClickListener() {

    @Override
    public void onClick(View arg0) {

        String tMsg = welcomeMsg.getText().toString();
        if(tMsg.equals("")){
            tMsg = null;
            Toast.makeText(ClientActivity.this, "No Welcome Msg sent", Toast.LENGTH_SHORT).show();
        }

        MyClientTask myClientTask = new MyClientTask(editTextAddress
                .getText().toString(), Integer.parseInt(editTextPort
                .getText().toString()),
                tMsg);
        myClientTask.execute();
    }
};


public class MyClientTask extends AsyncTask<Void, Void, Void> {

    String dstAddress;
    int dstPort;
    String response = "";
    String msgToServer;
    Socket socket = null;
    DataOutputStream dataOutputStream = null;
    DataInputStream dataInputStream = null;

    MyClientTask(String addr, int port, String msgTo) {
        dstAddress = addr;
        dstPort = port;
        msgToServer = msgTo;
    }

    @Override
    protected Void doInBackground(Void... arg0) {



        try {
            socket = new Socket(dstAddress, dstPort);
            dataOutputStream = new DataOutputStream(
                    socket.getOutputStream());
            dataInputStream = new DataInputStream(socket.getInputStream());

            if(msgToServer != null){
                dataOutputStream.writeUTF(msgToServer);
            }

            response = dataInputStream.readUTF();

        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            response = "UnknownHostException: " + e.toString();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            response = "IOException: " + e.toString();
        } 
        return null;
    }

    protected void CloseSockets()
    {

                try {
                    socket.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }



                try {
                    dataOutputStream.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }


                try {
                    dataInputStream.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

    }
    @Override
    protected void onPostExecute(Void result) {
        textResponse.setText(response);
        super.onPostExecute(result);
    }


}

protected void onDestroy()
{
    myClientTask.CloseSockets();
    super.onDestroy();
}

}


Answer:

You are not updating the chatMsg string after the onClick, so it initializes as a zero length string, and does not change.

When onClick occurs, you need to get the current string from your TextView:

            @Override
            public void onClick(View v) {
                // add this!!!

                chatMsg = chatBoxText.getText().toString();


                try {
                    dataOutputStream.writeUTF(chatMsg);
                } catch (IOException e) {
                    e.printStackTrace();
                    Toast.makeText(ServerActivity.this, "An exception occurred: " + e.toString(), Toast.LENGTH_SHORT).show();
                    // TODO Auto-generated catch block

                }

            }

Question:

Java(client) and C#(Server) TCP Socket. and Server read infinite last data from client(Java) I has been search for entire day already, its weird.

I created 2 client: Java(real), C#(for testing) like this:

Java(Real):

Socket socket = new Socket(SyncActivity.ip,SyncActivity.port);
DataOutputStream out;
out = new DataOutputStream(socket.getOutputStream());
String s = "Hello!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!$";
out.write(s.getBytes(),0,s.getBytes().length);
out.flush();
s = "Yes this another data$";
out.write(s.getBytes(),0,s.getBytes().length);
out.flush();
socket.shutdownInput();
socket.shutdownOutput();
socket.close();
Thread.currentThread().interrupt();

and C#(for testing)

System.Net.Sockets.TcpClient clientSocket = new System.Net.Sockets.TcpClient();
clientSocket.Connect("192.168.0.138", 11838);
NetworkStream serverStream = clientSocket.GetStream();
byte[] outStream = System.Text.Encoding.ASCII.GetBytes(textBox2.Text + "$");
serverStream.Write(outStream, 0, outStream.Length);
serverStream.Flush();

On C#(testing) side, sent one data to server, and server readed the data once and blocked to wait another data.(second data same as reading it once and blocked)I just want like this.

On Java(Real)side, sent two data to server and server reading 1st data once and read same 2nd data forever. Java side is verified sent only once.

It is full data I was received. Why? its weird.

result as:

on C#(testing)

Client request connection.

Server accept and created connection.

Server try Read (and Blocked)

Client send >> TextBox

Server received >> TextBox

Server try Read (and Blocked)

but on Java(Real):

Client request connection.

Server accept and created connection.

Server try Read (and Blocked)

Client send >> Hello!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Server received >> Hello!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Client send >> Yes this another data

Server try Read

Server received >> Yes this another data

Server try Read

Server received >> Yes this another data

Server try Read

Server received >> Yes this another data

Server try Read

Server received >> Yes this another data

Server try Read

Server received >> Yes this another data

Server try Read

Server received >> Yes this another data

(and forever and forever)

Server code:

    TcpListener serverSocket = new TcpListener(IPAddress.Any, Convert.ToInt16(Ini.IniReadValue("About", "ServerPort", "MVS_VAN.info")));
    TcpClient clientSocket = default(TcpClient);
    serverSocket.Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
    serverSocket.Start();
    clientSocket = serverSocket.AcceptTcpClient();
    serverSocket.Stop();
    NetworkStream networkStream = clientSocket.GetStream();
    byte[] bytesFrom = new byte[128000];
    do
    {
                        Socket soc = clientSocket.Client;
                        soc.Receive(bytesFrom);
                        string dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);
                        dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("$"));
                        MessageBox.Show("", dataFromClient);
                        networkStream.Flush();

                    //networkStream.Read(bytesFrom, 0, (int)clientSocket.ReceiveBufferSize);
                    //string dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);
                    //dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("$"));
                    //tried ^ this 3 line also.

                    } while ((true));
    clientSocket.Close();
    serverSocket.Stop();

Answer:

The server is ignoring the count returned by Receive(). It is therefore (a) ignoring endi of stream and (b) processing invalid data in the buffer.

Question:

I study socket programming, and the example in the book shows:

// SimpleClient.java: A simple client program.
import java.net.*;
import java.io.*;
public class SimpleClient {
  public static void main(String args[]) throws IOException {
    // Open your connection to a server, at port 1254
    Socket s1 = new Socket("localhost",1254);
    // Get an input file handle from the socket and read the input
    InputStream s1In = s1.getInputStream();
    DataInputStream dis = new DataInputStream(s1In);
    String st = new String (dis.readUTF());
    System.out.println(st);
    // When done, just close the connection and exit
    dis.close();
    s1In.close();
    s1.close();
  }
}

My question is that, at line new Socket("localhost",1254), why the address is localhost, instead of the server's IP address?


Answer:

For this particular program it's hard to say exactly why. The usual reason is because the server may not even have another IP address. If it's local, then accessing it through "localhost" or "127.0.0.1" is guaranteed to work even if you have no NICs at all.

Another possible reason is security. Your machine may have multiple NICs, but the server may be configured to only listen on the loopback interface and therefore accept only local connections. If it isn't intended for external use at all, this is usually the best thing to do because the potential attacker will have a very hard time connecting it through an interface it isn't even listening on! They will have to break into the system using some other way first.

Question:

I have a tested server on ESP8266 with loopback and a tcp client app that doesn't send messages. I also tested it on a server that tells you if there is somebody connected and it says that it connects.

The "chat" textView shows the message when I click send.

For example: Client: message, but it doesn't send it to the server for it to loop it back.

What should I change for it so send and receive messages?

Client

package com.example.tinemasilo.researchgate_sockettut;

import android.app.Activity;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.Socket;

public class MainActivity extends Activity
{

static EditText serverIp,smessage;
static TextView chat;
static Button connectPhones,disconnectPhones,sent;
static String serverIpAddress = "",msg = "",str;
Handler handler = new Handler();
//static InetAddress serverAddr;
static Socket socket;
static DataOutputStream os;
//static DataInputStream in;
static BufferedReader in;



@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    chat = (TextView) findViewById(R.id.chat);
    serverIp = (EditText) findViewById(R.id.server_ip);
    smessage = (EditText) findViewById(R.id.smessage);

    sent = (Button) findViewById(R.id.sent_button);
    connectPhones = (Button) findViewById(R.id.connectPhones);
    disconnectPhones = (Button) findViewById(R.id.disconnectPhones);

    connectPhones.setEnabled(true);
    connectPhones.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
            connectPhones.setEnabled(false);
            disconnectPhones.setEnabled(true);
            serverIpAddress = serverIp.getText().toString();
            //try
            //{
            //    InetAddress.getByName(serverIpAddress);
            //    serverAddr.getByName(serverIpAddress);
            //    socket = new Socket(serverAddr, 10000);
            //}
            // catch (IOException e)
            //{
            //}

            if (!serverIpAddress.equals(""))
            {
                Thread clientThread = new Thread(new ClientThread());
                clientThread.start();
            }

        }
    });

    sent.setOnClickListener(new View.OnClickListener()
     {
        public void onClick(View v)
        {
             Thread sentThread = new Thread(new sentMessage());
             sentThread.start();
         }
     });

      disconnectPhones.setEnabled(false);
      disconnectPhones.setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View v)
         {
            connectPhones.setEnabled(true);
            disconnectPhones.setEnabled(false);
                try
                {
                 socket.close();
                }
                catch (IOException e)
                {
                }
          }
      });
}

public class ClientThread implements Runnable
{
    public void run()
    {
        try
        {

            InetAddress serverAddr = InetAddress.getByName(serverIpAddress);
            //serverAddr.getByName(serverIpAddress);
            socket = new Socket(serverAddr, 502);


            while(true)
            {
                //InetAddress serverAddr = InetAddress.getByName(serverIpAddress);
                //serverAddr.getByName(serverIpAddress);
                //socket = new Socket(serverAddr, 10000);
                //in = new DataInputStream(socket.getInputStream());
                in = new BufferedReader( new InputStreamReader(socket.getInputStream()));
                String line = null;
                while ((line = in.readLine()) != null)
                {
                    msg = msg + "Server : " + line + "\n";
                    handler.post(new Runnable()
                    {
                        @Override
                        public void run()
                        {
                            chat.setText(msg);
                        }
                    });
                }
                in.close();
                Thread.sleep(100);
            }
        }
        catch (Exception e)
        {
        }
    }
}

class sentMessage implements Runnable
{
    @Override
    public void run()
    {
        try
        {

            InetAddress serverAddr = InetAddress.getByName(serverIpAddress);
            //serverAddr.getByName(serverIpAddress);
            socket = new Socket(serverAddr, 502);

            os = new DataOutputStream(socket.getOutputStream());
            str = smessage.getText().toString();
            str = str + "\n";
            msg = msg + "Client : " + str;
            handler.post(new Runnable()
            {
                @Override
                public void run()
                {
                    chat.setText(msg);
                }
            });
            os.writeBytes(str);
            os.flush();
            os.close();
            }
        catch(IOException e)
        {
        }
    }
}
}

Answer:

You are trying to create a new Socket connection on same port in sentThread. First connection is created in ClientThread class and when you are pressing sent button you are creating another Socket connection on same port 502. I think that's is the main problem.

Try to use existing Socket connection in sentThread class.

class sentMessage implements Runnable
{
  @Override
  public void run()
  {
    try
    {

        //InetAddress serverAddr = InetAddress.getByName(serverIpAddress);
        //serverAddr.getByName(serverIpAddress);
       // socket = new Socket(serverAddr, 502);

       // os = new DataOutputStream(socket.getOutputStream());
        str = smessage.getText().toString();
        str = str + "\n";
        msg = msg + "Client : " + str;
        handler.post(new Runnable()
        {
            @Override
            public void run()
            {
                chat.setText(msg);
            }
        });
        os.writeBytes(str);
        os.flush();
        //os.close();
        }
    catch(IOException e)
    {
    }
}
}

Edit: You you want to send multiple message then don't close DataOutputStream. Remove os.close(); and os = new DataOutputStream(socket.getOutputStream()); line from sentMessage class. Initialize your os when you are connecting first time. Then every time you want to send message use that os instance.

In ClientThread class initialize os after connection created

   socket = new Socket(serverAddr, 502);
   os = new DataOutputStream(socket.getOutputStream());

Question:

I have a GUI TCP server written in C# which listens in 4444 port and a GUI java client which connects to 4444 port. I can send message from client to server and server side text field is set with message but when I send message from server to client no message is shown in the client's text field(also no result in console). Need help.

--Code for sending msg from server to client----- C#

 private void button1_Click(object sender, EventArgs e)
    {
        String outmsg = textBox1.Text;

        textBox1.Text = "";
        byte[] bytes = Encoding.ASCII.GetBytes(outmsg);


        String Msg = Encoding.ASCII.GetString(bytes);
        richTextBox1.AppendText("\n\n" + Msg);


        networkStreamData.Write(bytes, 0, bytes.Length); //NetworkStream


        bytes = new byte[1024];   //For clearing the buffer



    }

----Java client code-----

 public void run () throws IOException
{
    Socket socket = new Socket ("127.0.0.1", 4444);
    BufferedReader in = new BufferedReader (new InputStreamReader (socket.getInputStream ()));
    out = new PrintWriter (socket.getOutputStream (), true);

    String inputLine;

    while ((inputLine = in.readLine ()) != null)
    {
        System.out.println ("Client <  " + inputLine);
        rxArea.setText (inputLine);
    }

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

Note: COMMUNICATION IS WORKING FINE BETWEEN CLIENT AND SERVER, ONLY PROBLEM BETWEEN SERVER AND CLIENT.

Updates:- I Closed the Network Stream and It worked!!! But as I have another child thread running within the server to listen for incoming stream, so when I close the network stream it throws an exception and stop execution.


Answer:

Readline() needs '\n' as a message termination.As there was no termination in the sent message readline kept on reading and message wasn't set.

Question:

I have a question:

I had created a client app in Android Studio, and I need to know if it will work if the server was on Windows as a GUI program using Java.

so if the server was made using java in GUI on Windows and the client as a app on a Android smartphone... Will they connect successfully to each other?


Answer:

If both client and server comply with TCP protocol, they can interact with each other regardless of their underlying platforms, because all network protocols have their own principles and rules which must be obeyed by all platforms using them.

Also you shouldn't worry about medium-level byte ordering, because network has its own endianness which is big-endian and in various platforms they first convert their data to this endianness before sending it over medium. All these stuff are handled at OS level and you're not supposed to take care of them.

Question:

I'm trying to change my game to use TCP, but I can't even get it to work. The client connects successfully with the server, but for some reason I can't receive messages from server nor receive messages from client. My guess is that I'm doing something wrong with the output/input?

Here is the server code:

public class Server implements Runnable {
    Server() {
        serverSocket = new ServerSocket(1919, 300);
    }

    run() {
        while (true) {
            String message = "blank";
            try {

                //w8ting for some connection
                tcpSOCKET = tcpServer.accept(null);
                //Connected to some1!
                input = new BufferedReader(new InputStreamReader(
                        tcpSOCKET.getInputStream()));
                output = new DataOutputStream(
                        tcpSOCKET.getOutputStream());
                output.flush();

                //TODO PROBLEM it stays here trying to read line but even if the  client send a message it wont move on
                message = input.readLine();
                main.addLabel(Color.BLUE, message);

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

And this is the client:

public class Client implements Runnable {

    Client() { }

    run() {
        String message = "";
        try {
            tcpSOCKET = new Socket(serverIp, serverTCPport);
            input = new BufferedReader(new InputStreamReader(
                    tcpSOCKET.getInputStream()));
            output = new DataOutputStream(tcpSOCKET.getOutputStream());
            output.flush();

            while (true) {
                System.out.println("w8ting for message from server");
                //TODO problem, it wont read anything even if the server send a message
                message = input.readLine();

                System.out.println("A message has arrived: " + message);
                gameScreen.serverMessage = message;
            }
        } catch (EOFException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

and the class is called when I hit "s" in the server or in the client, they both use the same class

public void sendTCPMessage(String message) {
    try {
        output.writeBytes(message);
        output.flush();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Answer:

  • If you want to read lines, you must write lines.
  • If you want to read with a BufferedReader, you should write with a BufferedWriter.
  • If you want to write with a DataOutputStream, you should read with a DataInputStream.

Question:

Here is the code of a Client:

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;



public class Client_TCP {

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

    Socket client_socket = new Socket("127.0.0.1", 1025);

    DataOutputStream os = new DataOutputStream(client_socket.getOutputStream());
    os.writeBytes("Hi Server, I'm the Client. How are you?");

    BufferedReader br = new BufferedReader(new InputStreamReader(client_socket.getInputStream()));

    String line = new String("");
    String supportLine=new String("");

    while((line=br.readLine()) != null)
    supportLine = line;

    System.out.println(supportLine);

    os.close();
    br.close();
    client_socket.close();

    }

}

Here is the code of the server which we will connect the client above:

import java.io.BufferedReader;  
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;



    public class ServerTCP {

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

        ServerSocket server_Socket = new ServerSocket();
        server_Socket.bind(new InetSocketAddress(1025));

        Socket welcomeSocket = server_Socket.accept();
        System.out.println("Connection done on: " + welcomeSocket.getPort());

        BufferedReader br = new BufferedReader(new InputStreamReader(welcomeSocket.getInputStream()));

        String line= new String("");
        String supportLine = new String("");

        while((line=br.readLine()) != null ) {

            supportLine=supportLine + line; 
        }

        System.out.println(supportLine);

        DataOutputStream os = new DataOutputStream(welcomeSocket.getOutputStream());
        os.writeBytes("I'm fine thanks! And you?");

        br.close();
        os.close();
        welcomeSocket.close();          
    }

}

As you can see the Client sends the message: "Hi Server, I'm the Client. How are you?" The Server receives the message and replay:"I'm fine thanks! And you?". Client's message arrives to the Server rightly. But, Server's message, instead, does not arrive to the Client.

I need your help to fix this problem. Can you help me?

Thank you, bye.


Answer:

First, you should flush the OutputStream after sending the data if you expect to read/write immediately:

os.flush();

Second, see the API for BufferedReader

Reads a line of text. A line is considered to be terminated by any one of a line feed ('\n'), a carriage return ('\r'), or a carriage return followed immediately by a linefeed.

Since your Client (and Server) is not sending the end of line character the Server (and Client) may block trying to read the Line. Include this when sending the data if the server (and/or client) expects it.

Question:

So I have a java TCP server and client.The client is trying to register a user to the server.I can see that the user is being added on the server from my print statement but my client is not recieving the "User was added,try logging in" message.

Server

class Server implements Runnable
{
Socket connectionSocket;
    UserRepo userRepo;
    public static final String COMMAND_SEPARATOR = "%%";

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{

               String recievedMessage="";
            BufferedReader reader =
                    new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
            BufferedWriter writer= 
                    new BufferedWriter(new OutputStreamWriter(connectionSocket.getOutputStream()));

                    while(!recievedMessage.equalsIgnoreCase("exit")){
            recievedMessage = reader.readLine().trim();
                    String [] components = recievedMessage.split(COMMAND_SEPARATOR);
                    if(components[0].equals("register")){
                        User user= userRepo.addUser(components[1], components[2]);
                        if(user==null){
                            writer.write("\r\n=== User wasnt added,"
                                    + "mayby there is already an account for that email? " );
            writer.flush();
                        }else{
                                writer.write("\r\n=== User was added,try logging in");
                                System.out.println("user added");
            writer.flush();
                        }
                    }


            recievedMessage="";
                    recievedMessage = reader.readLine().trim();
                    }
            connectionSocket.close();
    }catch(Exception e){e.printStackTrace();}
}

 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();

     }
  }
 }

Client

    import java.io.IOException;
     import java.io.PrintWriter;
   import java.net.Socket;
  import java.util.Scanner;
 import java.util.logging.Level;
 import java.util.logging.Logger;


     public class ClientShell {
   public static final String COMMAND_SEPARATOR = "%%";
/**
 * @param args the command line arguments
 */
public static void main(String[] args) {
    try {
        User loggedInUser = null;
        String message = "";
        String response = null;
        Scanner keyboard = new Scanner(System.in);

        // 1) Build data socket for client to use
        Socket serverLink = new Socket("localhost", 5555);

        // 2) Set up streams
        // PrintWriter used for sending messages
        PrintWriter output = new PrintWriter(serverLink.getOutputStream());
        // Scanner / BufferedReader used for receiving messages
        Scanner input = new Scanner(serverLink.getInputStream());

        // 3) While we want still want to exchange messages
        while(!message.equalsIgnoreCase("exit"))
        {
            while(loggedInUser==null){
                notLoggedInOptions(keyboard,message,response,loggedInUser,output,input);
            }


        }
        // 8) Close the link to the server (the data socket)
        serverLink.close();
    } catch (IOException ex) {
        Logger.getLogger(ClientShell.class.getName()).log(Level.SEVERE, null, ex);
    }
}

public static void notLoggedInOptions(Scanner keyboard,String message,String response,User loggedInUser,
                                PrintWriter output,Scanner input){
    System.out.println("Type login for login or register for register");
                message = keyboard.nextLine();
                if(message.equalsIgnoreCase("login")){

                }else if(message.equalsIgnoreCase("register")){
                    message="";
                    boolean validUserName = false;
                    while(validUserName == false){
                    System.out.println("Type the username you want as your prefix for your email");
                    System.out.println("It must be between 5 and 10 characters");
                    System.out.println("eg type mgraham if you want mgraham@danielhaughton@haughton.com");
                    message = keyboard.nextLine();
                    if(message.length()>4 && message.length()<11 == true){
                        validUserName = true;
                    }else{
                        System.out.println("It must be between 5 and 10 characters try again" );
                    }
                    }
                    String username = message;
                    message="";
                    boolean validPassword = false;
                    while(validPassword == false){
                        System.out.println("Type the password you want");
                    System.out.println("It must be atleast 8 characterrs");
                    message = keyboard.nextLine();
                    if(message.length()> 7){
                        validPassword = true;
                    }else{
                        System.out.println("It must be atleast 8 characterrs,try again");
                    }
                    }
                    String password = message;
                    System.out.println("username:" + username);
                    System.out.println("password:" + password);
                    output.println("register"+ COMMAND_SEPARATOR + username + COMMAND_SEPARATOR + password);
                    output.flush();
                    response = input.nextLine();
                    System.out.println(response);
                }else{
                    System.out.println("Unsupported command!try again");
                }
   }

 }

`

My output on the client

Type login for login or register for register

register

Type the username you want as your prefix for your email

It must be between 5 and 10 characters

eg type mgraham if you want mgraham@danielhaughton@haughton.com

daniel

Type the password you want

It must be atleast 8 characterrs

hello12345

username:daniel

password:hello12345

blank line is printed here

Type login for login or register for register


Answer:

Well, look at what your server sends back:

writer.write("\r\n=== User was added,try logging in");

So, it sends an empty line, followed by === User was added,try logging in. So, since the client reads the next line, and the next line received is an empty line, the output is what you should expect.

If you expect the message to be printed, the server should use

writer.write("=== User was added,try logging in\r\n");

Question:


Answer:

You are trying to perform a network operation on main thread.Try running it on background thread using asyntask or by creating a separate thread whichever you prefer and the issue will be gone.

A not so good method is to use

StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();

StrictMode.setThreadPolicy(policy); 

For a better reference see This answer

Question:

My question is how do i send an UDP message for an array with a list of IP's connected to the server in TCP sockets?

the code i did (just the server application, the sending part):

DatagramSocket socketCliente = new DatagramSocket();       
InetAddress[] IP = InetAddress.getAllByName(socketLigacao.getInetAddress().getHostAddress());   
byte[] enviaMensagem = new byte[1024];        
enviaMensagem = mensagemCliente.getBytes();
for (int i = 0; i < IP.length; i++){
DatagramPacket enviaPacote = new DatagramPacket(enviaMensagem, enviaMensagem.length, IP[i],     3790);
socketCliente.send(enviaPacote)

The code i did are just working in localhost (tested in netbeans output), when I run in different machines the client don't show any output, and i'm sure that the problem is in this part of code that i posted...

Any help would be apreciated, if tou need any more information please let me know.

Cheers!


Answer:

Your code is correct. The problem is with the networking.

In your current code, you are trying to send UDP packets to several clients at their corresponding IP addresses and a port (3790).

This worked while you were on localhost as the client IP and port were not mapped to a different one. While you were on the local host, you simply played with the local IP and a local port to the machine.

In practical scenario, things are different. The clients are connected to a router, and precisely a firewall between the internet and your client.

The router creates a mapping to reach out the client machine. The local IP and port of the client are mapped to the external IP (the IP which the router gets by the ISP) and an external port(which identifies the client process). The local IP and port are allotted by the router to the client. This is called Network Address Translation(NAT).

The router maintains a routing table to route the packets from source to destination.

By default, it allows all TCP packets to enter or leave the system after a successful connection.

But in case of UDP packets, the router allows only outgoing packets(packets leaving the network to some other network) and blocks the incoming packet.

It allows UDP packets only from those address to enter the network, to which a packet was sent by the client earlier(as sending a packet creates an entry in the router table). In other words, the router allows only those packets whose IP and port entry is available in the routing table.

Example:

Consider a client machine "A" connected to a router. Let the router has an external IP w.x.y.z provided by the ISP. When the client initiates a UDP packet, let the router assign it an external port say 55000. To reach the client machine, the router will allot it a local IP say 192.168.1.62 and some port 3790(or define by the client process). The router creates a mapping of this internal or local IP and port to the external IP and port respectively. This can be a possible mappding:

External IP:port    <-------------->    Local IP:port

   w.x.y.z:55000    <-------------->    192.168.1.62:3790

This depends on the type of NAT scheme the router uses. So, in order to let the clients receive packets from some machine external to the network, the machine on the other side must send the packets to the external IP and port of the client allotted by the router while initiating the UDP packet. The router will then forward it to the local IP and port of the client.

In your case, you are sending packets but these packets are blocked by the router which comes in between the internet and the client. You need to send packets to the external IP and port of the client.

You will need to implement UDP hole punching for this. Although it does not guarantee to work on all types of NAT.

Or better to say that please read more about networking conditions, about how these mappings are done in the router, etc.

Here are some of the sources:

Network Address Translation

UDP Hole Punching

RFC 4787 NAT Behavioral Requirements UDP

RFC 5128 P2P across NAT

Question:

I'm trying to set the client that will open the connection and will listen for new data available

But actually if the data is not available instantly or like with a delay of some ms my app give the following error:

> 07-27 08:50:09.732 27021-27153/com.example.sguidetti.selfmanegment
> E/TCP Client: C: Connecting... 07-27 08:50:09.802
> 27021-27153/com.example.sguidetti.selfmanegment E/SERVER: S: ONLINE
> 07-27 08:50:09.803 27021-27153/com.example.sguidetti.selfmanegment
> E/RESPONSE FROM SERVER: S: Received Message: '3' 07-27 08:50:11.424
> 27021-27021/com.example.sguidetti.selfmanegment V/Monotype:
> SetAppTypeFace- try to flip, app = com.example.sguidetti.selfmanegment
> 07-27 08:50:11.424 27021-27021/com.example.sguidetti.selfmanegment
> V/Monotype:     Typeface getFontPathFlipFont - systemFont =
> default#default 07-27 08:50:11.698
> 27021-27180/com.example.sguidetti.selfmanegment E/TCP Client: C:
> Connecting... 07-27 08:50:14.127
> 27021-27180/com.example.sguidetti.selfmanegment E/TCP: S: Error
>                                                                           java.net.SocketException: recvfrom failed: ECONNRESET (Connection
> reset by peer)
>                                                                               at libcore.io.IoBridge.maybeThrowAfterRecvfrom(IoBridge.java:592)
>                                                                               at libcore.io.IoBridge.recvfrom(IoBridge.java:556)
>                                                                               at java.net.PlainSocketImpl.read(PlainSocketImpl.java:485)
>                                                                               at java.net.PlainSocketImpl.access$000(PlainSocketImpl.java:37)
>                                                                               at
> java.net.PlainSocketImpl$PlainSocketInputStream.read(PlainSocketImpl.java:237)
>                                                                               at java.io.InputStreamReader.read(InputStreamReader.java:231)
>                                                                               at java.io.BufferedReader.fillBuf(BufferedReader.java:145)
>                                                                               at java.io.BufferedReader.readLine(BufferedReader.java:397)
>                                                                               at com.example.sguidetti.selfmanegment.Client.run(Client.java:95)
>                                                                               at
> com.example.sguidetti.selfmanegment.help$ConnectTask.doInBackground(help.java:127)
>                                                                               at
> com.example.sguidetti.selfmanegment.help$ConnectTask.doInBackground(help.java:112)
>                                                                               at android.os.AsyncTask$2.call(AsyncTask.java:288)
>                                                                               at java.util.concurrent.FutureTask.run(FutureTask.java:237)
>                                                                               at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
>                                                                               at
> java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
>                                                                               at
> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
>                                                                               at java.lang.Thread.run(Thread.java:818)
>                                                                            Caused by: android.system.ErrnoException: recvfrom failed: ECONNRESET
> (Connection reset by peer)
>                                                                               at libcore.io.Posix.recvfromBytes(Native Method)
>                                                                               at libcore.io.Posix.recvfrom(Posix.java:161)
>                                                                               at libcore.io.BlockGuardOs.recvfrom(BlockGuardOs.java:250)
>                                                                               at libcore.io.IoBridge.recvfrom(IoBridge.java:553)
>                                                                               at java.net.PlainSocketImpl.read(PlainSocketImpl.java:485) 
>                                                                               at java.net.PlainSocketImpl.access$000(PlainSocketImpl.java:37) 
>                                                                               at
> java.net.PlainSocketImpl$PlainSocketInputStream.read(PlainSocketImpl.java:237) 
>                                                                               at java.io.InputStreamReader.read(InputStreamReader.java:231) 
>                                                                               at java.io.BufferedReader.fillBuf(BufferedReader.java:145) 
>                                                                               at java.io.BufferedReader.readLine(BufferedReader.java:397) 
>                                                                               at com.example.sguidetti.selfmanegment.Client.run(Client.java:95) 
>                                                                               at
> com.example.sguidetti.selfmanegment.help$ConnectTask.doInBackground(help.java:127) 
>                                                                               at
> com.example.sguidetti.selfmanegment.help$ConnectTask.doInBackground(help.java:112) 
>                                                                               at android.os.AsyncTask$2.call(AsyncTask.java:288) 
>                                                                               at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
>                                                                               at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231) 
>                                                                               at
> java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) 
>                                                                               at
> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) 
>                                                                               at java.lang.Thread.run(Thread.java:818)  07-27 08:50:14.130
> 27021-27217/com.example.sguidetti.selfmanegment E/TCP Client: C:
> Connecting...

For my TCP Client i've used the following GUIDE by just adding in the TCPClient.class the following string mRun = false; under the mMessageListener.messageReceived(mServerMessage);

For testing i've just added a Thread.Sleep(2000) in my TCP Server made in VB before it will make the data available whyle the 1st data at the start is getting fine because is without any delay.

Here is my activity where i use the TCP Client for the 2nd time and where it give the error if there is some delay:

Start client function that repeat it x times

    public void startClient(){
    for(int i=0; i< Integer.valueOf(MainActivity.SelfNumber); i++) {


        new ConnectTask().execute("");

        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }


        client.sendMessage("C" + Integer.valueOf(i+1));

    }
}

And here is my AsyncTask where i decode the text sent by the Server and put it in a RecyclerView

    public class ConnectTask extends AsyncTask<String, String, Client> {

    @Override
    protected Client doInBackground(String... message) {


        client = new Client(new Client.OnMessageReceived() {
            @Override

            public void messageReceived(String message) {

                publishProgress(message);

            }
        });
        client.run();

        return null;
    }

    @Override
    protected void onProgressUpdate(String... values) {
        super.onProgressUpdate(values);


        StringTokenizer stringTokenizer = new StringTokenizer(values[0], "#");
        nCassa = stringTokenizer.nextToken();
        status = stringTokenizer.nextToken();
        receipt = stringTokenizer.nextToken();
        eur = stringTokenizer.nextToken();

        adapter = new SelfAdapter("CASSA SELF N° " + nCassa, "EUR: " + eur, "SC: " + receipt, help.img);
        selfList.add(help.adapter);
        adapterView.notifyDataSetChanged();


        }

    }

EDIT Actually there is no delay at the 1st Client-Server Connection so as you can see in the screenshot the server got the IP string from the client and the client got number 3, but when i run another activity where i open another time the connection and the response from the server has a delay you can see in the screen what is happening, and the Server got also CS1 string from the Client when it had to be on delay...


Answer:

You are getting error message "ECONNRESET" which means either server is rejecting the connection or the firewalls in between client or server are blocking the connection. In either case you have to fist check server logs.If server is refusing with some reason ,you will get that in server logs. If server is not resetting the connection which means at server there is no entry of ur connection, In that case u should try from open network and if it works the try tuning the firewall for allowing required ports or IP.

You can take help from the link Getting "SocketException : Connection reset by peer" in Android