Getting response from Netty server in non-Netty client - java

This is my first question on StackOverflow and I hope I have adhered to the expected standards.
I have been taking over some code from someone else who isn't working here anymore and I'm pretty much stranded here. I searched and asked some colleagues (not too much Java experience unfortunately) but no-one seems to be able to help me. Searching didn't really help me either.
I'm sending Json requests to a Netty server from a client which intentionally is NOT implemented using Netty. For now it is just a simple Java socket, but the intention is to have a Flask client send requests to the Netty server. The requests arrive (both using Java Sockets and using Python Flask), and get properly processed in the pipeline, but I want to send a response to the client and although I suspect where in the code to send the response I'm clearly missing out on something as I don't get any response. Any suggestions?
The Java Socket client (note that the json1 and json2 strings have been omitted from the snippet here as they are rather long, but they are formatted properly). Posting requests using a Socket and the related output stream. The response part (with the input stream for the same socket) is just some test which I have my doubt about, but not sure how to do this otherwise (and that's why I kept it here). I've been seeing plenty of examples with clients implementing Netty interfaces and that seems to work fine, but as said I want a client not using Netty to be able to receive the responses as well (if that's possible at all).
String serverResponse;
for (int j = 0; j < 100; j++) {
for (int i = 0; i < 1000; i++) {
try {
Socket s = new Socket("localhost", 12000);
PrintWriter out = new PrintWriter(s.getOutputStream(), true);
out.write(json1 + i + json2);
out.flush();
// Testing only - trying to get the response back from the server
BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
while(true) {
if ((serverResponse = in.readLine()) != null) {
log.info("server says", serverResponse);
break;
}
}
out.close();
s.close();
Thread.sleep(1000);
} catch (Exception ex) {
ex.printStackTrace();
}
}
Thread.sleep(2000);
}
MCTcpServer.java
/**
* Abstract TCP Server class. this class should be implemented in the subclass to implement an actual server.
*
* #param <R> The data to be read from the socket.
* #param <W> data to be written (in case of duplex) from the socket.
*/
public abstract class MFTcpServer<R, W> {
protected final AtomicBoolean started;
protected MFTcpServer() {
this.started = new AtomicBoolean();
}
/**
* Start the server.
*
* #param initializer the channel initializers. they will be called when a new client connects to the server.
* #return instance of tcp server
*/
public final MFTcpServer<R, W> start(ChannelInitializer<Channel> initializer) {
if (!started.compareAndSet(false, true)) {
throw new IllegalStateException("Server already started");
}
doStart(initializer);
return this;
}
/**
* Start the server and wait for all the threads to be finished before shutdown.
* #param initializer the channel initializers. they will be called when a new client connects to the server.
*/
public final void startAndAwait(ChannelInitializer<Channel> initializer) {
start(initializer);
awaitShutdown();
}
/**
* Shutdown the server
* #return true if successfully shutdown.
*/
public final boolean shutdown() {
return !started.compareAndSet(true, false) || doShutdown();
}
/**
* Wait for all the threads to be finished before shutdown.
*/
public abstract void awaitShutdown();
/**
* Do the shutdown now.
* #return true if successfully shutdown
*/
public abstract boolean doShutdown();
/**
* start the server
* #param initializer the channel initializers. they will be called when a new client connetcs to the server.
* #return instance of tcp server
*/
public abstract MFTcpServer<R, W> doStart(ChannelInitializer<Channel> initializer);
/**
*
* #return the port where the server is running.
*/
public abstract int getPort();
MFNetty4TcpServer.java Actual server implementation
public class MFNetty4TcpServer<R, W> extends MFTcpServer<R, W> {
private static final Logger logger = LoggerFactory.getLogger(MFNetty4TcpServer.class);
private static final int BOSS_THREAD_POOL_SIZE = 2;
private int port;
private ServerBootstrap bootstrap;
private ChannelFuture bindFuture;
/**
* The constructor.
*
* #param port port where to listen
*/
protected MFNetty4TcpServer(int port) {
this.port = port;
final NioEventLoopGroup bossGroup = new NioEventLoopGroup(0, new DefaultEventExecutorGroup
(BOSS_THREAD_POOL_SIZE));
final NioEventLoopGroup workerGroup = new NioEventLoopGroup(0, new DefaultEventExecutorGroup
(JsonProducerConfig.THREAD_POOL_SIZE));
bootstrap = new ServerBootstrap()
.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class);
}
#Override
public MFNetty4TcpServer<R, W> doStart(ChannelInitializer<Channel> initializer) {
bootstrap.childHandler(new ChannelInitializer<Channel>() {
#Override
protected void initChannel(Channel ch) throws Exception {
if (initializer != null) {
ch.pipeline().addLast(initializer);
}
}
});
try {
bindFuture = bootstrap.bind(port).sync();
if (!bindFuture.isSuccess()) {
// Connection not successful
throw new RuntimeException(bindFuture.cause());
}
SocketAddress localAddress = bindFuture.channel().localAddress();
if (localAddress instanceof InetSocketAddress) {
port = ((InetSocketAddress) localAddress).getPort();
logger.info("Started server at port: " + port);
}
} catch (InterruptedException e) {
logger.error("Error waiting for binding server port: " + port, e);
}
return this;
}
#Override
public void awaitShutdown() {
try {
bindFuture.channel().closeFuture().await();
} catch (InterruptedException e) {
Thread.interrupted(); // Reset the interrupted status
logger.error("Interrupted while waiting for the server socket to close.", e);
}
}
#Override
public boolean doShutdown() {
try {
bindFuture.channel().close().sync();
return true;
} catch (InterruptedException e) {
logger.error("Failed to shutdown the server.", e);
return false;
}
}
#Override
public int getPort() {
return port;
}
/**
* Creates a tcp server at the defined port.
*
* #param port port to listen to
* #param <R> data to be read
* #param <W> data to be written back. Only in case of duplex connection.
* #return instance of tcp server.
*/
public static <R, W> MFTcpServer<R, W> create(int port) {
return new MFNetty4TcpServer<>(port);
}
}
JsonProducerConfig.java The pipeline is setup here.
/**
* Spring Configuration class of the application.
*/
#Configuration
#Import({DatabusConfig.class})
public class JsonProducerConfig {
private static final Logger log = LoggerFactory.getLogger(JsonProducerConfig.class);
public static final int THREAD_POOL_SIZE = Runtime.getRuntime().availableProcessors() * 2;
public static final String TCP_SERVER = "tcpServer";
public static final String CHANNEL_PIPELINE_INITIALIZER = "channel_initializer";
public static final String MF_KAFKA_PRODUCER = "mf_kafka_producer";
public static final String JSON_AVRO_CONVERTOR = "jsonAvroConvertor";
#Value("#{systemProperties['tcpserver.port']?:'12000'}")
private String tcpServerPort;
#Bean(name = TCP_SERVER)
#Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
public MFTcpServer nettyTCPServer() {
return MFNetty4TcpServer.create(Integer.parseInt(tcpServerPort));
}
#Bean(name = MF_KAFKA_PRODUCER)
#Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
public MFKafkaProducer pushToKafka() {
return new MFKafkaProducer();
}
#Bean(name = JSON_AVRO_CONVERTOR)
#Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
public JsonAvroConvertor jsonAvroConvertor() {
return new JsonAvroConvertor();
}
/**
* This is where the pipeline is set for processing of events.
*
* #param jsonAvroConvertor converts json to avro
* #param kafkaProducer pushes to kafka
* #return chanenl initializers pipeline.
*/
#Bean(name = CHANNEL_PIPELINE_INITIALIZER)
#Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public ChannelInitializer<Channel> channelInitializers(JsonAvroConvertor jsonAvroConvertor,
MFKafkaProducer kafkaProducer) {
return new ChannelInitializer<Channel>() {
#Override
protected void initChannel(Channel channel) throws Exception {
if (log.isInfoEnabled())
log.info("initChannel - initing channel...");
channel.pipeline().addLast(new NioEventLoopGroup(0, new DefaultEventExecutorGroup(THREAD_POOL_SIZE)));
channel.pipeline().addLast(new JsonObjectDecoder(1048576));
channel.pipeline().addLast(jsonAvroConvertor);
channel.pipeline().addLast(kafkaProducer);
if (log.isInfoEnabled())
log.info("channel = " + channel.toString());
}
};
}
}
JsonProducer.java The main program
public class JsonProducer {
private static final Logger log = LoggerFactory.getLogger(JsonProducer.class);
private static MFTcpServer tcpServer;
/**
* Main startup method
*
* #param args not used
*/
public static void main(String[] args) {
System.setProperty("solschema", "false");
try {
// the shutdown hook.
Runtime.getRuntime().addShutdownHook(new Thread(
() -> {
if (tcpServer != null) {
tcpServer.shutdown();
}
}
));
AnnotationConfigApplicationContext context = new
AnnotationConfigApplicationContext(JsonProducerConfig.class);
tcpServer = (MFTcpServer) context.getBean(JsonProducerConfig.TCP_SERVER);
ChannelInitializer<Channel> channelInitializer = (ChannelInitializer<Channel>) context.
getBean(JsonProducerConfig.CHANNEL_PIPELINE_INITIALIZER);
tcpServer.startAndAwait(channelInitializer);
} catch (Exception t) {
log.error("Error while starting JsonProducer ", t);
System.exit(-1);
}
}
}
The MFKafkaProducer.java as the last channel in the pipeline. Note the ctx.writeAndFlush(msg) in the channelRead method which is where I understand the response should be initiated. But what after that. When running this channelFuture.isSuccess() evaluates to false. The response object was an attempt to a String response.
#ChannelHandler.Sharable
public class MFKafkaProducer extends ChannelInboundHandlerAdapter {
private static final Logger log = LoggerFactory.getLogger(MFKafkaProducer.class);
#Resource
ApplicationContext context;
#Resource(name = DatabusConfig.ADMIN)
Admin admin;
private Map<String, IProducer> streams = new HashMap<>();
#PreDestroy
public void stop() {
removeAllStreams(); // then stop writing to producers
}
/**
* #param clickRecord the record to be pushed to kafka
* #throws Exception
*/
public void handle(GenericRecord clickRecord) throws Exception {
Utf8 clientId = null;
try {
clientId = (Utf8) clickRecord.get(SchemaUtil.APP_ID);
stream(producer(clientId.toString()), clickRecord);
} catch (Exception e) {
String message = "Could not push click data for clientId:" + clientId;
log.warn("handle - " + message + "!!!", e);
assert clientId != null;
removeStream(clientId.toString());
}
}
/**
* removes all the streams
*/
private void removeAllStreams() {
Set<String> strings = streams.keySet();
for (String clientId : strings) {
removeStream(clientId);
}
}
/**
* removes a particular stream
*
* #param clientId the stream to be removed
*/
private void removeStream(String clientId) {
Assert.notEmpty(streams);
IProducer producer = streams.get(clientId);
producer.stopProducer();
streams.remove(clientId);
}
/**
* #param producer the producer where data needs to be written
* #param clickRecord teh record to be written
*/
private void stream(IProducer producer, GenericRecord clickRecord) {
producer.send(clickRecord);
}
/**
* This will create a producer in case it is not already created.
* If already created return the already present one
*
* #param clientId stream id
* #return the producer instance
*/
private IProducer producer(String clientId) {
if (streams.containsKey(clientId)) {
return streams.get(clientId);
} else {
IProducer producer = admin.createKeyTopicProducer(SchemaUtil.APP_ID, "test_" + clientId, new ICallback() {
#Override
public void onSuccess(long offset) {
if (log.isInfoEnabled())
log.info("onSuccess - Data at offset:" + offset + " send.");
}
#Override
public void onError(long offset, Exception ex) {
if (log.isInfoEnabled())
log.info("onError - Data at offset:" + offset + " failed. Exception: ", ex);
}
#Override
public void onStreamClosed() {
log.warn("onStreamClosed - Stream:" + clientId + " closed.");
removeStream(clientId);
}
});
producer.startProducer();
streams.put(clientId, producer);
return producer;
}
}
#Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
log.debug("KafkaProducer - channelRead() called with " + "ctx = [" + ctx + "], msg = [" + msg + "]");
if (msg instanceof GenericRecord) {
GenericRecord genericRecord = (GenericRecord) msg;
try {
handle(genericRecord);
log.debug("channelRead sending response");
Charset charset = Charset.defaultCharset();
ByteBuf response = Unpooled.copiedBuffer("Just a response", charset);
ChannelFuture future = ctx.writeAndFlush(msg);
future.addListener(new ChannelFutureListener() {
#Override
public void operationComplete(ChannelFuture channelFuture) throws Exception {
if (channelFuture.isSuccess())
log.info("channelRead - future.operationComplete - Response has been delivered to all channels");
else
log.info("channelRead - future.operationComplete - Response has NOT been delivered to all channels");
}
});
} catch (Exception ex) {
log.error("Something went wrong processing the generic record: " + msg + "\n ", ex);
}
} else {
log.debug("KafkaProducer - msg not of Type Generic Record !!! " + msg);
}
}
#Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
// Close the connection when an exception is raised.
log.error("Something went wrong writing to Kafka: \n", cause);
ctx.close();
}
}

