package org.jgroups.tests.rt.transports; import org.jgroups.logging.Log; import org.jgroups.logging.LogFactory; import org.jgroups.tests.RoundTrip; import org.jgroups.tests.rt.RtReceiver; import org.jgroups.tests.rt.RtTransport; import org.jgroups.util.Util; import java.io.InputStream; import java.io.OutputStream; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; import java.util.List; import static java.lang.System.out; /** * @author Bela Ban * @since 4.0 */ public class TcpTransport implements RtTransport { protected ServerSocket srv_sock; protected Socket sock; protected OutputStream output; protected InputStream input; protected Receiver receiver_thread; protected RtReceiver receiver; protected InetAddress host=null; protected int port=7800; protected boolean server, tcp_nodelay; protected final Log log=LogFactory.getLog(TcpTransport.class); public TcpTransport() { } public String[] options() { return new String[]{"-host <host>", "-port <port>", "-server", "-tcp-nodelay"}; } public void options(String... options) throws Exception { if(options == null) return; for(int i=0; i < options.length; i++) { if(options[i].equals("-server")) { server=true; continue; } if(options[i].equals("-host")) { host=InetAddress.getByName(options[++i]); continue; } if(options[i].equals("-port")) { port=Integer.parseInt(options[++i]); continue; } if(options[i].equals("-tcp-nodelay")) { tcp_nodelay=true; } } if(host == null) host=InetAddress.getLocalHost(); } public void receiver(RtReceiver receiver) { this.receiver=receiver; } public Object localAddress() {return null;} public List<? extends Object> clusterMembers() { return null; } public void start(String ... options) throws Exception { options(options); if(server) { // simple single threaded server, can only handle a single connection at a time srv_sock=new ServerSocket(port, 50, host); out.println("server started (ctrl-c to kill)"); for(;;) { Socket client_sock=srv_sock.accept(); client_sock.setTcpNoDelay(tcp_nodelay); // we're concerned about latency input=client_sock.getInputStream(); output=client_sock.getOutputStream(); receiver_thread=new Receiver(input); receiver_thread.start(); } } else { sock=new Socket(); sock.setTcpNoDelay(tcp_nodelay); sock.connect(new InetSocketAddress(host, port)); output=sock.getOutputStream(); input=sock.getInputStream(); receiver_thread=new Receiver(input); receiver_thread.start(); } } public void stop() { Util.close(sock, srv_sock, input, output); } public void send(Object dest, byte[] buf, int offset, int length) throws Exception { output.write(buf, offset, length); } protected class Receiver extends Thread { protected final InputStream in; public Receiver(InputStream in) { this.in=in; } public void run() { byte[] buf=new byte[RoundTrip.PAYLOAD]; for(;;) { try { int num=in.read(buf, 0, buf.length); if(num == -1) return; if(num != buf.length) throw new IllegalStateException("expected " + buf.length + " bytes, but got only " + num); if(receiver != null) receiver.receive(null, buf, 0, buf.length); } catch(Exception e) { e.printStackTrace(); } } } } }