/**
* Copyright (C) 2010-2013 Alibaba Group Holding Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.moshi.receptionist.remoting.common;
import io.netty.channel.Channel;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import com.moshi.receptionist.remoting.exception.RemotingConnectException;
import com.moshi.receptionist.remoting.exception.RemotingSendRequestException;
import com.moshi.receptionist.remoting.exception.RemotingTimeoutException;
import com.moshi.receptionist.remoting.protocol.RemotingCommand;
/**
* 通信层一些辅助方法
*
* @author shijia.wxr<vintage.wang@gmail.com>
* @since 2013-7-13
*/
public class RemotingHelper {
public static final String RemotingLogName = "NetWorker";
public static String exceptionSimpleDesc(final Throwable e) {
StringBuffer sb = new StringBuffer();
if (e != null) {
sb.append(e.toString());
StackTraceElement[] stackTrace = e.getStackTrace();
if (stackTrace != null && stackTrace.length > 0) {
StackTraceElement elment = stackTrace[0];
sb.append(", ");
sb.append(elment.toString());
}
}
return sb.toString();
}
/**
* IP:PORT
*/
public static SocketAddress string2SocketAddress(final String addr) {
String[] s = addr.split(":");
InetSocketAddress isa = new InetSocketAddress(s[0], Integer.valueOf(s[1]));
return isa;
}
/**
* 短连接调用 TODO
*/
public static RemotingCommand invokeSync(final String addr, final RemotingCommand request,
final long timeoutMillis) throws InterruptedException, RemotingConnectException,
RemotingSendRequestException, RemotingTimeoutException {
long beginTime = System.currentTimeMillis();
SocketAddress socketAddress = RemotingUtil.string2SocketAddress(addr);
SocketChannel socketChannel = RemotingUtil.connect(socketAddress);
if (socketChannel != null) {
boolean sendRequestOK = false;
try {
// 使用阻塞模式
socketChannel.configureBlocking(true);
/*
* FIXME The read methods in SocketChannel (and DatagramChannel)
* do notsupport timeouts
* http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4614802
*/
socketChannel.socket().setSoTimeout((int) timeoutMillis);
// 发送数据
ByteBuffer byteBufferRequest = request.encode();
while (byteBufferRequest.hasRemaining()) {
int length = socketChannel.write(byteBufferRequest);
if (length > 0) {
if (byteBufferRequest.hasRemaining()) {
if ((System.currentTimeMillis() - beginTime) > timeoutMillis) {
// 发送请求超时
throw new RemotingSendRequestException(addr);
}
}
}
else {
throw new RemotingSendRequestException(addr);
}
// 比较土
Thread.sleep(1);
}
sendRequestOK = true;
// 接收应答 SIZE
ByteBuffer byteBufferSize = ByteBuffer.allocate(4);
while (byteBufferSize.hasRemaining()) {
int length = socketChannel.read(byteBufferSize);
if (length > 0) {
if (byteBufferSize.hasRemaining()) {
if ((System.currentTimeMillis() - beginTime) > timeoutMillis) {
// 接收应答超时
throw new RemotingTimeoutException(addr, timeoutMillis);
}
}
}
else {
throw new RemotingTimeoutException(addr, timeoutMillis);
}
// 比较土
Thread.sleep(1);
}
// 接收应答 BODY
int size = byteBufferSize.getInt(0);
ByteBuffer byteBufferBody = ByteBuffer.allocate(size);
while (byteBufferBody.hasRemaining()) {
int length = socketChannel.read(byteBufferBody);
if (length > 0) {
if (byteBufferBody.hasRemaining()) {
if ((System.currentTimeMillis() - beginTime) > timeoutMillis) {
// 接收应答超时
throw new RemotingTimeoutException(addr, timeoutMillis);
}
}
}
else {
throw new RemotingTimeoutException(addr, timeoutMillis);
}
// 比较土
Thread.sleep(1);
}
// 对应答数据解码
byteBufferBody.flip();
return RemotingCommand.decode(byteBufferBody);
}
catch (IOException e) {
e.printStackTrace();
if (sendRequestOK) {
throw new RemotingTimeoutException(addr, timeoutMillis);
}
else {
throw new RemotingSendRequestException(addr);
}
}
finally {
try {
socketChannel.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
else {
throw new RemotingConnectException(addr);
}
}
public static String parseChannelRemoteAddr(final Channel channel) {
if (null == channel) {
return "";
}
final SocketAddress remote = channel.remoteAddress();
final String addr = remote != null ? remote.toString() : "";
if (addr.length() > 0) {
int index = addr.lastIndexOf("/");
if (index >= 0) {
return addr.substring(index + 1);
}
return addr;
}
return "";
}
public static String parseChannelRemoteName(final Channel channel) {
if (null == channel) {
return "";
}
final InetSocketAddress remote = (InetSocketAddress) channel.remoteAddress();
if (remote != null) {
return remote.getAddress().getHostName();
}
return "";
}
public static String parseSocketAddressAddr(SocketAddress socketAddress) {
if (socketAddress != null) {
final String addr = socketAddress.toString();
if (addr.length() > 0) {
return addr.substring(1);
}
}
return "";
}
public static String parseSocketAddressName(SocketAddress socketAddress) {
final InetSocketAddress addrs = (InetSocketAddress) socketAddress;
if (addrs != null) {
return addrs.getAddress().getHostName();
}
return "";
}
}