Using ChannelFuture#cause() I noticed I was not serializing a ByteBuf object, but a GenericRecord instead. Using
ByteBuf response = Unpooled.copiedBuffer(genericRecord.toString(), charset);
ChannelFuture future = ctx.writeAndFlush(response);
the GenericRecord gets converted to a ButeBuf and sends a response using the writeAndFlush method.
The test client using a Socket implementation somehow never really received a response, but by using a SocketChannel this was resolved as well.

Related

Hyperledger Fabric grpcs error: Connection Refused: no further information,JAVA SDK

I have been trying out to invoke and querying transactions from the Java SDK for the BYFN network in Hyperledger Fabric v1.4.4 So far i have started the network (which has two peers in two orgs, an orderer and chaincode mycc installed). The network starts successfully, and scripts and tests complete.
This is my Java SDK code to manipulate the network from Java and do queries and invokes
Main class:
public class sdksample {
// Main program to simply call the client, Am i making some mistake here ?? persistency ?
public static void main(String[] args) throws Exception {
// create fabric-ca client
BlockChainHFClient.getInstance().setupCryptoMaterialsForClient();
BlockChainHFClient.getInstance().initChannel();
// get HFC client instance
BlockChainHFClient client = BlockChainHFClient.getInstance();
System.out.println(client);
}
}
BlockchainClient Class:
public class BlockChainHFClient {
private static BlockChainHFClient instance;
/**
* Client instance constructor
*/
private BlockChainHFClient() {
}
/**
* Returns an instance of the Fabric client
*
* #return instance
*/
public static synchronized BlockChainHFClient getInstance() {
if (instance == null) {
instance = new BlockChainHFClient();
}
return instance;
}
/**
* Fabric client object
*/
final HFClient hfClient = HFClient.createNewInstance();
/**
* Crypto config folder location . keep crypto-config folder in user/home
*/
final String CRYPTO_CONFIG_HOME_DIR = System.getProperty("user.home");
/**
* Grpcs URL
*/
final String GRPCS = "grpcs://";
/**
* Dot for utility
*/
final String DOT = ".";
/**
* MSP ID Root
*/
final String ROOT_MSP_ID = "Org1MSP";
/**
* Admin user
*/
final String PEER_ADMIN = "PeerAdmin";
/**
* Channel object
*/
Channel channel;
/**
* Channel initialize timeout values
*/
final Long ChannelBuilderOptionkeepAliveMinutes = 15L;
final Long ChannelBuilderOptionkeepAliveSeconds = 15L;
/**
* Get channel instance
*
* #return channel
*/
public Channel getChannel() {
return channel;
}
/**
* Get HF client
*
* #return HF client
*/
public HFClient getClient() {
return hfClient;
}
/**
* Set up User contexts by using Crypto materials - Private key and cert files
*
* #throws CryptoException
* #throws InvalidArgumentException
* #throws IllegalAccessException
* #throws InstantiationException
* #throws ClassNotFoundException
* #throws NoSuchMethodException
* #throws InvocationTargetException
*/
public void setupCryptoMaterialsForClient()
throws CryptoException, InvalidArgumentException, IllegalAccessException, InstantiationException,
ClassNotFoundException, NoSuchMethodException, InvocationTargetException {
hfClient.setCryptoSuite(CryptoSuite.Factory.getCryptoSuite());
hfClient.setUserContext(new User() {
public String getName() {
return PEER_ADMIN;
}
public Set<String> getRoles() {
return null;
}
public String getAccount() {
return null;
}
public String getAffiliation() {
return null;
}
public Enrollment getEnrollment() {
return new Enrollment() {
public PrivateKey getKey() {
PrivateKey privateKey = null;
File privateKeyFile = findFileSk(
"D:\\Hyperledger Fabric_Research_Blockchain\\Fabric1.4.4\\fabric-samples\\first-network\\crypto-config\\peerOrganizations\\org1.example.com\\users\\Admin#org1.example.com\\msp\\keystore");
try {
privateKey = getPrivateKeyFromBytes(
IOUtils.toByteArray(new FileInputStream(privateKeyFile)));
} catch (IOException e) {
e.printStackTrace();
} catch (NoSuchProviderException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidKeySpecException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return privateKey;
}
public String getCert() {
String certificate = null;
try {
File certificateFile = new File(
"D:\\Hyperledger Fabric_Research_Blockchain\\Fabric1.4.4\\fabric-samples\\first-network\\crypto-config\\peerOrganizations\\org1.example.com\\users\\Admin#org1.example.com\\msp\\signcerts\\Admin#org1.example.com-cert.pem");
certificate = new String(IOUtils.toByteArray(new FileInputStream(certificateFile)),
"UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return certificate;
}
};
}
public String getMspId() {
return ROOT_MSP_ID;
}
});
}
public void initChannel() throws Exception {
Properties peerProperties = new Properties();
peerProperties.setProperty("pemFile",
"D:\\Hyperledger Fabric_Research_Blockchain\\Fabric1.4.4\\fabric-samples\\first-network\\crypto-config\\peerOrganizations\\org1.example.com\\peers\\peer0.org1.example.com\\tls\\server.crt");
peerProperties.setProperty("trustServerCertificate", "true"); // testing environment only NOT FOR PRODUCTION!
peerProperties.setProperty("hostnameOverride", "peer0.org1.example.com");
peerProperties.setProperty("sslProvider", "openSSL");
peerProperties.setProperty("negotiationType", "TLS");
peerProperties.put("grpc.NettyChannelBuilderOption.maxInboundMessageSize", 9000000);
Peer peer = hfClient.newPeer("peer0.org1.example.com", "grpcs://localhost:7051");
Properties ordererProperties = new Properties();
ordererProperties.setProperty("pemFile",
"D:\\Hyperledger Fabric_Research_Blockchain\\Fabric1.4.4\\fabric-samples\\first-network\\crypto-config\\ordererOrganizations\\example.com\\orderers\\orderer.example.com\\tls\\server.crt");
ordererProperties.setProperty("trustServerCertificate", "true"); // testing environment only NOT FOR PRODUCTION!
ordererProperties.setProperty("hostnameOverride", "orderer.example.com");
ordererProperties.setProperty("sslProvider", "openSSL");
ordererProperties.setProperty("negotiationType", "TLS");
ordererProperties.put("grpc.NettyChannelBuilderOption.keepAliveTime", new Object[] { 5L, TimeUnit.MINUTES });
ordererProperties.put("grpc.NettyChannelBuilderOption.keepAliveTimeout", new Object[] { 8L, TimeUnit.SECONDS });
Orderer orderer = hfClient.newOrderer("orderer.example.com", "grpcs://localhost:7050");
Channel channel = hfClient.newChannel("mychannel");
channel.addPeer(peer);
channel.addOrderer(orderer);
channel.initialize();
moveUnits(hfClient);
queryBlockChain(hfClient);
}
private String printableString(String string) {
int maxLogStringLength = 10000;
if (string == null || string.length() == 0) {
return string;
}
String ret = string.replaceAll("[^\\p{Print}]", "\n");
ret = ret.substring(0, Math.min(ret.length(), maxLogStringLength))
+ (ret.length() > maxLogStringLength ? "..." : "");
return ret;
}
void queryBlockChain(HFClient client) throws ProposalException, InvalidArgumentException {
// get channel instance from client
Channel channel = client.getChannel("mychannel");
// create chaincode request
QueryByChaincodeRequest qpr = client.newQueryProposalRequest();
// build cc id providing the chaincode name. Version is omitted here.
ChaincodeID cid = ChaincodeID.newBuilder().setName("mycc").build();
qpr.setChaincodeID(cid);
// CC function to be called
qpr.setFcn("query");
qpr.setArgs(new String[] { "a" });
Collection<ProposalResponse> res = channel.queryByChaincode(qpr);
// display response
for (ProposalResponse pres : res) {
String stringResponse = new String(pres.getChaincodeActionResponsePayload());
System.out.println(stringResponse);
}
}
void moveUnits(HFClient client)
throws Exception {
Channel channel = client.getChannel("mychannel");
TransactionProposalRequest req = client.newTransactionProposalRequest();
ChaincodeID cid = ChaincodeID.newBuilder().setName("mycc").setVersion("1.0").build();
req.setChaincodeID(cid);
req.setFcn("invoke");
req.setArgs(new String[] {"a","b","50"});
Collection<ProposalResponse> resps = channel.sendTransactionProposal(req);
channel.sendTransaction(resps);
}
/**
* Utility method to get private key from bytes using Bouncy Castle Security
* Provider
*
* #param data
* #return privateKey
* #throws IOException
* #throws NoSuchProviderException
* #throws NoSuchAlgorithmException
* #throws InvalidKeySpecException
*/
private PrivateKey getPrivateKeyFromBytes(byte[] data)
throws IOException, NoSuchProviderException, NoSuchAlgorithmException, InvalidKeySpecException {
final Reader pemReader = new StringReader(new String(data));
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
final PrivateKeyInfo pemPair;
try (PEMParser pemParser = new PEMParser(pemReader)) {
pemPair = (PrivateKeyInfo) pemParser.readObject();
}
PrivateKey privateKey = new JcaPEMKeyConverter().setProvider(BouncyCastleProvider.PROVIDER_NAME)
.getPrivateKey(pemPair);
return privateKey;
}
/**
* Find files ending with _sk
*
* #param directorys
* #return file
*/
private File findFileSk(String directorys) {
File directory = new File(directorys);
File[] matches = directory.listFiles((dir, name) -> name.endsWith("_sk"));
if (null == matches) {
throw new RuntimeException(
format("Matches returned null does %s directory exist?", directory.getAbsoluteFile().getName()));
}
if (matches.length != 1) {
throw new RuntimeException(format("Expected in %s only 1 sk file but found %d",
directory.getAbsoluteFile().getName(), matches.length));
}
return matches[0];
}
}
The setting up crypto materials part and the channel initialization part works fine (adding peer and order to the channel and initializing it)
I get errors during QueryProposal or a TransactionProposal, that is , if I want to do anything after initializing channel with the required crypto material
This is the error trace:
Message Request processing failed; nested exception is
org.hyperledger.fabric.sdk.exception.ProposalException:
org.hyperledger.fabric.sdk.exception.ProposalException: Channel
mychannel failed proposal on peer peer0.org1.example.com
org.hyperledger.fabric.sdk.exception.TransactionException:
org.hyperledger.fabric.sdk.exception.ProposalException: getConfigBlock
for channel mychannel failed with peer peer0.org1.example.com. Status
FAILURE, details: Channel Channel{id: 1, name: mychannel} Sending
proposal with transaction:
3323e96e7e9147ccee2491b310e6dacfc2db93d50578f08a43a5c997a211135a to
Peer{ id: 7, name: peer0.org1.example.com, channelName: mychannel,
url: grpcs://localhost:7051} failed because of: gRPC
failure=Status{code=UNAVAILABLE, description=io exception,
cause=io.netty.channel.AbstractChannel$AnnotatedConnectException:
Connection refused: no further information:
localhost/0:0:0:0:0:0:0:1:7051
I have tried changing docker images, did not work, same error, I have a feeling that this error has something to do with grpcs refusing to connect with the peer on the port? Is there something that i have missed or something that can prevent from accessing the peer. Somewhere is the port already used, or a firewall maybe ? Because this worked in another system with the same steps. Not really sure about this.
Suggestions would help !
Thanks

Netty Channel fail when write and flush too many and too fast

When I write a producer to publish message to my server. I've seen this:
java.io.IOException: Connection reset by peer
at sun.nio.ch.FileDispatcherImpl.read0(Native Method)
at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:39)
at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223)
at sun.nio.ch.IOUtil.read(IOUtil.java:192)
at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:384)
at io.netty.buffer.UnpooledUnsafeDirectByteBuf.setBytes(UnpooledUnsafeDirectByteBuf.java:447)
at io.netty.buffer.AbstractByteBuf.writeBytes(AbstractByteBuf.java:881)
at io.netty.channel.socket.nio.NioSocketChannel.doReadBytes(NioSocketChannel.java:242)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:119)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:511)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:468)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:382)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:354)
at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:111)
at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
at java.lang.Thread.run(Thread.java:745)
I've searched all around and was told that because of channel is closed.
But, in my code. I'm just close my channel when my channel pool destroy the channel.
Here my code:
public static class ChannelFactory implements PoolableObjectFactory<Channel> {
private final Bootstrap bootstrap;
private String host;
private int port;
public ChannelFactory(Bootstrap bootstrap, String host, int port) {
this.bootstrap = bootstrap;
this.host = host;
this.port = port;
}
#Override
public Channel makeObject() throws Exception {
System.out.println("Create new channel!!!");
bootstrap.validate();
return bootstrap.connect(host, port).channel();
}
#Override
public void destroyObject(Channel channel) throws Exception {
ChannelFuture close = channel.close();
if (close.isSuccess()) {
System.out.println(channel + " close successfully");
}
}
#Override
public boolean validateObject(Channel channel) {
System.out.println("Validate object");
return (channel.isOpen());
}
#Override
public void activateObject(Channel channel) throws Exception {
System.out.println(channel + " is activated");
}
#Override
public void passivateObject(Channel channel) throws Exception {
System.out.println(channel + " is passivated");
}
/**
* #return the host
*/
public String getHost() {
return host;
}
/**
* #param host the host to set
* #return
*/
public ChannelFactory setHost(String host) {
this.host = host;
return this;
}
/**
* #return the port
*/
public int getPort() {
return port;
}
/**
* #param port the port to set
* #return
*/
public ChannelFactory setPort(int port) {
this.port = port;
return this;
}
}
And here is my Runner:
public static class Runner implements Runnable {
private Channel channel;
private ButtyMessage message;
private MyChannelPool channelPool;
public Runner(MyChannelPool channelPool, Channel channel, ButtyMessage message) {
this.channel = channel;
this.message = message;
this.channelPool = channelPool;
}
#Override
public void run() {
channel.writeAndFlush(message.content()).syncUninterruptibly().addListener(new ChannelFutureListener() {
#Override
public void operationComplete(ChannelFuture future) throws Exception {
channelPool.returnObject(future.channel());
}
});
}
}
And my main:
public static void main(String[] args) throws InterruptedException {
final String host = "127.0.0.1";
final int port = 8080;
int jobSize = 100;
int jobNumber = 10000;
final Bootstrap b = func(host, port);
final MyChannelPool channelPool = new MyChannelPool(new ChannelFactory(b, host, port));
ExecutorService threadPool = Executors.newFixedThreadPool(1);
for (int i = 0; i < jobNumber; i++) {
try {
threadPool.execute(new Runner(channelPool, channelPool.borrowObject(), new ButtyMessage()));
} catch (Exception ex) {
System.out.println("ex = " + ex.getMessage());
}
}
}
With ButtyMessage extends ByteBufHolder.
In my Runner class, if I sleep(10) after writeAndFlush it run quite OK. But I don't want to reply on sleep. So I use ChannelFutureListener, but the result is bad. If I send about 1000 to 10.000 messages, it will crash and throw exception above. Is there any way to avoid this?
Thanks all.
Sorry for my bad explain and my English :)
You have several issues that could explain this. Most of them are related to wrong usage of asynchronous operations and future usage.
I don't know if it could be in link with your issue but, if you really want to print when the channel is really closed, you have to wait on the future, since the future on close() (or any other operations) immediately returns, without waiting for the real close. Therefore your test if (close.isSuccess()) shall be always false.
public void destroyObject(final Channel channel) throws Exception {
channel.close().addListener(new ChannelFutureListener() {
#Override
public void operationComplete(ChannelFuture close) {
if (close.isSuccess()) {
System.out.println(channel + " close successfully");
}
}
});
}
However, as I suppose it is only for debug purpose, it is not mandatory.
Another one: you send back to your pool a channel that is not already connected (which could explain your sleep(10) maybe?). You have to wait on the connect().
public Channel makeObject() throws Exception {
System.out.println("Create new channel!!!");
//bootstrap.validate(); // this is implicitely called in connect()
ChannelFuture future = bootstrap.connect(host, port).awaitUninterruptibly();
if (future.isSuccess()) {
return future.channel();
} else {
// do what you need to do when the connection is not done
}
}
third one: validation of a connected channel might be better using isActive():
#Override
public boolean validateObject(Channel channel) {
System.out.println("Validate object");
return channel.isActive(); // instead of isOpen()
}
fourth one: in your runner, you wrongly await on the future while you should not. You can remove your syncUninterruptibly() and let the rest as is.
#Override
public void run() {
Channel.writeAndFlush(message.content()).addListener(new ChannelFutureListener() {
#Override
public void operationComplete(ChannelFuture future) throws Exception {
channelPool.returnObject(future.channel());
}
});
}
And finally, I suppose you know your test is completely sequential (1 thread in your pool), such that each client will reuse over and over the very same channel?
Could you try to change the 4 points to see if it corrects your issue?
EDIT: after requester comment
For syncUntinterruptibly(), I did not read carefully. If you want to block on write, then you don't need the extra addListener since the future is done once the sync is over. So you can directly call your channelPool.returnObject as next command just after your sync.
So you should write it this way, simpler.
#Override
public void run() {
Channel.writeAndFlush(message.content()).syncUntinterruptibly();
channelPool.returnObject(future.channel());
}
For fireChannelActive, it will be called as soon as the connect finished (so from makeObject, sometime in the future). Moreover, once disconnected (as you did have notice in your exception), the channel is no more usable and must be recreated from zero. So I would suggest to use isActive however, such that, if not active, it will be removed using destroyObject...
Take a look at the channel state model here.
Finally, I've found a solution for myself. But, I'm still think about another solution. (this solution is exactly copy from 4.0.28 netty release note)
final String host = "127.0.0.1";
final int port = 8080;
int jobNumber = 100000;
final EventLoopGroup group = new NioEventLoopGroup(100);
ChannelPoolMap<InetSocketAddress, MyChannelPool> poolMap = new AbstractChannelPoolMap<InetSocketAddress, MyChannelPool>() {
#Override
protected MyChannelPool newPool(InetSocketAddress key) {
Bootstrap bootstrap = func(group, key.getHostName(), key.getPort());
return new MyChannelPool(bootstrap, new _AbstractChannelPoolHandler());
}
};
ChannelPoolMap<InetSocketAddress, FixedChannelPool> poolMap1 = new AbstractChannelPoolMap<InetSocketAddress, FixedChannelPool>() {
#Override
protected FixedChannelPool newPool(InetSocketAddress key) {
Bootstrap bootstrap = func(group, key.getHostName(), key.getPort());
return new FixedChannelPool(bootstrap, new _AbstractChannelPoolHandler(), 10);
}
};
final ChannelPool myChannelPool = poolMap.get(new InetSocketAddress(host, port));
final CountDownLatch latch = new CountDownLatch(jobNumber);
for (int i = 0; i < jobNumber; i++) {
final int counter = i;
final Future<Channel> future = myChannelPool.acquire();
future.addListener(new FutureListener<Channel>() {
#Override
public void operationComplete(Future<Channel> f) {
if (f.isSuccess()) {
Channel ch = f.getNow();
// Do somethings
ch.writeAndFlush(new ButtyMessage().content()).addListener(new ChannelFutureListener() {
#Override
public void operationComplete(ChannelFuture future) throws Exception {
if (future.isSuccess()) {
System.out.println("counter = " + counter);
System.out.println("future = " + future.channel());
latch.countDown();
}
}
});
// Release back to pool
myChannelPool.release(ch);
} else {
System.out.println(f.cause().getMessage());
f.cause().printStackTrace();
}
}
});
}
try {
latch.await();
System.exit(0);
} catch (InterruptedException ex) {
System.out.println("ex = " + ex.getMessage());
}
As you can see, I use SimpleChannelPool and FixedChannelPool (an implementation of SimpleChannelPool provided by netty).
What it can do:
SimpleChannelPool: open channels as much as it need ---> if you has 100.000 msg -> cuz error, of course. Many socket open, then IOExeption: Too many file open occur. (is that really pool? Create as much as possible and throw exception? I don't call this is pooling)
FixedChannelPool: not work in my case (Still study why? =)) Sorry for my stupidness)
Indeed, I want to use ObjectPool instead. And I may post it as soon as when I finish. Tks #Frederic Brégier for helping me so much!

