자바 NIO 를 사용 하여 비동기 적 인 socket 통신 을 실현 합 니 다.
구 IO 로 이 루어 진 Socket 통신 에 대해 서 는 이 글 을 참고 할 수 있 습 니 다.http://blog.csdn.net/kongxx/article/category/1077912
최근 NIO 와 Socket 을 공부 할 때 인터넷 에서 진정 으로 비동기 적 인 socket 을 실현 하 는 예 가 드 물 게 발견 되 었 다.대부분 Selector 만 사용 하여 서버 의 Server Socket Channel 을 관리 하 는데 사실상 진정한 이 보 를 하지 못 했 거나 순서대로 연결 을 받 아들 이 고 메 시 지 를 받 은 후에 연결 을 풀 었 다.
더 일반적인 방법 은 서버 에서 두 개의 스 레 드 를 사용 하고 한 스 레 드 는 차단 하 는 방법 으로 accept 클 라 이언 트 를 사용 하 며 다른 스 레 드 는 selector 로 모든 연결 을 비동기 적 으로 처리 하 는 것 입 니 다.
비동기 IO 의 간단 한 인 스 턴 스 를 위해 selector 를 사용 합 니 다.서버 는 메 인 스 레 드 에서 무한 순환 차단 스 레 드 를 통 해 들 어 오 는 연결 을 감청 하고 다른 스 레 드 를 시작 합 니 다.selector 를 통 해 연 결 된 통 로 를 비동기 적 으로 처리 합 니 다.클 라 이언 트 가 100 개의 스 레 드 를 시작 하여 100 명의 사용자 가 동시에 서버 에 연결 되 는 것 을 모 의 합 니 다.출력 결 과 를 통 해 클 라 이언 트 와 서버 의 통신 이 비동기 적 으로 이 루어 진 것 을 알 수 있 습 니 다.
먼저 도구 류 를 붙 이 고 그 안에 메 시 지 를 보 내 는 두 가지 방법 이 있다.
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
public class SendAndReceiveUtil {
public static String receiveData(SocketChannel channel) {
// TODO Auto-generated method stub
// TODO Auto-generated method stub
ByteBuffer bb = ByteBuffer.allocate(1024);
StringBuilder msg = new StringBuilder();
Charset charset = Charset.forName("UTF-8");
CharsetDecoder decoder = charset.newDecoder();
try {
while( (channel.read(bb) ) > 0 ){
bb.flip();
msg.append(decoder.decode(bb).toString());
//System.out.println(msg.toString());
bb.clear();
}
return msg.toString();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public static void sendData(SocketChannel socketChannel, String msg) {
// TODO Auto-generated method stub
try {
socketChannel.write(ByteBuffer.wrap(msg.getBytes()));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
그리고 서버 코드 를 붙 여 주세요.
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
public class ChatServer {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
final Selector selector = Selector.open();;
ServerSocketChannel ssc = ServerSocketChannel.open();
try{
// Bind the server socket to the local host and port
ssc.socket().bind(new InetSocketAddress("localhost", 8080));
//start a thread to handle the wirte and read
startWRThread(selector);
//block the main thread to accept client
while(true){ // will block the thread
SocketChannel sc = ssc.accept();
//Get the server socket and set to non blocking mode
sc.configureBlocking(false);
sc.register(selector, SelectionKey.OP_READ);
}
}finally{
selector.close();
ssc.close();
}
}
private static void startWRThread(final Selector selector) {
// TODO Auto-generated method stub
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
try {
while(true){
while(selector.selectNow() > 0){
Iterator it = selector.selectedKeys().iterator();
//// Walk through the ready keys collection and process date requests.
while(it.hasNext()){
SelectionKey readyKey = it.next();
if(readyKey.isReadable()){
SocketChannel sc = (SocketChannel) readyKey.channel();
String msg = SendAndReceiveUtil.receiveData(sc);
if(msg != null && !msg.equals("")) {
if(msg.equals("bye")){
System.out.println("Get a msg : " + msg);
sc.close();
}else{
System.out.println("Get a msg : " + msg);
SendAndReceiveUtil.sendData(sc,"Server have got you msg:"+ msg);
sc.shutdownOutput();
}
}
it.remove();
}
//execute((ServerSocketChannel) readyKey.channel());
}
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
}
}
마지막 으로 클 라 이언 트 코드 를 붙 입 니 다.클 라 이언 트 는 100 개의 스 레 드 를 시작 하여 100 개의 클 라 이언 트 를 모 의 해서 서버 에 연결 하고 스 레 드 id 를 서버 에 보 낸 다음 에'bye'를 보 내 서 연결 을 끝 냅 니 다.
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.channels.SocketChannel;
public class ChatClient {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
for (int i = 1; i < 100; i++) {
final int idx = i;
new Thread(new MyRunnable(idx)).start();
}
}
private static class MyRunnable implements Runnable {
private final int idx;
private MyRunnable(int idx) {
this.idx = idx;
}
@Override
public void run() {
// TODO Auto-generated method stub
SocketChannel socketChannel = null;
try {
socketChannel = SocketChannel.open();
SocketAddress socketAddress = new InetSocketAddress("localhost", 8080);
socketChannel.connect(socketAddress);
SendAndReceiveUtil.sendData(socketChannel, "My id is " + idx);
String msg = SendAndReceiveUtil.receiveData(socketChannel);
if(msg != null) System.out.println("The server reply:"+msg);
SendAndReceiveUtil.sendData(socketChannel,"bye");
} catch (Exception ex) {
ex.printStackTrace();
} finally {
try {
socketChannel.close();
} catch(Exception ex) {
ex.printStackTrace();
}
}
}
}
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JAVA 객체 작성 및 제거 방법정적 공장 방법 정적 공장 방법의 장점 를 반환할 수 있습니다. 정적 공장 방법의 단점 류 공유되거나 보호된 구조기를 포함하지 않으면 이불류화할 수 없음 여러 개의 구조기 파라미터를 만났을 때 구축기를 고려해야 한다...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.