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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

java nio socket长连接_nio实现Socket长连接和心跳

發(fā)布時(shí)間:2023/12/9 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java nio socket长连接_nio实现Socket长连接和心跳 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

前段時(shí)間用bio方式,也就是傳統(tǒng)io實(shí)現(xiàn)了socket的長(zhǎng)連接和心跳,總覺著服務(wù)端開啟多線程管理socket連接的方式過(guò)于消耗資源,數(shù)據(jù)并發(fā)的情況下可能會(huì)影響到性能,因此就嘗試使用nio改進(jìn)原來(lái)的代碼。

然而改進(jìn)的過(guò)程卻不像我起初設(shè)想的那般容易,可以說(shuō)一波三折,原因主要是nio讀寫都是字節(jié)流,LZ一開始依然通過(guò)ObjectOutputStream.writeObject直接向Socket服務(wù)端發(fā)送數(shù)據(jù),然而問(wèn)題出現(xiàn)了,每次從ByteBuffer解析出來(lái)字節(jié)流都不一樣,LZ使出渾身解數(shù),一個(gè)字節(jié)一個(gè)字節(jié)的讀取啊,問(wèn)題沒有了,可是由于是長(zhǎng)連接,數(shù)據(jù)怎么解析啊,查資料,找大神,最后一個(gè)網(wǎng)友說(shuō)有可能是粘包和分包的問(wèn)題,一時(shí)暈菜,LZ網(wǎng)絡(luò)可是渣渣啊,行吧,惡補(bǔ)一番,想了解的童鞋可以看看這個(gè)。http://blog.csdn.net/sunmenggmail/article/details/38952131

實(shí)現(xiàn)原理就像很多協(xié)議那樣,自定義一套傳輸協(xié)議,比如消息長(zhǎng)度(int型,4個(gè)字節(jié))+消息體的方式,根據(jù)解析的消息長(zhǎng)度定長(zhǎng)解析消息內(nèi)容,雖然最后證明LZ的問(wèn)題不是由于粘包和分包造成的,但是LZ就這樣歪打正著,給實(shí)現(xiàn)了!!!數(shù)據(jù)不正常的問(wèn)題后來(lái)通過(guò)DataOutputStream和DataInputStream的方式也得到了解決。

廢話多了,帖代碼。

服務(wù)端:

package com.feng.test.longconnection1;

import java.io.ByteArrayInputStream;

import java.io.ByteArrayOutputStream;

import java.io.IOException;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

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.nio.charset.Charset;

import java.util.Arrays;

import java.util.HashMap;

import java.util.Iterator;

import java.util.Map;

import java.util.concurrent.BlockingQueue;

import java.util.concurrent.LinkedBlockingDeque;

import org.apache.commons.lang.ArrayUtils;

/**

*

* @author songfeng

* @version 1.0

* @since 2015-10-24

* @category com.feng.test.longconnection

*

*/

public class Server

{

private Map heatTimeMap = new HashMap();

public Server(int port)

{

Selector selector = null;

ServerSocketChannel serverChannel = null;

try

{

//獲取一個(gè)ServerSocket通道

serverChannel = ServerSocketChannel.open();

serverChannel.configureBlocking(false);

serverChannel.socket().bind(new InetSocketAddress(port));

//獲取通道管理器

selector = Selector.open();

//將通道管理器與通道綁定,并為該通道注冊(cè)SelectionKey.OP_ACCEPT事件,

//只有當(dāng)該事件到達(dá)時(shí),Selector.select()會(huì)返回,否則一直阻塞。

serverChannel.register(selector, SelectionKey.OP_ACCEPT);

while (selector.select() > 0)

{

//選擇注冊(cè)過(guò)的io操作的事件

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

while (it.hasNext())

{

SelectionKey readyKey = it.next();

//刪除已選key,防止重復(fù)處理

it.remove();

if (readyKey.isAcceptable())

{

ServerSocketChannel serverSocketChannel = (ServerSocketChannel) readyKey.channel();

SocketChannel socketChannel = serverSocketChannel.accept();

socketChannel.configureBlocking(false);

// 連接成功后,注冊(cè)接收服務(wù)器消息的事件

socketChannel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);

}

else if(readyKey.isReadable())

{

SocketChannel socketChannel = (SocketChannel)readyKey.channel();

Object obj = receiveData(socketChannel);

String msg = "Server back:";

if(obj instanceof String)

{

String id = obj.toString().split(",")[0];

if(heatTimeMap.get(id) != null

&& System.currentTimeMillis() - heatTimeMap.get(id) > 5000)

{

socketChannel.socket().close();

}

else

{

heatTimeMap.put(id, System.currentTimeMillis());

}

long time = System.currentTimeMillis();

msg += time + "\n";

sendData(socketChannel, msg);

}

else if(obj instanceof Pojo)

{

msg += ((Pojo)obj).getName() + "\n";

sendData(socketChannel, msg);

}

}

}

}

}

catch (Exception e)

{

e.printStackTrace();

}

finally

{

try

{

selector.close();

if(serverChannel != null)

{

serverChannel.close();

}

}

catch (Exception e)

{

e.printStackTrace();

}

}

}