TTransportException Exception while working with Apache Thrift

I am working with apache Thrift. I am getting TTransportException exception while everthing looks fine with my code. Here is my Thrift Server Code:
private TNonblockingServerSocket socket;
/**
* #breif Store processor instance.
*/
private PringService.Processor processor;
/**
* Store server instance.
*/
private TServer tServer;
/**
*
* #breif A handle to the unique Singleton instance.
*/
static private ThriftServer _instance = null;
/**
* #breif The unique instance of this class.
* #throws TTransportException
*/
static public ThriftServer getInstance() throws TTransportException {
if (null == _instance) {
_instance = new ThriftServer();
}
return _instance;
}
/**
* #breif A Ctor for ThriftServer. Initialize all members.
* #throws TTransportException
*/
private ThriftServer() throws TTransportException {
socket = new TNonblockingServerSocket(Config.THRIFT_PORT);
processor = new PringService.Processor(new Handler());
THsHaServer.Args args = new THsHaServer.Args(socket);
args.processor(processor);
args.transportFactory(new TFramedTransport.Factory());
args.inputProtocolFactory(new TBinaryProtocol.Factory());
args.outputProtocolFactory(new TBinaryProtocol.Factory());
tServer = new THsHaServer(args);
/*tServer = new THsHaServer(processor, socket,
new TFramedTransport.Factory(),
new TFramedTransport.Factory(),
new TBinaryProtocol.Factory(),
new TBinaryProtocol.Factory());*/
}
/**
* #breif main method
* #param args the command line arguments
* #throws TTransportException
*/
public static void main(String[] args) throws TTransportException {
// To Run it directly from PringCore.jar, else use SmsProcessor Helper functionality
ThriftServer server = new ThriftServer();
server.execute(args);
}
#Override
/**
* #breif Starts the execution.
*/
protected void execute(String[] args) {
if (db != null) {
db.close();
}
tServer.serve();
}
private static class Handler implements PringService.Iface {
......
}
}
And This is my thrift client:
TTransport transport;
try {
transport = new TSocket("localhost", Config.THRIFT_PORT);
transport.open();
TProtocol protocol = new TBinaryProtocol(transport);
PringService.Client client = new PringService.Client(protocol);
String result = client.importPringer(2558456, true);
System.out.println("Result String is ::"+result);
transport.close();
} catch (TTransportException e) {
e.printStackTrace();
} catch (TException e) {
e.printStackTrace();
}
When I run my Thrift server and then run thrift client, I get the following exception:
org.apache.thrift.transport.TTransportException
at org.apache.thrift.transport.TIOStreamTransport.read(TIOStreamTransport.java:132)
at org.apache.thrift.transport.TTransport.readAll(TTransport.java:84)
at org.apache.thrift.protocol.TBinaryProtocol.readAll(TBinaryProtocol.java:378)
at org.apache.thrift.protocol.TBinaryProtocol.readI32(TBinaryProtocol.java:297)
at org.apache.thrift.protocol.TBinaryProtocol.readMessageBegin(TBinaryProtocol.java:204)
at org.apache.thrift.TServiceClient.receiveBase(TServiceClient.java:69)
Am I using mis-matching transport sockt/layer on my thrift server or client ? Or there is something other wrong?
Thanks in Advance for your guidance :)
When you use TNonblockingServerSocket, you need to use TFramedTransport both server- and client-side. The documentation of TNonblockingServerSocket is quite explicit about that:
To use this server, you MUST use a TFramedTransport at the outermost transport, otherwise this server will be unable to determine when a whole method call has been read off the wire. Clients must also use TFramedTransport.
Your client should therefore look like this:
TTransport transport;
try {
transport = new TSocket("localhost", Config.THRIFT_PORT);
transport.open();
TProtocol protocol = new TBinaryProtocol(new TFramedTransport(transport));
PringService.Client client = new PringService.Client(protocol);
String result = client.importPringer(2558456, true);
System.out.println("Result String is ::"+result);
transport.close();
} catch (TTransportException e) {
e.printStackTrace();
} catch (TException e) {
e.printStackTrace();
}

