У меня есть Tcp Server
public class SomeServer implements Runnable{
private static final int BUFFER_SIZE = 4096;
private Selector selector;
private int port;
private boolean runserver = true;
private ServerSocketChannel mySocketChannel;
private ServerSocket serverSocket;
public SomeServer(int port) {
this.port = port;
}
@Override
public void run() {
startServer();
}
private void startServer() {
try {
selector = Selector.open();
InetAddress hostIP = InetAddress.getByName("127.0.0.1");
mySocketChannel = ServerSocketChannel.open();
serverSocket = mySocketChannel.socket();
InetSocketAddress address = new InetSocketAddress(hostIP, port);
log.info("Setting up SomeServer with on {} with port {} ", hostIP, port);
serverSocket.bind(address);
mySocketChannel.configureBlocking(false);
int ops = mySocketChannel.validOps();
mySocketChannel.register(selector, ops, null);
while (runserver) {
log.info("Server running");
selector.select();
Set<SelectionKey> selectedKeys = selector.selectedKeys();
Iterator<SelectionKey> i = selectedKeys.iterator();
while (i.hasNext()) {
SelectionKey key = i.next();
if (key.isAcceptable()) {
processAcceptEvent(mySocketChannel, key);
} else if (key.isReadable()) {
processReadEvent(key);
}
i.remove();
}
}
} catch (Exception e) {
log.error("Something gone wrong in SomeServer {}", e);
}
}
private void processAcceptEvent(ServerSocketChannel mySocket, SelectionKey key) throws IOException {
log.info("Connection Accepted...");
// Accept the connection and make it non-blocking
SocketChannel myClient = mySocket.accept();
myClient.configureBlocking(false);
// Register interest in reading this channel
myClient.register(selector, SelectionKey.OP_READ);
}
private void processReadEvent(SelectionKey key) throws Exception {
log.info("Inside processReadEvent...");
// create a ServerSocketChannel to read the request
SocketChannel myClient = (SocketChannel) key.channel();
ByteBuffer myBuffer = ByteBuffer.allocate(BUFFER_SIZE);
myBuffer.order(ByteOrder.BIG_ENDIAN);
int radBytes= myClient.read(myBuffer);
if(radBytes ==-1)
return; //means connection is closed
ByteBuffer responseBuffer = clone(execute(myBuffer));
if(responseBuffer ==null){
return;
}
int byteswritten = myClient.write(responseBuffer);
log.info("bytesWritten...: {}", byteswritten);
}
public ByteBuffer execute(ByteBuffer requestBuffer) throws Exception {
final CharsetEncoder myEncoder = Charset.forName("ISO-8859-1").newEncoder();
final byte END_OF_MESSAGE_BYTE = (byte) 0x2b;
CharsetDecoder myDecoder = Charset.forName("ISO-8859-1").newDecoder();
//Process Request
final ByteBuffer processBuffer = clone(requestBuffer);
// processBuffer.flip();
int bufferSize = processBuffer.getInt();
String request = myDecoder.decode(processBuffer).toString().trim();
int requestLength=request.length();
if(requestLength<8){
log.info("Connection closed ");
return null;
}
String firstName = request.substring(0,8);
int requestBodyLength= requestLength-firstName.length();
String command = request.substring(8,requestLength-1);
processBuffer.flip();
//Build-Response
processBuffer.clear();
String response="some response";
int responselength = response.length()+firstName.length()+4;
processBuffer.putInt(responselength);
processBuffer.put(myEncoder.encode(CharBuffer.wrap(firstName)));
processBuffer.put(myEncoder.encode(CharBuffer.wrap(response)));
processBuffer.put(END_OF_MESSAGE_BYTE);
processBuffer.flip();
return processBuffer;
}
public static ByteBuffer clone(ByteBuffer original) {
if(original == null)
return null;
ByteBuffer clone = ByteBuffer.allocate(original.capacity());
original.rewind();//copy from the beginning
clone.put(original);
original.rewind();
clone.flip();
return clone;
}
}
Отправка некоторого сообщения и, кроме ответа, обратно
На стороне клиента: Чтение ответа
public class Mycleint {
priavte SocketCahnnel mySocket;
priavte String name;
final byte END_OF_MESSAGE_BYTE = (byte) 0x2b;
public Mycleint (String name , InetSocketAddress inetAddress){
this.name=name;
mySocket = SocketChannel.open();
mySocket.connect(inetAddress);
}
private String sendRequest(String request) throws IOException {
final CharsetEncoder myEncoder = Charset.forName("ISO-8859-1").newEncoder();
int requestLength = 12 + request.length() + 1;
ByteBuffer buffer = ByteBuffer.allocate(requestLength);
buffer.order(ByteOrder.BIG_ENDIAN);
buffer.putInt(requestLength);
buffer.put(myEncoder.encode(CharBuffer.wrap(name)));
buffer.put(myEncoder.encode(CharBuffer.wrap(request)));
buffer.put();
buffer.flip();
mysocket.write(buffer);
return readResponse();
}
private String readResponse(SocketChannel mySocket) throws IOException {
CharsetDecoder myDecoder = Charset.forName("ISO-8859-1").newDecoder();
ByteBuffer responseHeaderBuf = ByteBuffer.allocate(12);
responseHeaderBuf.order(ByteOrder.BIG_ENDIAN);
int bytesRead = 0;
do {
bytesRead = mySocket.read(responseHeaderBuf);
} while (bytesRead != -1 && responseHeaderBuf.position() < 12);
if (bytesRead == -1) {
throw new IOException(" : Remote connection closed unexpectedly");
}
responseHeaderBuf.flip();
int lengthField = responseHeaderBuf.getInt();
int responseLength = lengthField - responseHeaderLength;
String responseName = myDecoder.decode(responseHeaderBuf).toString();
ByteBuffer responseBuf = ByteBuffer.allocate(responseLength);
do {
bytesRead = mySocket.read(responseBuf);
} while (bytesRead != -1 && responseBuf.position() < responseLength);
if (bytesRead == -1) {
throw new IOException(name + " : Remote connection closed unexpectedly");
}
responseBuf.flip();
if (responseBuf.get(responseBuf.limit() - 1) == END_OF_MESSAGE_BYTE) {
responseBuf.limit(responseBuf.limit() - 1);
}
String response = myDecoder.decode(responseBuf).toString();
return response;
}
}
Я оставляю SocketChannel
открыть на неопределенное время на стороне клиента.
Когда я декодирую ответ в клиенте responseHeaderBuf.getInt()
, он работает правильно в первый раз.но во второй раз данные будут повреждены при декодировании.
Также, если для отправки запроса используется сокет, все работает как положено, но я хочу повторно использовать созданный мной сокет
Пример, если серверотправлено 28 processBuffer.putInt(28);
клиент говорит, что получил responseHeaderBuf.getInt()
-> 721420288,
Может кто-нибудь помочь и сказать мне, что я делаю неправильно.