private static Object receiveData(SocketChannel socketChannel)

{

Object obj = null;

ByteArrayOutputStream baos = new ByteArrayOutputStream();

ByteBuffer intBuffer = ByteBuffer.allocate(4);

ByteBuffer objBuffer = ByteBuffer.allocate(1024);

int size = 0;

int sum = 0;

int objlen = 0;

byte[] bytes = null;

try

{

while((size = socketChannel.read(intBuffer)) > 0)

{

intBuffer.flip();

bytes = new byte[size];

intBuffer.get(bytes);

baos.write(bytes);

intBuffer.clear();

if(bytes.length == 4)

{

objlen = bytesToInt(bytes,0);

}

if(objlen > 0)

{

byte[] objByte = new byte[0];

while(sum != objlen)

{

size = socketChannel.read(objBuffer);

if(size > 0)

{

objBuffer.flip();

bytes = new byte[size];

objBuffer.get(bytes,0,size);

baos.write(bytes);

objBuffer.clear();

objByte = ArrayUtils.addAll(objByte, bytes);

sum += bytes.length;

}

}

obj = ByteToObject(objByte);

break;

}

}

}

catch (Exception e)

{

e.printStackTrace();

}

finally

{

try

{

baos.close();

}

catch (Exception e)

{

e.printStackTrace();

}

}

return obj;

}

private static void sendData(SocketChannel socketChannel,Object obj)

{

byte[] bytes = ObjectToByte(obj);

ByteBuffer buffer = ByteBuffer.wrap(bytes);

try

{

socketChannel.write(buffer);

}

catch (IOException e)

{

e.printStackTrace();

}

}

/**

* byte數(shù)組中取int數(shù)值,本方法適用于(低位在前,高位在后)的順序。

*

* @param ary

* byte數(shù)組

* @param offset

* 從數(shù)組的第offset位開始

* @return int數(shù)值

*/

public static int bytesToInt(byte[] ary, int offset) {

int value;

value = (int) ((ary[offset]&0xFF)

| ((ary[offset+1]<<8) & 0xFF00)

| ((ary[offset+2]<<16)& 0xFF0000)

| ((ary[offset+3]<<24) & 0xFF000000));

return value;

}

public static Object ByteToObject(byte[] bytes)

{

Object obj = null;

try

{

// bytearray to object

ByteArrayInputStream bi = new ByteArrayInputStream(bytes);

ObjectInputStream oi = new ObjectInputStream(bi);

obj = oi.readObject();

bi.close();

oi.close();

}

catch (Exception e)

{

//e.printStackTrace();

}

return obj;

}

public static byte[] ObjectToByte(Object obj)

{

byte[] bytes = null;

try

{

// object to bytearray

ByteArrayOutputStream bo = new ByteArrayOutputStream();

ObjectOutputStream oo = new ObjectOutputStream(bo);

oo.writeObject(obj);

bytes = bo.toByteArray();

bo.close();

oo.close();

}

catch (Exception e)

{

e.printStackTrace();

}

return bytes;

}

public static void main(String[] args)

{

Server server = new Server(55555);

}

}

客戶端:

package com.feng.test.longconnection1;

import java.io.ByteArrayInputStream;

import java.io.ByteArrayOutputStream;

import java.io.DataInputStream;

import java.io.DataOutputStream;

import java.io.IOException;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

import java.net.Socket;

import java.nio.ByteBuffer;

import java.nio.ByteOrder;

import java.util.ArrayList;