zeromq socket recv returned null (java warper)

i have network client / server application that using java zeromq
framework for the communications .
i have the main server and N clients that polls the server . when the server gets online.
the clients connect him and there some short massaging going on between them
until now i done with single client and it worked fine .
but when adding another client ( that's 2 )
i getting in the request null as returned massage :
request = socket.recv (0);
based on the this example :
http://zguide.zeromq.org/java:mtserver
my code (part of it its very long )
all context and the ZeroMq Settings are set and not null
and i allways get this exception :
Exception in thread "Thread-1" org.zeromq.ZMQException: Operation cannot be accomplished in current state(0x9523dfb)
at org.zeromq.ZMQ$Socket.recv(Native Method)
at com.controller.core.Daemon$1.run(Daemon.java:127)
for(int thread_nbr = 0; thread_nbr < m_iThreadPoolCount; thread_nbr++) {
Thread worker_routine = new Thread() {
#Override
public void run() {
//synchronized(OBJ_LOCK) {
ZMQ.Socket socket = m_pNetworkManager.getContext().socket(ZMQ.REP);//context.socket(ZMQ.REP);
socket.connect ("inproc://workers");
while (true) {
/** Wait for next request from client (C string) */
byte[] request = null;
try{
if(m_pNetworkManager.getContext()!=null) // its never null
{
request = socket.recv (0);
}
}catch (Exception e)
{
// it allays gets null exception
}
boolean bFoundInList = false;
if(request!=null)
{
// multi frame sending
socket.send(m_UT.getbyteArray(
m_UT.getReplayStructure(aStateMap_replay)
),ZMQ.SNDMORE);
socket.send(new byte[0], ZMQ.SNDMORE);
byte[] byteFileStruct = null;
byteFileStruct = m_UT.serialize(stateFilesStruct);
boolean send = socket.send(byteFileStruct,0);
} // socket.recv end
}
// }// synchronized block
}
}; //Thread worker_routine
worker_routine.start();
}
// Connect work threads to client threads via a queue
ZMQQueue zMQQueue = new ZMQQueue( m_pNetworkManager.getContext(),
m_pNetworkManager.getClients(),
m_pNetworkManager.getWorkers());
zMQQueue.run();
// We never get here but clean up anyhow
m_pNetworkManager.getClients().close();
m_pNetworkManager.getWorkers().close();
m_pNetworkManager.getContext().term();
}
allso added the NetworkManager class
public class NetworkManager {
/** ZeroMQ context */
private ZMQ.Context m_context = null;
/** ZeroMQ socket */
private ZMQ.Socket m_socket = null;
/** representation of the clients */
ZMQ.Socket m_clients = null;
/** representation of the workers threads */
ZMQ.Socket m_workers = null;
/**
* NetworkManager constructor.
*/
public NetworkManager()
{
;
}
/**
* Setup the network ZeroMQ network layer
* #param sControllerDomain the Controller domain name and port
*/
public void Init(String sControllerDomain)
{
/** Prepare our context and socket */
m_context = ZMQ.context(1);
m_clients = m_context.socket(ZMQ.ROUTER);
// m_clients = m_context.socket(ZMQ.REP);
m_clients.bind (sControllerDomain);
m_workers = m_context.socket(ZMQ.DEALER);
m_workers.bind ("inproc://workers");
}
/**
* Get ZeroMQ context
* #return ZMQ.Context
*/
public ZMQ.Context getContext() {
return m_context;
}
/**
* get ZeroMQ Socket
* #return ZMQ.Socket
*/
public ZMQ.Socket getSocket() {
return m_socket;
}
/**
* get the workers as ZMQ.Socket
* #return ZMQ.Socket
*/
public ZMQ.Socket getWorkers() {
return m_workers;
}
/**
* get the Clients as ZMQ.Socket
* #return ZMQ.Socket
*/
public ZMQ.Socket getClients() {
return m_clients;
}
}
What your OS system? If you are using Windows the operations using: m_workers.bind ("inproc://workers") is not supported. IIRC.

