I want to make a simple Netty Server and I have the basic Server/Client code, but I have a problem. How do I write to the server from outside the Client Main class?
HereĀ“s the code:
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public final class ChatClient {
static final String HOST = System.getProperty("host", "127.0.0.1");
static final int PORT = Integer.parseInt(System.getProperty("port", "8992"));
public static void main(String[] args) throws Exception {
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap b = new Bootstrap();
b.group(group)
.channel(NioSocketChannel.class)
.handler(new ChatClientInitializer());
Channel ch = b.connect(HOST, PORT).sync().channel();
ChannelFuture lastWriteFuture = null;
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
for (;;) {
String line = in.readLine();
if (line == null) {
break;
}
// WRITE TO SERVER, HOW DO I CALL THIS OUTSIDE FROM THIS CLASS TO WRITE TO THE SERVER?
lastWriteFuture = ch.writeAndFlush(line + "\r\n");
}
if (lastWriteFuture != null) {
lastWriteFuture.sync();
}
} finally {
group.shutdownGracefully();
}
}
}
As noted in the comments, I want to send messages to the Server from outside this class. How can I do that?
Best Regards,
Alex
You can just make the Channel accessible from the outside by expose it via a getter and use it. Channel is thread safe and so can be used from any thread.
Related
Hi programmer all over the world
In order to understand what's the difference between Concurrency vs Parallelism, I was given this problem to solve but I fall off in this problem that I couldn't solve and it took me a lot of time , so I came here and I home someone could help me .
I have a problemm here I have built a program that has 4 classes , 2 of them are "Client" (Agsrq to send generates squares numbers and AgFibo so send sequence of number of fibonacci) used to send number to the server (agclassserver recieve data from Agsqr and Agfibo to order and display them in form of list ) , and I add other class to make server accepts many clients (Multithreading) in this case ,Agsqr and AgFibo are taking the role of client.
So here is my problem , when I execute the classes (agclassserver "server" , Agsqr & AgFibo "Clients") the result is giving me only the fist client lets say "Agsqr" and when I execute the AgFibo it doesn't executes but it gives me another execution of Agsqr "so I have the result of two Agsqr "
Here is all the class I vae used in this program
Agclassserver
package smatp2;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Collections;
import java.util.concurrent.*;
public class agclassserver {
public static void main(String[] args) throws IOException, InterruptedException {
// TODO Auto-generated method stub
ArrayList<Integer> array = new ArrayList<Integer>();
ArrayList<ClassesHandler> classes_handler = new ArrayList<ClassesHandler>();
ExecutorService service= Executors.newFixedThreadPool(10);
boolean var=true;
int message;
try {
while(true) {
ServerSocket server = new ServerSocket(9090);
System.out.println("I waiting for the client ");
Socket socket = server.accept();// waiting for client to connect with server
ClassesHandler client = new ClassesHandler(socket);
classes_handler.add(client);
service.execute(client);
}
}catch (Exception e) {
}
}
}
Agsqr
package smatp2;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
public class Agsqr {
public static void main(String[] args) throws IOException, InterruptedException {
// TODO Auto-generated method stub
try {
Socket socket = new Socket ("localhost", 9090);
int n=0;
OutputStream output = socket.getOutputStream();
DataOutputStream stream = new DataOutputStream(output);
while(true) {
int result = n*n;
stream.writeInt(result);
n++;
Thread.sleep(1000);
}
}catch(Exception e) {
}
}
}
AgFibo
package smatp2;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class AgFibo extends Thread {
public synchronized void run() {
}
public static void main(String[] args) throws UnknownHostException, IOException, InterruptedException {
// TODO Auto-generated method stub
try {
int number ;
int previousNumber = 0;
int nextNumber = 1;
boolean variable=false ;
Socket socket = new Socket ("localhost", 9090);
int n=0;
OutputStream output = socket.getOutputStream();
DataOutputStream stream = new DataOutputStream(output);
while(!variable){
stream.writeInt(previousNumber);
int sum = previousNumber + nextNumber;
previousNumber = nextNumber;
nextNumber = sum;
Thread.sleep(1000);
}
}catch(Exception e) {
}
}
}
ClassesHandler
package smatp2;
import java.io.*;
import java.net.*;
import java.util.ArrayList;
import java.util.Collections;
public class ClassesHandler implements Runnable {
private Socket socket;
private int message;
ArrayList<Integer> array = new ArrayList<Integer>();
private DataInputStream dataInputStream;
public ClassesHandler(Socket socket) throws IOException{
this.socket = socket;
dataInputStream = new DataInputStream(socket.getInputStream());
}
#Override
public void run() {
// TODO Auto-generated method stub
try {
while(true) {
message = dataInputStream.readInt();
array.add(message);// waiting for client to connect with server
Collections.sort(array);
System.out.println(message);
System.out.println(array);
//Thread.sleep(500);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
agclassserver /* Sorry I forgot to post the classserver Class */
package smatp2;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Collections;
import java.util.concurrent.*;
public class agclassserver {
public static void main(String[] args) throws IOException, InterruptedException {
// TODO Auto-generated method stub
ArrayList<Integer> array = new ArrayList<Integer>();
ArrayList<Integer> arraySQR = new ArrayList<Integer>();
ArrayList<Integer> arrayFibo = new ArrayList<Integer>();
ArrayList<ClassesHandler> classes_handler = new ArrayList<ClassesHandler>();
ExecutorService service= Executors.newFixedThreadPool(10);
boolean var=true;
int message;
try {
ServerSocket server = new ServerSocket(9090);
while(true) {
System.out.println("I waiting for the client ");
Socket socket = server.accept();// waiting for client to connect with server
String hostName = socket.getInetAddress().getHostName();
ClassesHandler client = new ClassesHandler(socket,array,arraySQR,arrayFibo,hostName);
classes_handler.add(client);
service.execute(client);
}
}catch (Exception e) {
}
}
}
Concurrent vs Parallel.
Imagine you need to get a new passport and you need to prepare a presentation for work.
Not parallel and not concurrent: first you go get your passport and then you prepare a presentation.
Not parallel, but concurrent: you go to the embassy and wait on a chair for you turn. While you are waiting, you work on your presentation. As soon as it is your turn, you close your laptop and fill in the passport papers and later you will complete your presentation.
Parallel and concurrent: you go work on your presentation while you send your wife/husband to the embassy to get your passport.
There is also a possibility to do parallel and not concurrent. But that doesn't fit with the above example. And example would calculating the sum of 2 huge integer arrays. Using SIMD multiple integer adds can be executed in parallel, but there is no concurrency since there is just a single request.
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.epoll.EpollChannelOption;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.epoll.EpollServerSocketChannel;
import io.netty.channel.socket.SocketChannel;
import sun.misc.Signal;
import sun.misc.SignalHandler;
import java.net.InetSocketAddress;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
public class ReusePortServer {
private final int port;
private List<Channel> bindingChannels = new LinkedList<>();
public ReusePortServer(int port) {
this.port = port;
}
private void initSignals() {
Signal.handle(new Signal("BUS"), new SignalHandler() {
#Override public void handle(Signal signal) {
System.out.println("signal arrived");
closeChannels();
}
});
}
synchronized private void closeChannels() {
for (Channel channel : bindingChannels) {
channel.close();
}
bindingChannels.clear();
}
synchronized private void registerChannel(Channel channel) {
bindingChannels.add(channel);
}
public void start() throws Exception {
initSignals();
EventLoopGroup group = new EpollEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(group)
.channel(EpollServerSocketChannel.class)
.option(EpollChannelOption.SO_REUSEPORT, true)
.localAddress(new InetSocketAddress(port))
.childHandler(new ChannelInitializer<SocketChannel>(){
#Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new ReusePortHandler());
registerChannel(ch);
}
});
for (StackTraceElement e : Thread.currentThread().getStackTrace()) {
System.out.println(e.toString());
}
ChannelFuture f = b.bind().sync();
log(String.format("%s started and listen on %s", ReusePortServer.class.getName(), f.channel().localAddress()));
// registerChannel(ch); // ---------------I also tried to register this channel, but after my signaling, it closes my client's connection, rather than keeping it.
f.channel().closeFuture().sync();
} finally {
group.shutdownGracefully().sync();
}
}
private final static SimpleDateFormat datefmt = new SimpleDateFormat("HH:mm:ss ");
public static void log(final String msg) {
System.out.print(datefmt.format(new Date()));
System.out.println(msg);
System.out.flush();
}
public static void main(final String[] args) throws Exception {
int port = 12355;
new ReusePortServer(port).start();
}
}
Hi, I am looking a way to stop netty from listening and accepting on server socket, but to finish up any ongoing job on current connections.
I come across the following question:
How to stop netty from listening and accepting on server socket
and according to it, I wrote the above code, which receive signal (kill -7) to do the closing.
But the result is not expected, it closes the tcp connections, and netty can still accept new connection.
Do I use the correct way of stop netty from listening and accepting?
What's wrong here?
You should close the ServerChannel like this:
ChannelFuture f = b.bind().sync();
// Call this once you want to stop accepting new connections.
f.channel().close().sync();
I've spent about two days about this problem. I try this, and it work for me :
First, I declare:
static ChannelFuture future;
Then, when I bind port, I assign future variable:
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ServerInitializer())
.option(ChannelOption.SO_BACKLOG, NetUtil.SOMAXCONN)
.childOption(ChannelOption.SO_KEEPALIVE, true);
future = b.bind(WS_PORT).sync();
Final, I add a function to handler event when web application stop.
#PreDestroy
void shutdownWorkers() throws InterruptedException {
future.channel().close().sync();
}
I have a multi threaded server in which server is waiting for all possible clients to be connected.As soon as client is connected it sends an int(12345) to server and server reads and display it now server uses a specific IPaddress of a client using hash map architecture sends a message to that client to which ipaddress is matched.but my code is stuck in while loop and it isn't go to the function messagetospecificclient() and if it goes it displays null. Sorry for my bad English
My code is
Server
public class ServerStart implements Runnable
{
#Override
public void run()
{
try
{
HandleMultipleClients hmc=new HandleMultipleClients();
hmc.connect();
hmc.messagetospecificclients("172.20.3.122");
}
}
HandleMultipleClients
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package zeeshannisar210;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
*
* #author Zeeshan Nisar
*/
public class HandleMultipleClients{
Map<Integer, java.net.Socket> clients = new HashMap<Integer, java.net.Socket> ();
Socket sock;
ServerSocket serverSock;
DataOutputStream dos;
DataInputStream dis;
String ip;
public HandleMultipleClients()
{
}
public void connect()
{
try
{
serverSock = new ServerSocket(2101);
while (true)
{
sock = serverSock.accept();
clients.put(sock.getPort(), sock);
dis=new DataInputStream(sock.getInputStream());
int s=dis.readInt();
System.out.print(s);
messagetospecificclients(ip);
}
}
catch(Exception e)
{
}
}
public void messagetospecificclients(String ipaddress) throws IOException
{
System.out.print(ipaddress);
for (Iterator<Integer> iter = clients.keySet().iterator(); iter.hasNext(); )
{
int key = iter.next();
System.out.print("ok1");
ip=ipaddress;
System.out.print(ip);
System.out.print("ok2");
java.net.Socket client = clients.get(key);
InetAddress zee = client.getInetAddress();
String s = zee.getHostAddress();
System.out.print("ok3");
System.out.print(s);
if (s.equals(ipaddress))
{
System.out.print("ok4");
dos =new DataOutputStream(client.getOutputStream());
dos.writeUTF("Some message");
}
}
}
public static void main(String[] args) {
new HandleMultipleClients();
}
}
Client code is
public class messagefromserver implements Runnable
{
#Override
public void run()
{
try
{
sock = new Socket("localhost",2101);
System.out.println("Success");
dos=new DataOutputStream(sock.getOutputStream());
dos.writeInt(12345);
// Basicinfosend bis=new Basicinfosend(sock);
// Thread t1=new Thread(bis);
// t1.start();
// Thread.sleep(1000);
// Systeminfosend sis=new Systeminfosend(sock);
// Thread t2=new Thread(sis);
// t2.start();
// Thread.sleep(1000);
// Thread p = new Thread(new Process());
// p.start();
while(true)
{
String s=dis.readUTF();
System.out.print(s);
}
}
I am not talking about threading or anything to make this more complicated.
Most server programs I saw are like this or while(true){...} (same concept).
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.io.DataOutputStream;
import java.io.IOException;
public class TCPServer {
ServerSocket welcomeSocket;
public TCPServer(int port) throws IOException {
welcomeSocket = new ServerSocket(port);
}
public void go() throws IOException {
// This is not a valid way to wait for a socket connection, You should
// not have a forever loop or while(true)
**for (; ;) {**
Socket connectionSocket = welcomeSocket.accept();
Scanner clientIn = new Scanner(connectionSocket.getInputStream());
DataOutputStream clientOut = new DataOutputStream(connectionSocket.getOutputStream());
String clientLine = clientIn.nextLine();
String modLine = clientLine.toUpperCase();
clientOut.writeBytes(modLine + "\n");
}
}
public static void main(String[] args){
try {
TCPServer server = new TCPServer(6789);
server.go();
}
catch(IOException ioe) {
ioe.printStackTrace();
}
}
}
It is not looping permanently, your code blocks on line welcomeSocket.accept() until someone connects and only after that next lines are executed then it waits for a new connection on welcomeSocket.accept(). In other words it loops as many times as it needs( per each connection ).
If you just want to allow only one client to connect, remove for (; ;) statement. But it will require to restart your server every time.
The while(!finished) option might be a better solution than the "empty" for loop. When the exit event occurs, you just set finished to true.
You can run a scheduler with any number of thread in the pool
and prevent the main thread from termination. Here I've used input stream but you can do it in different ways. Here you can use multiple threads to get connections and customize the frequency of the scheduler.
import java.io.IOException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import org.junit.Test;
public class MyTest {
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(4);
#Test
public void hello() {
final Runnable helloServer = new Runnable() {
public void run() {
// handle soket connection here
System.out.println("hadling connection");
}
};
final ScheduledFuture<?> helloHandle = scheduler.scheduleAtFixedRate(helloServer, 1000, 1000, TimeUnit.MILLISECONDS);
try {
System.in.read();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Whether it's from a GUI or Console, how would either interact with Consumer? Should I simply expose consume as public, or perhaps package-private? That seems like it's stepping into a minefield.
Consumer:
package net.bounceme.dur.client;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.concurrent.BlockingQueue;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.bounceme.dur.data.State;
import net.bounceme.dur.data.Title;
public class Consumer implements Runnable {
private final BlockingQueue<Title> queue;
private ObjectOutputStream objectOutputStream = null;
public Consumer(BlockingQueue<Title> queue, ObjectOutputStream objectOutputStream) {
this.queue = queue;
this.objectOutputStream = objectOutputStream;
}
private void consume() throws InterruptedException, IOException {
Title title = queue.take();
title.setState(State.x);
objectOutputStream.writeObject(title);
}
#Override
public void run() {
try {
consume();
} catch (InterruptedException | IOException ex) {
Logger.getLogger(Consumer.class.getName()).log(Level.SEVERE, null, ex);
//exit?
}
}
}
the service:
package net.bounceme.dur.client;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.Properties;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executor;
import java.util.logging.Logger;
import net.bounceme.dur.data.Title;
public class ProducerConsumerService implements Executor {
private static final Logger log = Logger.getLogger(ProducerConsumerService.class.getName());
private final BlockingQueue<Title> queue = new ArrayBlockingQueue<>(1);
private Producer producer = null;
private Consumer consumer = null;
public void ProducerConsumerService() {
}
public void produce() {
}
public void consume() {
}
public void startService() throws IOException {
Properties props = PropertiesReader.getProps();
int portNumber = Integer.parseInt(props.getProperty("port"));
String host = props.getProperty("server");
Socket socket = new Socket(host, portNumber);
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
producer = new Producer(queue, objectInputStream);
consumer = new Consumer(queue, objectOutputStream);
new Thread((Runnable) producer).start();
new Thread((Runnable) consumer).start();
log.info("started...");
}
#Override
public void execute(Runnable command) {
new Thread(command).start();
}
}
Or, alternately, do I add methods in the service to access the BlockingQueue? However, doing so seems to obviate the need for the Consumer class itself.
What's the correct usage of these three classes by an outside class, either a Console or Swing interface?
reference:
http://www.journaldev.com/1034/java-blockingqueue-example-implementing-producer-consumer-problem
My concern with the following solution:
package net.bounceme.dur.client;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.Properties;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executor;
import java.util.logging.Logger;
import net.bounceme.dur.data.Title;
public class ProducerConsumerService implements Executor {
private static final Logger log = Logger.getLogger(ProducerConsumerService.class.getName());
private final BlockingQueue<Title> queue = new ArrayBlockingQueue<>(1);
private Producer producer = null;
private Consumer consumer = null;
private Title title = null;
public void ProducerConsumerService() {
}
public Title produce() throws InterruptedException, IOException, ClassNotFoundException {
producer.produce();
title = queue.take();
consumer.consume(title);
return title;
}
public void startService() throws IOException {
Properties props = PropertiesReader.getProps();
int portNumber = Integer.parseInt(props.getProperty("port"));
String host = props.getProperty("server");
Socket socket = new Socket(host, portNumber);
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
producer = new Producer(queue, objectInputStream);
consumer = new Consumer(queue, objectOutputStream);
new Thread((Runnable) producer).start();
new Thread((Runnable) consumer).start();
log.info("started...");
}
#Override
public void execute(Runnable command) {
new Thread(command).start();
}
}
is that it breaks encapsulation by exposing too much of Produceer and Consumer through the produce() method in the service.