/**

*

* @author songfeng

* @version 1.0

* @since 2015-10-24

* @category com.feng.test.longconnection

*

*/

public class Client

{

private Socket socket;

private String ip;

private int port;

private String id;

DataOutputStream dos;

DataInputStream dis;

public Client(String ip, int port,String id)

{

try

{

this.ip = ip;

this.port = port;

this.id = id;

this.socket = new Socket(ip, port);

//this.socket.setKeepAlive(true);

dos = new DataOutputStream(socket.getOutputStream());

dis = new DataInputStream(socket.getInputStream());

new Thread(new heartThread()).start();

new Thread(new MsgThread()).start();

}

catch (Exception e)

{

e.printStackTrace();

}

}

public void sendMsg(Object content)

{

try

{

int len = ObjectToByte(content).length;

ByteBuffer dataLenBuf = ByteBuffer.allocate(4);

dataLenBuf.order(ByteOrder.LITTLE_ENDIAN);

dataLenBuf.putInt(0, len);

dos.write(dataLenBuf.array(), 0 , 4);

dos.flush();

dos.write(ObjectToByte(content));

dos.flush();

}

catch (Exception e)

{

e.printStackTrace();

closeSocket();

}

}

public void closeSocket()

{

try

{

socket.close();

dos.close();

dis.close();

}

catch (IOException e)

{

e.printStackTrace();

}

}

public static byte[] ObjectToByte(Object obj)

{

byte[] bytes = null;

try

{

// object to bytearray

ByteArrayOutputStream bo = new ByteArrayOutputStream();

ObjectOutputStream oo = new ObjectOutputStream(bo);

oo.writeObject(obj);

bytes = bo.toByteArray();

bo.close();

oo.close();

}

catch (Exception e)

{

e.printStackTrace();

}

return bytes;

}

public static Object ByteToObject(byte[] bytes)

{

Object obj = null;

try

{

// bytearray to object

ByteArrayInputStream bi = new ByteArrayInputStream(bytes);

ObjectInputStream oi = new ObjectInputStream(bi);

obj = oi.readObject();

bi.close();

oi.close();

}

catch (Exception e)

{

e.printStackTrace();

}

return obj;

}

class heartThread implements Runnable

{

@Override

public void run()

{

while(true)

{

try

{

Thread.sleep(1000);

long time = System.currentTimeMillis();

//System.out.println("client send:" + time);

sendMsg("Client" + id + "," + time);

}

catch (Exception e)

{

e.printStackTrace();

}

}

}

}

class MsgThread implements Runnable

{

@Override

public void run()

{

int temp;

while(true)

{

try

{

if(socket.getInputStream().available() > 0)

{

byte[] bytes = new byte[1024];

int len = 0;

while((char)(temp = dis.read()) != '\n')

{

bytes[len]=(byte)temp;

len++;

}

System.out.println(ByteToObject(bytes));

}

}

catch (Exception e)

{

closeSocket();

}

}

}

}

public static void main(String[] args)

{

Client client1 = new Client("127.0.0.1", 55555, "1");

client1.sendMsg(new Pojo("songfeng", 26, new ArrayList()));

try

{

Thread.sleep(500);

}

catch (InterruptedException e)

{

e.printStackTrace();

}

Client client2 = new Client("127.0.0.1", 55555, "2");

}

}

數(shù)據(jù)類:

package com.feng.test.longconnection1;

import java.io.Serializable;

import java.util.List;

/**

*

* @author songfeng

* @version 1.0

* @since 2015-10-16

* @category com.feng.test.longconnection

*

*/

public class Pojo implements Serializable

{

/**

* 序列化

*/

private static final long serialVersionUID = -8868529619983791261L;

private String name;

private int age;

private List likeThing;

public Pojo(String name, int age, List likeThing)

{

super();

this.name = name;

this.age = age;

this.likeThing = likeThing;

}

public String getName()

{

return name;

}

public void setName(String name)

{

this.name = name;

}

public int getAge()

{

return age;

}

public void setAge(int age)

{

this.age = age;

}

public List getLikeThing()

{

return likeThing;

}

public void setLikeThing(List likeThing)

{

this.likeThing = likeThing;

}

}

總結(jié)

以上是生活随笔為你收集整理的java nio socket长连接_nio实现Socket长连接和心跳的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。