sending sms(text) from java code to mobile phone in windows

Is it possible to send sms from windows machine to mobile phone.
I have searched a lot and got the following code.
Sender.java
package sms;
import java.util.Date;
public class Sender implements Runnable {
private static final long STANDARD=500;
private static final long LONG=2000;
private static final long VERYLONG=20000;
SerialConnection mySerial =null;
static final private char cntrlZ=(char)26;
String in, out;
Thread aThread=null;
private long delay=STANDARD;
String recipient=null;
String message=null;
private String csca="+6596845999"; // the message center
private SerialParameters defaultParameters= new SerialParameters ("COM2",9600,0,0,8,1,0);
public int step;
public int status=-1;
public long messageNo=-1;
public Sender(String recipient, String message){
this.recipient=recipient;
this.message=message;
}
/**
* connect to the port and start the dialogue thread
*/
public int send () throws Exception{
SerialParameters params = defaultParameters;
mySerial =new SerialConnection (params);
mySerial.openConnection();
aThread=new Thread(this);
aThread.start() ;
//log("start");
return 0;
}
/**
* implement the dialogue thread,
* message / response via steps,
* handle time out
*/
public void run(){
boolean timeOut=false;
long startTime=(new Date()).getTime();
while ((step <7) && (!timeOut)){
// log(""+((new Date()).getTime() - startTime);
//check where we are in specified delay
timeOut=((new Date()).getTime() - startTime)>delay;
//if atz does not work, type to send cntrlZ and retry, in case a message was stuck
if (timeOut && (step==1)) {
step=-1;
mySerial.send( ""+cntrlZ);
}
//read incoming string
String result= mySerial.getIncommingString() ;
// log ("<- "+result+"\n--------");
int expectedResult=-1;
try{
//log ("Step:"+step);
switch (step){
case 0:
mySerial.send("atz");
delay=LONG;
startTime=(new Date()).getTime();
break;
case 1:
delay=STANDARD;
mySerial.send("ath0");
startTime=(new Date()).getTime();
break;
case 2:
expectedResult=result.indexOf("OK");
//log ("received ok ="+expectedResult);
if (expectedResult>-1){
mySerial.send("at+cmgf=1");
startTime=(new Date()).getTime();
}else{
step=step-1;
}
break;
case 3:
expectedResult=result.indexOf("OK");
// log ("received ok ="+expectedResult);
if (expectedResult>-1){
mySerial.send("at+csca=\""+csca+"\"");
startTime=(new Date()).getTime();
}else{
step=step-1;
}
break;
case 4:
expectedResult=result.indexOf("OK");
// log ("received ok ="+expectedResult);
if (expectedResult>-1){
mySerial.send("at+cmgs=\""+recipient+"\"");
startTime=(new Date()).getTime();
}else{
step=step-1;
}
break;
case 5:
expectedResult=result.indexOf(">");
// log ("received ok ="+expectedResult);
if (expectedResult>-1){
mySerial.send(message+cntrlZ);
startTime=(new Date()).getTime();
}else{
step=step-1;
}
delay=VERYLONG;//waitning for message ack
break;
case 6:
expectedResult=result.indexOf("OK");
//read message number
if (expectedResult>-1){
int n=result.indexOf("CMGS:");
result=result.substring(n+5);
n=result.indexOf("\n");
status=0;
messageNo=Long.parseLong(result.substring(0,n).trim() );
log ("sent message no:"+messageNo);
}else{
step=step-1;
}
break;
}
step=step+1;
aThread.sleep(100);
}catch (Exception e){
e.printStackTrace();
}
}
mySerial.closeConnection() ;
//if timed out set status
if (timeOut ) {
status=-2;
log("*** time out at step "+step+"***");
}
}
/**
* logging function, includes date and class name
*/
private void log(String s){
System.out.println (new java.util.Date()+":"+this.getClass().getName()+":"+s);
}
}
SerialConnection.java
package sms;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.TooManyListenersException;
import javax.comm.CommPortIdentifier;
import javax.comm.CommPortOwnershipListener;
import javax.comm.NoSuchPortException;
import javax.comm.PortInUseException;
import javax.comm.SerialPort;
import javax.comm.SerialPortEvent;
import javax.comm.SerialPortEventListener;
import javax.comm.UnsupportedCommOperationException;
/**
A class that handles the details of a serial connection. Reads from one
TextArea and writes to a second TextArea.
Holds the state of the connection.
*/
public class SerialConnection implements SerialPortEventListener,
CommPortOwnershipListener {
private SerialParameters parameters;
private OutputStream os;
private InputStream is;
private KeyHandler keyHandler;
private CommPortIdentifier portId;
private SerialPort sPort;
private boolean open;
private String receptionString="";
public String getIncommingString(){
byte[] bVal= receptionString.getBytes();
receptionString="";
return new String (bVal);
}
public SerialConnection(SerialParameters parameters) {
this.parameters = parameters;
open = false;
}
/**
Attempts to open a serial connection and streams using the parameters
in the SerialParameters object. If it is unsuccesfull at any step it
returns the port to a closed state, throws a
<code>SerialConnectionException</code>, and returns.
Gives a timeout of 30 seconds on the portOpen to allow other applications
to reliquish the port if have it open and no longer need it.
*/
public void openConnection() throws SerialConnectionException {
// System.out.println("OK 0 ");
// Obtain a CommPortIdentifier object for the port you want to open.
try {
// System.out.println(parameters.getPortName());
portId = CommPortIdentifier.getPortIdentifier(parameters.getPortName());
} catch (NoSuchPortException e) {
// System.out.println("Yes the problem is here 1 ");
e.printStackTrace();
// throw new SerialConnectionException(e.getMessage());
}catch(Exception e)
{
// System.out.println("ErrorErrorErrorError");
e.printStackTrace();
}
//System.out.println(portId);
//System.out.println("OK 1 ");
// Open the port represented by the CommPortIdentifier object. Give
// the open call a relatively long timeout of 30 seconds to allow
// a different application to reliquish the port if the user
// wants to.
try {
sPort = (SerialPort)portId.open("SMSConnector", 30000);
} catch (PortInUseException e) {
throw new SerialConnectionException(e.getMessage());
}
//System.out.println("OK 2 ");
sPort.sendBreak(1000);
// Set the parameters of the connection. If they won't set, close the
// port before throwing an exception.
try {
setConnectionParameters();
} catch (SerialConnectionException e) {
sPort.close();
throw e;
}
// System.out.println("OK 3 ");
// Open the input and output streams for the connection. If they won't
// open, close the port before throwing an exception.
try {
os = sPort.getOutputStream();
is = sPort.getInputStream();
} catch (IOException e) {
sPort.close();
throw new SerialConnectionException("Error opening i/o streams");
}
//System.out.println("OK 4 ");
/*
// Create a new KeyHandler to respond to key strokes in the
// messageAreaOut. Add the KeyHandler as a keyListener to the
// messageAreaOut.
keyHandler = new KeyHandler(os);
messageAreaOut.addKeyListener(keyHandler);
*/
// Add this object as an event listener for the serial port.
try {
sPort.addEventListener(this);
} catch (TooManyListenersException e) {
sPort.close();
throw new SerialConnectionException("too many listeners added");
}
//System.out.println("OK 5 ");
// Set notifyOnDataAvailable to true to allow event driven input.
sPort.notifyOnDataAvailable(true);
// Set notifyOnBreakInterrup to allow event driven break handling.
sPort.notifyOnBreakInterrupt(true);
// Set receive timeout to allow breaking out of polling loop during
// input handling.
try {
sPort.enableReceiveTimeout(30);
} catch (UnsupportedCommOperationException e) {
}
//System.out.println("OK 6 ");
// Add ownership listener to allow ownership event handling.
portId.addPortOwnershipListener(this);
open = true;
}
/**
Sets the connection parameters to the setting in the parameters object.
If set fails return the parameters object to origional settings and
throw exception.
*/
public void setConnectionParameters() throws SerialConnectionException {
// Save state of parameters before trying a set.
int oldBaudRate = sPort.getBaudRate();
int oldDatabits = sPort.getDataBits();
int oldStopbits = sPort.getStopBits();
int oldParity = sPort.getParity();
int oldFlowControl = sPort.getFlowControlMode();
// Set connection parameters, if set fails return parameters object
// to original state.
try {
sPort.setSerialPortParams(parameters.getBaudRate(),
parameters.getDatabits(),
parameters.getStopbits(),
parameters.getParity());
} catch (UnsupportedCommOperationException e) {
parameters.setBaudRate(oldBaudRate);
parameters.setDatabits(oldDatabits);
parameters.setStopbits(oldStopbits);
parameters.setParity(oldParity);
throw new SerialConnectionException("Unsupported parameter");
}
// Set flow control.
try {
sPort.setFlowControlMode(parameters.getFlowControlIn()
| parameters.getFlowControlOut());
} catch (UnsupportedCommOperationException e) {
throw new SerialConnectionException("Unsupported flow control");
}
}
/**
Close the port and clean up associated elements.
*/
public void closeConnection() {
// If port is alread closed just return.
if (!open) {
return;
}
// Remove the key listener.
// messageAreaOut.removeKeyListener(keyHandler);
// Check to make sure sPort has reference to avoid a NPE.
if (sPort != null) {
try {
// close the i/o streams.
os.close();
is.close();
} catch (IOException e) {
System.err.println(e);
}
// Close the port.
sPort.close();
// Remove the ownership listener.
portId.removePortOwnershipListener(this);
}
open = false;
}
/**
Send a one second break signal.
*/
public void sendBreak() {
sPort.sendBreak(1000);
}
/**
Reports the open status of the port.
#return true if port is open, false if port is closed.
*/
public boolean isOpen() {
return open;
}
/**
Handles SerialPortEvents. The two types of SerialPortEvents that this
program is registered to listen for are DATA_AVAILABLE and BI. During
DATA_AVAILABLE the port buffer is read until it is drained, when no more
data is availble and 30ms has passed the method returns. When a BI
event occurs the words BREAK RECEIVED are written to the messageAreaIn.
*/
public void serialEvent(SerialPortEvent e) {
// Create a StringBuffer and int to receive input data.
StringBuffer inputBuffer = new StringBuffer();
int newData = 0;
// Determine type of event.
switch (e.getEventType()) {
// Read data until -1 is returned. If \r is received substitute
// \n for correct newline handling.
case SerialPortEvent.DATA_AVAILABLE:
while (newData != -1) {
try {
newData = is.read();
if (newData == -1) {
break;
}
if ('\r' == (char)newData) {
inputBuffer.append('\n');
} else {
inputBuffer.append((char)newData);
}
} catch (IOException ex) {
System.err.println(ex);
return;
}
}
// Append received data to messageAreaIn.
receptionString=receptionString+ (new String(inputBuffer));
//System.out.print("<-"+receptionString);
break;
// If break event append BREAK RECEIVED message.
case SerialPortEvent.BI:
receptionString=receptionString+("\n--- BREAK RECEIVED ---\n");
}
}
/**
Handles ownership events. If a PORT_OWNERSHIP_REQUESTED event is
received a dialog box is created asking the user if they are
willing to give up the port. No action is taken on other types
of ownership events.
*/
public void ownershipChange(int type) {
/*
if (type == CommPortOwnershipListener.PORT_OWNERSHIP_REQUESTED) {
PortRequestedDialog prd = new PortRequestedDialog(parent);
}
*/
}
/**
A class to handle <code>KeyEvent</code>s generated by the messageAreaOut.
When a <code>KeyEvent</code> occurs the <code>char</code> that is
generated by the event is read, converted to an <code>int</code> and
writen to the <code>OutputStream</code> for the port.
*/
class KeyHandler extends KeyAdapter {
OutputStream os;
/**
Creates the KeyHandler.
#param os The OutputStream for the port.
*/
public KeyHandler(OutputStream os) {
super();
this.os = os;
}
/**
Handles the KeyEvent.
Gets the <code>char</char> generated by the <code>KeyEvent</code>,
converts it to an <code>int</code>, writes it to the <code>
OutputStream</code> for the port.
*/
public void keyTyped(KeyEvent evt) {
char newCharacter = evt.getKeyChar();
if ((int)newCharacter==10) newCharacter = '\r';
System.out.println ((int)newCharacter);
try {
os.write((int)newCharacter);
} catch (IOException e) {
System.err.println("OutputStream write error: " + e);
}
}
}
public void send(String message) {
byte[] theBytes= (message+"\n").getBytes();
for (int i=0; i<theBytes.length;i++){
char newCharacter = (char)theBytes[i];
if ((int)newCharacter==10) newCharacter = '\r';
try {
os.write((int)newCharacter);
} catch (IOException e) {
System.err.println("OutputStream write error: " + e);
}
}
//System.out.println (">'" +message +"' sent");
}
}
SerialConnection.java
package sms;
public class SerialConnectionException extends Exception {
/**
* Constructs a <code>SerialConnectionException</code>
* with the specified detail message.
*
* #param s the detail message.
*/
public SerialConnectionException(String str) {
super(str);
}
/**
* Constructs a <code>SerialConnectionException</code>
* with no detail message.
*/
public SerialConnectionException() {
super();
}
}
SerialParameters.java
package sms;
import javax.comm.SerialPort;
/**
A class that stores parameters for serial ports.
*/
public class SerialParameters {
private String portName;
private int baudRate;
private int flowControlIn;
private int flowControlOut;
private int databits;
private int stopbits;
private int parity;
/**
Default constructer. Sets parameters to no port, 9600 baud, no flow
control, 8 data bits, 1 stop bit, no parity.
*/
public SerialParameters () {
this("",
9600,
SerialPort.FLOWCONTROL_NONE,
SerialPort.FLOWCONTROL_NONE,
SerialPort.DATABITS_8,
SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE );
}
/**
Paramaterized constructer.
#param portName The name of the port.
#param baudRate The baud rate.
#param flowControlIn Type of flow control for receiving.
#param flowControlOut Type of flow control for sending.
#param databits The number of data bits.
#param stopbits The number of stop bits.
#param parity The type of parity.
*/
public SerialParameters(String portName,
int baudRate,
int flowControlIn,
int flowControlOut,
int databits,
int stopbits,
int parity) {
this.portName = portName;
this.baudRate = baudRate;
this.flowControlIn = flowControlIn;
this.flowControlOut = flowControlOut;
this.databits = databits;
this.stopbits = stopbits;
this.parity = parity;
}
/**
Sets port name.
#param portName New port name.
*/
public void setPortName(String portName) {
this.portName = portName;
}
/**
Gets port name.
#return Current port name.
*/
public String getPortName() {
return portName;
}
/**
Sets baud rate.
#param baudRate New baud rate.
*/
public void setBaudRate(int baudRate) {
this.baudRate = baudRate;
}
/**
Sets baud rate.
#param baudRate New baud rate.
*/
public void setBaudRate(String baudRate) {
this.baudRate = Integer.parseInt(baudRate);
}
/**
Gets baud rate as an <code>int</code>.
#return Current baud rate.
*/
public int getBaudRate() {
return baudRate;
}
/**
Gets baud rate as a <code>String</code>.
#return Current baud rate.
*/
public String getBaudRateString() {
return Integer.toString(baudRate);
}
/**
Sets flow control for reading.
#param flowControlIn New flow control for reading type.
*/
public void setFlowControlIn(int flowControlIn) {
this.flowControlIn = flowControlIn;
}
/**
Sets flow control for reading.
#param flowControlIn New flow control for reading type.
*/
public void setFlowControlIn(String flowControlIn) {
this.flowControlIn = stringToFlow(flowControlIn);
}
/**
Gets flow control for reading as an <code>int</code>.
#return Current flow control type.
*/
public int getFlowControlIn() {
return flowControlIn;
}
/**
Gets flow control for reading as a <code>String</code>.
#return Current flow control type.
*/
public String getFlowControlInString() {
return flowToString(flowControlIn);
}
/**
Sets flow control for writing.
#param flowControlIn New flow control for writing type.
*/
public void setFlowControlOut(int flowControlOut) {
this.flowControlOut = flowControlOut;
}
/**
Sets flow control for writing.
#param flowControlIn New flow control for writing type.
*/
public void setFlowControlOut(String flowControlOut) {
this.flowControlOut = stringToFlow(flowControlOut);
}
/**
Gets flow control for writing as an <code>int</code>.
#return Current flow control type.
*/
public int getFlowControlOut() {
return flowControlOut;
}
/**
Gets flow control for writing as a <code>String</code>.
#return Current flow control type.
*/
public String getFlowControlOutString() {
return flowToString(flowControlOut);
}
/**
Sets data bits.
#param databits New data bits setting.
*/
public void setDatabits(int databits) {
this.databits = databits;
}
/**
Sets data bits.
#param databits New data bits setting.
*/
public void setDatabits(String databits) {
if (databits.equals("5")) {
this.databits = SerialPort.DATABITS_5;
}
if (databits.equals("6")) {
this.databits = SerialPort.DATABITS_6;
}
if (databits.equals("7")) {
this.databits = SerialPort.DATABITS_7;
}
if (databits.equals("8")) {
this.databits = SerialPort.DATABITS_8;
}
}
/**
Gets data bits as an <code>int</code>.
#return Current data bits setting.
*/
public int getDatabits() {
return databits;
}
/**
Gets data bits as a <code>String</code>.
#return Current data bits setting.
*/
public String getDatabitsString() {
switch(databits) {
case SerialPort.DATABITS_5:
return "5";
case SerialPort.DATABITS_6:
return "6";
case SerialPort.DATABITS_7:
return "7";
case SerialPort.DATABITS_8:
return "8";
default:
return "8";
}
}
/**
Sets stop bits.
#param stopbits New stop bits setting.
*/
public void setStopbits(int stopbits) {
this.stopbits = stopbits;
}
/**
Sets stop bits.
#param stopbits New stop bits setting.
*/
public void setStopbits(String stopbits) {
if (stopbits.equals("1")) {
this.stopbits = SerialPort.STOPBITS_1;
}
if (stopbits.equals("1.5")) {
this.stopbits = SerialPort.STOPBITS_1_5;
}
if (stopbits.equals("2")) {
this.stopbits = SerialPort.STOPBITS_2;
}
}
/**
Gets stop bits setting as an <code>int</code>.
#return Current stop bits setting.
*/
public int getStopbits() {
return stopbits;
}
/**
Gets stop bits setting as a <code>String</code>.
#return Current stop bits setting.
*/
public String getStopbitsString() {
switch(stopbits) {
case SerialPort.STOPBITS_1:
return "1";
case SerialPort.STOPBITS_1_5:
return "1.5";
case SerialPort.STOPBITS_2:
return "2";
default:
return "1";
}
}
/**
Sets parity setting.
#param parity New parity setting.
*/
public void setParity(int parity) {
this.parity = parity;
}
/**
Sets parity setting.
#param parity New parity setting.
*/
public void setParity(String parity) {
if (parity.equals("None")) {
this.parity = SerialPort.PARITY_NONE;
}
if (parity.equals("Even")) {
this.parity = SerialPort.PARITY_EVEN;
}
if (parity.equals("Odd")) {
this.parity = SerialPort.PARITY_ODD;
}
}
/**
Gets parity setting as an <code>int</code>.
#return Current parity setting.
*/
public int getParity() {
return parity;
}
/**
Gets parity setting as a <code>String</code>.
#return Current parity setting.
*/
public String getParityString() {
switch(parity) {
case SerialPort.PARITY_NONE:
return "None";
case SerialPort.PARITY_EVEN:
return "Even";
case SerialPort.PARITY_ODD:
return "Odd";
default:
return "None";
}
}
/**
Converts a <code>String</code> describing a flow control type to an
<code>int</code> type defined in <code>SerialPort</code>.
#param flowControl A <code>string</code> describing a flow control type.
#return An <code>int</code> describing a flow control type.
*/
private int stringToFlow(String flowControl) {
if (flowControl.equals("None")) {
return SerialPort.FLOWCONTROL_NONE;
}
if (flowControl.equals("Xon/Xoff Out")) {
return SerialPort.FLOWCONTROL_XONXOFF_OUT;
}
if (flowControl.equals("Xon/Xoff In")) {
return SerialPort.FLOWCONTROL_XONXOFF_IN;
}
if (flowControl.equals("RTS/CTS In")) {
return SerialPort.FLOWCONTROL_RTSCTS_IN;
}
if (flowControl.equals("RTS/CTS Out")) {
return SerialPort.FLOWCONTROL_RTSCTS_OUT;
}
return SerialPort.FLOWCONTROL_NONE;
}
/**
Converts an <code>int</code> describing a flow control type to a
<code>String</code> describing a flow control type.
#param flowControl An <code>int</code> describing a flow control type.
#return A <code>String</code> describing a flow control type.
*/
String flowToString(int flowControl) {
switch(flowControl) {
case SerialPort.FLOWCONTROL_NONE:
return "None";
case SerialPort.FLOWCONTROL_XONXOFF_OUT:
return "Xon/Xoff Out";
case SerialPort.FLOWCONTROL_XONXOFF_IN:
return "Xon/Xoff In";
case SerialPort.FLOWCONTROL_RTSCTS_IN:
return "RTS/CTS In";
case SerialPort.FLOWCONTROL_RTSCTS_OUT:
return "RTS/CTS Out";
default:
return "None";
}
}
}
But when i am trying to run the code, i am getting following error:-
Error loading SolarisSerial: java.lang.UnsatisfiedLinkError: no SolarisSerialParallel in java.library.path
Caught java.lang.UnsatisfiedLinkError: com.sun.comm.SolarisDriver.readRegistrySerial(Ljava/util/Vector;Ljava/lang/String;)I while loading driver com.sun.comm.SolarisDriver
is this code that i have taken OS specific. Or there are any other way to send sms(txt) from pc to mobile.
Please help me.
I think this is a very complicated approach.
If you are developing a commercial application, there are many companies which provide web services that you could use. You just send the sms text to the webservice, and they will send the sms for you, no need to reinvent the wheel.
Unless you are developing a webservice like this yourself!
Your code relies on a JNI driver class "com.sun.comm.SolarisDriver". Your program can't locate the dinamic library SolarisSerialParallel.
The Java virtual machine needs to be able to find the native library. To do this, set the library path adding the path to the library as follows:
Unix or Linux based systems:
LD_LIBRARY_PATH=$LD_LIBRARY_PATH;'/opt/whatever/SolarisSerialParallel.so'
export LD_LIBRARY_PATH
Windows (I guess that in this case, you'll need to search the appropiate DLL, as the one required at your question seems to be exclusive for Solaris environments):
set PATH=%path%;C:\whatever\SolarisSerialParallel.dll
Note that you can point it to the containing directory, if more libraries ar needed.
Reference: Java Native Interface Specification

Categories