日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java nio.2群发_JAVA NIO TCP SOCKET 聊天群发

發布時間:2024/1/23 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java nio.2群发_JAVA NIO TCP SOCKET 聊天群发 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

以前都是用一般的socket編程,用線程來控制。最近突然用nio來做些東西。

nio的好處我來說一下:第一,讀寫都是基于塊的,效率高。第二,通過引入selector,簡化了網絡編程模型,異步非阻塞。

既然有這么多好處,那就寫個NIO TCP網絡聊天室來練練手吧。

因為沒有寫gui,是基于控制臺的所以沒寫私了的部分,只寫了公共聊天室。(其實,既然是服務器端可以分發給所有人,分發給特定人也是很容易實現的。

注意:這里只是為了練手,聯系服務器端分發消息到各個客戶端。TCP 來寫聊天室,在現實中是不可取的。IM都是基于UDP來寫的。

先上代碼吧。

服務器端代碼 MySocketServer.java

/*

* To change this template, choose Tools | Templates

* and open the template in the editor.

*/

package com.kevin.nio;

import java.io.IOException;

import java.net.InetSocketAddress;

import java.nio.ByteBuffer;

import java.nio.channels.SelectionKey;

import java.nio.channels.Selector;

import java.nio.channels.ServerSocketChannel;

import java.nio.channels.SocketChannel;

import java.util.Date;

import java.util.Iterator;

import java.util.logging.Level;

import java.util.logging.Logger;

/**

*

* @author kevin

*/

public class MySocketServer implements Runnable{

private boolean running;

private Selector selector;

String writeMsg;

StringBuffer sb=new StringBuffer();

SelectionKey ssckey;

public MySocketServer(){

running=true;

}

public void init(){

try {

selector = Selector.open();

ServerSocketChannel ssc = ServerSocketChannel.open();

ssc.configureBlocking(false);

ssc.socket().bind(new InetSocketAddress(2345));

ssckey=ssc.register(selector, SelectionKey.OP_ACCEPT);

System.out.println("server is starting..."+new Date());

} catch (IOException ex) {

Logger.getLogger(MySocketServer.class.getName()).log(Level.SEVERE, null, ex);

}

}

public static void main(String[] args){

MySocketServer server=new MySocketServer();

new Thread(server).start();

}

public void execute(){

try {

while(running){

int num=selector.select();

if(num>0){

Iterator it=selector.selectedKeys().iterator();

while(it.hasNext()){

SelectionKey key=it.next();

it.remove();

if(!key.isValid()) continue;

if(key.isAcceptable()){

System.out.println("isAcceptable");

getConn(key);

}

else if(key.isReadable()){

System.out.println("isReadable");

readMsg(key);

}

else if(key.isValid()&&key.isWritable()){

if(writeMsg!=null){

System.out.println("isWritable");

writeMsg(key);

}

}

else break;

}

}

Thread.yield();

}

} catch (IOException ex) {

Logger.getLogger(MySocketServer.class.getName()).log(Level.SEVERE, null, ex);

}

}

private void getConn(SelectionKey key) throws IOException {

ServerSocketChannel ssc=(ServerSocketChannel)key.channel();

SocketChannel sc=ssc.accept();

sc.configureBlocking(false);

sc.register(selector, SelectionKey.OP_READ);

System.out.println("build connection :"+sc.socket().getRemoteSocketAddress());

}

private void readMsg(SelectionKey key) throws IOException {

sb.delete(0, sb.length());

SocketChannel sc=(SocketChannel)key.channel();

System.out.print(sc.socket().getRemoteSocketAddress()+" ");

ByteBuffer buffer=ByteBuffer.allocate(1024);

buffer.clear();

int len=0;

StringBuffer sb=new StringBuffer();

while((len=sc.read(buffer))>0){

buffer.flip();

sb.append(new String(buffer.array(),0,len));

}

if(sb.length()>0) System.out.println("get from client:"+sb.toString());

if(sb.toString().trim().toLowerCase().equals("quit")){

sc.write(ByteBuffer.wrap("BYE".getBytes()));

System.out.println("client is closed "+sc.socket().getRemoteSocketAddress());

key.cancel();

sc.close();

sc.socket().close();

}

else{

String toMsg=sc.socket().getRemoteSocketAddress()+ "said:"+sb.toString();

System.out.println(toMsg);

writeMsg=toMsg;

/*

Iterator it=key.selector().keys().iterator();

while(it.hasNext()){

SelectionKey skey=it.next();

if(skey!=key&&skey!=ssckey){

SocketChannel client=(SocketChannel) skey.channel();

client.write(ByteBuffer.wrap(toMsg.getBytes()));

}

}

*

*/

/*

key.attach(toMsg);

key.interestOps(key.interestOps()|SelectionKey.OP_WRITE);

*

*/

Iterator it=key.selector().keys().iterator();

while(it.hasNext()){

SelectionKey skey=it.next();

if(skey!=key&&skey!=ssckey){

if(skey.attachment()!=null){

String str=(String) skey.attachment();

skey.attach(str+toMsg);

}else{

skey.attach(toMsg);

}

skey.interestOps(skey.interestOps()|SelectionKey.OP_WRITE);

}

}

selector.wakeup();//可有可無

}

}

public void run() {

init();

execute();

}

private void writeMsg(SelectionKey key) throws IOException {

System.out.println("++++enter write+++");

SocketChannel sc=(SocketChannel) key.channel();

String str=(String) key.attachment();

sc.write(ByteBuffer.wrap(str.getBytes()));

key.interestOps(SelectionKey.OP_READ);

}

}

客戶端:MySocketClient.java

/*

* To change this template, choose Tools | Templates

* and open the template in the editor.

*/

package com.kevin.nio;

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.net.InetSocketAddress;

import java.nio.ByteBuffer;

import java.nio.channels.Selector;

import java.nio.channels.SocketChannel;

import java.util.logging.Level;

import java.util.logging.Logger;

import java.util.Currency.*;

/**

*

* @author kevin

*/

public class MySocketClient implements Runnable{

Selector selector;

boolean running;

SocketChannel sc;

public MySocketClient(){

running=true;

}

public void init() {

try {

sc = SocketChannel.open();

sc.configureBlocking(false);

sc.connect(new InetSocketAddress("localhost", 2345));

} catch (IOException ex) {

Logger.getLogger(MySocketClient.class.getName()).log(Level.SEVERE, null, ex);

}

}

public static void main(String[] args){

MySocketClient client=new MySocketClient();

new Thread(client).start();

}

public void execute(){

int num=0;

try {

while (!sc.finishConnect()) {

}

} catch (IOException ex) {

Logger.getLogger(MySocketClient.class.getName()).log(Level.SEVERE, null, ex);

}

ReadKeyBoard rkb=new ReadKeyBoard();

new Thread(rkb).start();

while(running){

try {

ByteBuffer buffer=ByteBuffer.allocate(1024);

buffer.clear();

StringBuffer sb=new StringBuffer();

Thread.sleep(500);

while((num=sc.read(buffer))>0){

sb.append(new String(buffer.array(),0,num));

buffer.clear();

}

if(sb.length()>0) System.out.println(sb.toString());

if(sb.toString().toLowerCase().trim().equals("bye")){

System.out.println("closed....");

sc.close();

sc.socket().close();

rkb.close();

running=false;

}

} catch (InterruptedException ex) {

Logger.getLogger(MySocketClient.class.getName()).log(Level.SEVERE, null, ex);

} catch (IOException ex) {

Logger.getLogger(MySocketClient.class.getName()).log(Level.SEVERE, null, ex);

}

}

}

public void run() {

init();

execute();

}

class ReadKeyBoard implements Runnable{

boolean running2=true;

public ReadKeyBoard(){

}

public void close(){

running2=false;

}

public void run() {

BufferedReader reader=new BufferedReader(new InputStreamReader(System.in));

while(running2){

try {

System.out.println("enter some commands:");

String str = reader.readLine();

sc.write(ByteBuffer.wrap(str.getBytes()));

} catch (IOException ex) {

Logger.getLogger(ReadKeyBoard.class.getName()).log(Level.SEVERE, null, ex);

}

}

}

}

}

總結:

1. 服務器端一定注意注冊需要的操作,不要注冊不需要的操作。比如在連接被接受后,其實scoket是可以讀和可以寫的。這里的注冊讀的話,那么意味著,只有真的有數據來了,才會接到消息。但是隨時可以寫,如果這個時候注冊讀寫的話(sc.register(selector, SelectionKey.OP_READ|SelectionKey.OP_WRITE);),那么服務器就會進入cpu 100%的狀態。所以當連接剛被接受的時候,一定要注冊讀sc.register(selector, SelectionKey.OP_READ);

2. 服務器端寫有兩種方法:一種就是直接寫。第二種是加入ATTACH,然后,通過skey.interestOps(skey.interestOps()|SelectionKey.OP_WRITE);把寫消息寫到interestOps集合中。就出發了可寫的通知了。注意第二種方式,在接到可寫的通知后,處理完了消息后,還是得恢復只對寫有興趣的interestOps 如key.interestOps(SelectionKey.OP_READ);

3. 得到所有服務器端的連接的方式是key.selector().keys(),但是一定記得,里面有一個是SocketServerChannel注冊的key,這個只可以接受連接,其他的什么都做不了。更不能寫數據給客戶端。所以一定記得剔除這個。不然程序會拋異常。

4. 客戶端比較簡單,所以可以用select的方式,也可以不用。

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的java nio.2群发_JAVA NIO TCP SOCKET 聊天群发的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。