java中异步socket类的实现和源代码
java中异步socket类的实现和源代码
我们知道,java中socket类一般操作都是同步进行,常常在read的时候socket就会阻塞直到有数据可读或socket连接断开的时候才返回,虽然可以设置超时返回,但是这样比较低效,需要做一个循环来不停扫描数据是否可读。看来,在同一个线程中,要是想实现异步读写不太容易。
下面介绍的这个类实现了伪异步socket通讯。基本思想就是在现有socket类的基础上进行封装,当socket连接建立成功后,立即创建一个socket数据接收线程,专门负责阻塞式的socket读取(read),而当前线程负责数据的发送(send)。另外定义了一个接口,包括了socket的各种事件的回调。我们要实现这个接口,在接口实现类中创建异步socket对象,并且传递接口类到异步socket对象中,目的是有socket事件的时候回调我们的方法。
下面是接口:
SocketExHandler.java
package com.ly.net;
import java.net.*;
/**
* Title:
* Description:
* Copyright: Copyright (c) 2001
* Company: http://dozb.blogchina.com
* @author dozb
* @version 1.0
*/
/**
* 异步Socket Client Interface
* 使用方法:
* 1.定义类 MySocketClientEx 实现SocketExHandler接口,实现 OnReceive OnClose OnConnect 事件
* 2.在类中实现start方法 MySocketEx = new SocketEx(this,ip,port)
* 3.在类中实现stop方法 delete MySocketEx
* 4.当有数据到达时会触发OnReceive事件
* 5.当对方SOCKET关闭时会触发OnClose事件
* 6.当SOCKET建立时会触发OnConnect事件
*/
/**
* 异步Socket Server Interface
* 使用方法:
* 1.定义类 MySocketServerEx 实现SocketExHandler接口,实现 OnReceive OnListen OnClose OnAccept 事件
* 2.在类中实现start方法 MySocketEx = new ServerSocketEx(this,ip,port)
* 3.在类中实现stop方法 delete MySocketEx
* 4.当开始监听时会触发OnListen事件
* 5.当SOCKET关闭时会触发OnClose事件
* 6.当有客户端SOCKET要建立连接时会触发OnAccept事件
*/
public interface SocketExHandler
{
//当客户端sock数据到达时触发
public void OnReceive(Object socket,byte buf[],int nLen);
//当客户端sock连接建立成功时触发
public void OnConnect(Object socket);
//当服务端sock监听开始时触发
public void OnListen(Object socket);
//当服务端sock接受一个新的sock连接时触发
public void OnAccept(Object socket,SocketEx ClientSocket) ;
//当sock关闭时触发
public void OnClose(Object socket);
}
下面是异步客户端socket类:
SocketEx.java
package com.ly.net;
import java.io.*;
import java.net.*;
import java.util.*;
import com.ly.net.SocketExHandler;
/**
* Title:
* Description:
* Copyright: Copyright (c) 2001
* Company: http://dozb.blogchina.com
* @author dozb
* @version 1.0
*/
public class SocketEx implements Runnable
{
public static final boolean isdebug = true;//调试
/**
*构造函数.
*/
public SocketEx(SocketExHandler seh,Socket ClientSocket){this.seh = seh;thisSocket = ClientSocket; InitNotify();}
public SocketEx(SocketExHandler seh,String host,int port) throws IOException {this.seh = seh;thisSocket = new Socket(host,port);InitNotify();}
public SocketEx(SocketExHandler seh, InetAddress address, int port ) throws IOException {this.seh = seh;thisSocket = new Socket(address, port);InitNotify();}
public SocketEx(SocketExHandler seh, String host, int port, InetAddress localAddr, int localPort ) throws IOException {this.seh = seh;thisSocket = new Socket(host,port,localAddr,localPort );InitNotify();}
public SocketEx(SocketExHandler seh, InetAddress address, int port, InetAddress localAddr, int localPort ) throws IOException {this.seh = seh;thisSocket = new Socket(address, port, localAddr,localPort );InitNotify();}
/**
* 实现Socket的可见方法.
*/
public synchronized void close() throws IOException {IsRunning = false;thisSocket.close();}
public InetAddress getInetAddress() {return thisSocket.getInetAddress();}
public InputStream getInputStream() throws IOException{ return thisSocket.getInputStream(); }
public InetAddress getLocalAddress() { return thisSocket.getLocalAddress() ; }
public int getLocalPort() { return thisSocket.getLocalPort() ; }
public OutputStream getOutputStream() throws IOException{return thisSocket.getOutputStream(); }
public int getPort() { return thisSocket.getPort() ; }
public int getSoLinger() throws SocketException{ return thisSocket.getSoLinger(); }
public synchronized int getSoTimeout() throws SocketException { return thisSocket.getSoTimeout(); }
public boolean getTcpNoDelay() throws SocketException { return thisSocket.getTcpNoDelay(); }
public void setSoLinger( boolean on, int val ) throws SocketException { thisSocket.setSoLinger(on,val); }
public synchronized void setSoTimeout( int timeout ) throws SocketException {thisSocket.setSoTimeout( timeout ) ; }
public void setTcpNoDelay( boolean on ) throws SocketException {thisSocket.setTcpNoDelay(on); }
public String toString() { return thisSocket.toString() ; }
/**
* 获取Socket
*/
public Socket GetSocket(){return thisSocket;}
/**
* 初始化异步Socket
*/
private void ShowMsg(String Msg)
{
if(isdebug)
System.out.println(Msg);
}
private void InitNotify()
{
if(NotifyThread != null) return ;
try{
biStream = new BufferedInputStream(getInputStream());
thisSocket.setSoTimeout(0);
}catch(IOException e){
ShowMsg("InitNotify() IOException.");
}
IsRunning = true;
NotifyThread = new Thread(this,"SocketEx_NoitfyThread");
NotifyThread.setDaemon(true);
NotifyThread.start();
if(seh !=null)
seh.OnConnect(this);
}
/**
* 关闭Socket
*/
private void Close()
{
try{
close();
}catch(Exception eclose){
ShowMsg("Close() Exception.");
}
}
protected void finalize() throws Throwable
{
Close();
super.finalize();
}
/**
* Thread 运行
*/
public void run()
{
while(IsRunning){
try{
if(getInputStream().read(buf,0,1) <= 0)//试读一个字节
{
DoClose();
return ;
}
if(!DoReceive(getInputStream().available()))
return ;
}catch(Exception e){
ShowMsg("run() Exception.");
DoClose();
return ;
}
try{
Thread.sleep(0); //
}catch(InterruptedException e){
ShowMsg("run() InterruptedException.");
DoClose();
return ;
}
}
}
/**
* 当有数据到达时的回调方法.
*/
private boolean DoReceive(int nCanReadCount)
{
try{
int len = 0,nCurrReadCount=0,nStart=1;
do{
for(int i=nStart;i< BUFLEN;i++)
buf[i]=0;
if(nCanReadCount == 0)
{
if(seh !=null)
seh.OnReceive(this,buf,nStart);
return true;
}
if(nCanReadCount >(BUFLEN-2))
{
nCurrReadCount = BUFLEN-2;
}
else
{
nCurrReadCount = nCanReadCount;
}
len = biStream.read(buf,nStart,nCurrReadCount);
if(len == 0)
{
DoClose();
return false;
}
nCanReadCount -= len;
buf[len+nStart] = 0;
if(seh !=null)
seh.OnReceive(this,buf,len+nStart);
nStart = 0;
}while(nCanReadCount >0);
}catch(Exception excpt){
ShowMsg("DoReceive() Exception.");
DoClose();
return false;
}
return true;
}
/**
* 当Socket建立连接时的回调方法.
*/
private void DoConnect()
{
if(seh !=null)
seh.OnConnect(this);
}
/**
* 当Socket关闭时的回调方法.
*/
private void DoClose()
{
try{
if(IsRunning)
{
Close();
if(seh !=null)
seh.OnClose(this);
IsRunning = false;
}
}catch(Exception e){
ShowMsg("DoClose() Exception.");
}
}
/**
* 以下实现不要改动!!!!
*/
private Thread NotifyThread=null;
private boolean IsRunning = false;
private Socket thisSocket = null;
private static final int BUFLEN = 4097;
private byte buf[] = new byte[BUFLEN];
private BufferedInputStream biStream = null;
private SocketExHandler seh=null;
}
下面是异步socketserver类:
ServerSocketEx .java
package com.ly.net;
import java.io.*;
import java.net.*;
import java.util.*;
/**
* Title:
* Description:
* Copyright: Copyright (c) 2001
* Company: http://dozb.blogchina.com
* @author dozb
* @version 1.0
*/
public class ServerSocketEx extends ServerSocket implements Runnable
{
/**
* 以下实现不要改动!!!!
*/
public ServerSocketEx(SocketExHandler seh, int port ) throws IOException {super(port);this.seh = seh; Listen();}
public ServerSocketEx(SocketExHandler seh, int port, int backlog ) throws IOException {super(port,backlog);this.seh = seh; Listen();}
public ServerSocketEx(SocketExHandler seh, int port, int backlog, InetAddress bindAddr ) throws IOException {super(port,backlog, bindAddr);this.seh = seh;Listen();}
public void setTimeout(int timeout) {
this.timeout = timeout;
}
public static Vector GetClientPool(){return ClientPool;};
public static void CloseAllClients(){
for(int i=0;i< ClientPool.size();i++)
{
try{
SocketEx s=(SocketEx)ClientPool.elementAt(i);
if(s != null) s.close();
}catch(Exception e){}
}
ClientPool.removeAllElements();
}
public static void PutClient(SocketEx s){ClientPool.addElement(s);};
/**
* 关闭Socket
*/
public void Close()
{
IsRunning = false;
try{
close();
}catch(Exception eclose){
}
}
protected void finalize() throws Throwable
{
Close();
super.finalize();
}
/**
* Thread 运行
*/
public void run()
{
while(IsRunning){
acceptConnections();
}
DoClose();
}
// -------------------- Private methods
private void Listen() throws IOException
{
InitNotify();
if(seh !=null)
seh.OnListen(this);
}
/**
* 初始化异步Socket
*/
private void InitNotify()throws IOException
{
if(NotifyThread != null) return ;
try{
setSoTimeout(this.timeout);
} catch( IOException ex ) {
IsRunning=false;
throw ex;
}
IsRunning = true;
NotifyThread = new Thread(this,"ServerSocketEx_NoitfyThread");
NotifyThread.setDaemon(true);
NotifyThread.start();
}
/**
* 当Socket关闭时的回调方法.
*/
private void DoClose()
{
try{
if(seh !=null)
seh.OnClose(this);
//NotifyThread.stop();
}catch(Exception e){
}
}
private void processSocket(Socket s) throws IOException
{
SocketEx se = new SocketEx(seh,s);
PutClient(se);
if(seh !=null)
seh.OnAccept(this,se);
}
private void acceptConnections() {
try {
if(IsRunning == false)
return;
Socket socket = acceptSocket();
if(IsRunning != false && socket != null) {
processSocket(socket);
}
} catch(Throwable e) {
IsRunning = false;
}
}
private Socket acceptSocket() {
Socket accepted = null;
try {
if(IsRunning == true) {
accepted = accept();
if(IsRunning == false) {
if(null != accepted) {
accepted.close(); // rude, but unlikely!
accepted = null;
}
}
}
} catch(InterruptedIOException iioe) {
// normal part -- should happen regularly so
// that the endpoint can release if the server
// is shutdown.
// you know, i really wish that there was a
// way for the socket to timeout without
// tripping an exception. Exceptions are so
// 'spensive.
} catch (SocketException e) {
if (IsRunning != false) {
IsRunning = false;
}
} catch(Throwable e) {
IsRunning = false;
}
return accepted;
}
private static final int TIMEOUT = 5000;
private int timeout = TIMEOUT;
private Thread NotifyThread=null;
private boolean IsRunning=false;
private SocketExHandler seh=null;
private static Vector ClientPool=new Vector();
}
下面是几个工具类:
TimerClient.java
package com.ly.util;
/**
* TimerClient Interface
*
* @version 1.0, 8 October 1995
*
*/
public interface TimerClient
{
void timerEvent(int id);
}
TimerCtl.java
package com.ly.util;
import java.util.Vector;
import java.util.Enumeration;
//import com.borland.jb.util.Diagnostic;
/**
* Timer Component
*
* Note:
* - The successful operation of this timer requires clients to execute simple, short
* code snippets when called back by the engine. Otherwise the queue's delivery
* mechanism will be held up
*
* Further work:
* - When Thread.Interrupt is implemented we can switch from the busy wait model to
* the calculated wait model. Without the interrupt the thread waits for the
* calculated interval before waking up. This is a problem if another shorter
* request arrives. For now we'll assume the minimum resolution of the timer is
* 100ms.
*
* @version 1.0, 2 October 1995
*
*/
public class TimerCtl
{
static TimerTasks timerTasks;
public TimerCtl() {
}
/*
* Start a timer running
*/
public static void startTimer(TimerClient client, int eventId, long delay, boolean repeat) {
// create the timer if necessary
if (timerTasks == null) {
timerTasks = new TimerTasks();
timerTasks.start();
}
//Diagnostic.out.println("TIMER: startTimer"+eventId);
// add the new task to the queue
timerTasks.add(client, eventId, delay, repeat);
}
/*
* Stop a timer
*/
public static void stopTimer(TimerClient client, int eventId) {
//Diagnostic.out.println("TIMER: stopTimer"+eventId);
if(timerTasks != null)
timerTasks.end(client, eventId);
}
}
class TimerTasks extends Thread
{
Vector tasks = new Vector();
boolean suspended = false;
boolean sleeping = false;
/**
* Thread task runner
*/
public void run() {
// Loop forever
while (true) {
long sleepTime = 0;
// Ensure that the tasks class is protected
synchronized (tasks) {
//Diagnostic.out.println("TIMER: Tick");
// Scan the job list for any jobs which may fire.
// Mark one-shot jobs for deletion
// Calculate the maximum time we can sleep for
sleepTime = scan();
// Delete DeletePending jobs. DeletePending jobs result from one-shots which have
// been sent, and repeat jobs which have been cancelled. Jobs may have been
// cancelled during the Scan process.
purge();
}
// Suspend timer if necessary
if (tasks.size() == 0) {
//Diagnostic.out.println("TIMER: Suspend");
try {
synchronized(this) {
suspended = true;
wait();
}
}
catch (InterruptedException e) {
}
}
else {
//Diagnostic.out.println("TIMER: Suggested Sleeping for "+sleepTime);
if (sleepTime >= 0) {
try {
sleeping = true;
sleep(sleepTime);
sleeping = false;
}
catch (InterruptedException i) {
//Diagnostic.out.println("TIMER: Caught me napping");
}
}
}
}
}
/**
* Add a new task
*/
public void add(TimerClient client, int eventId, long delay, boolean repeat) {
TimerTask t = new TimerTask(client, eventId, delay, repeat);
synchronized (tasks) {
tasks.addElement((Object)t);
}
// Want instant response - wake the thread if it's napping
// unfortunately the interrupt() method is not working
// if (sleeping)
// interrupt();
if (suspended) {
synchronized(this) {
notify();
//Diagnostic.out.println("TIMER: Resume");
suspended = false;
}
}
}
/**
* Find the job and mark it for deletion
*/
public void end(TimerClient client, int eventId) {
synchronized (tasks) {
for (int i = 0; i < tasks.size(); i++) {
TimerTask t = (TimerTask)tasks.elementAt(i);
//if (!t.deletePending && t.client == client && t.eventId == eventId)
if (t.deletePending == false && t.client == client && t.eventId == eventId) {
// JPBS - if we don't reset 'repeat', deletePending will be set again
t.repeat = false;
t.deletePending = true;
break;
}
}
}
}
/**
* Clear out all the dead wood
*/
void purge() {
for (int i = 0; i < tasks.size(); i++) {
TimerTask t = (TimerTask)tasks.elementAt(i);
if (t.deletePending) {
//Diagnostic.out.println("TIMER: purged");
tasks.removeElementAt(i);
i--;
}
}
}
long scan() {
// The value added to the current time determines the MAX time until
// the next scan
// This is 100 now since thread.interrupt() is not implemented
long nextTime = System.currentTimeMillis() + 100;
for (int i = 0; i < tasks.size(); i++) {
TimerTask t = (TimerTask)tasks.elementAt(i);
// if not already deletePending, test (and possibly send the event)
// as a result, the job may be flagged for deletion.
// May also be a non-repeating job and so require self deletion
if (!t.deletePending)
t.test();
// if the task didn't get deleted - see what it contributes to the time
if (!t.deletePending)
nextTime = Math.min(nextTime, t.timeNext);
//Diagnostic.out.println("TIMER: Scanning "+t.eventId+" "+(t.deletePending == true ? "DEL" : ""));
}
return nextTime - System.currentTimeMillis();
}
}
class TimerTask
{
TimerClient client;
int eventId;
long timePrev;
long timeDelay;
long timeNext;
boolean repeat;
boolean deletePending;
public TimerTask(TimerClient client, int eventId, long timeDelay, boolean repeat) {
this.client = client;
this.eventId = eventId;
this.timeDelay = timeDelay;
this.repeat = repeat;
// schedule the next click - now + delay
timeNext = System.currentTimeMillis() + timeDelay;
deletePending = false;
//Diagnostic.out.println("TIMER: Adding New Task");
}
public void test() {
if (System.currentTimeMillis() >= timeNext) {
//Diagnostic.out.println("TIMER: fire");
// Fire the event
client.timerEvent(eventId);
// Update the next time
timeNext = System.currentTimeMillis() + timeDelay;
deletePending = !repeat;
}
}
}
下面是使用上面的异步socket类,做的demo开发
DemoAppSocketHandler.java
package com.ly.net;
import java.net.*;
import java.util.*;
/**
* Title:
* Description:
* Copyright: Copyright (c) 2001
* Company: http://dozb.blogchina.com
* @author dozb
* @version 1.0
*/
public interface DemoAppSocketHandler
{
//当客户端sock有数据到达时触发
public void OnProcessCmd(Object socket,String FromArea,String ToArea,String ChannNo,String MainFun,String SubFun,Vector ParamList);
//当客户端sock连接建立成功时触发
public void OnConnect(Object socket);
//当服务端sock监听开始时触发
public void OnListen(Object socket);
//当服务端sock接受一个新的sock连接时触发
public void OnAccept(Object socket,SocketEx ClientSocket) ;
//当sock关闭时触发
public void OnClose(Object socket);
}
DemoAppSocket.java
package com.ly.net;
import java.io.*;
import java.util.*;
import com.ly.util.*;
/**
* Title:
* Description:
* Copyright: Copyright (c) 2001
* Company: http://dozb.blogchina.com
* @author dozb
* @version 1.0
*/
//这个类是异步socket 客户端和服务端的使用演示
//对于客户端,实现了断开后自动连接
//这个类是SocketExHandler 和 TimerClient 接口的实现
public class DemoAppSocket implements SocketExHandler,TimerClient{
//Sock构造函数
public DemoAppSocket(DemoAppSocketHandler issh,boolean isServer,String ip,int port) {
this.issh = issh;
this.isServer = isServer;
this.ip = ip;
if(this.ip == null) this.ip = "";
this.port = port;
if(this.port <0) this.port = 0;
}
//调用完构造后调用这个函数创建sock对象
public void create()
{
if(!start())
TimerCtl.startTimer(this,eventId,30*1000,true);
}
//这个方法一般不需要直接调用
public boolean start()
{
if(this.isServer) return startServer(); else return startClient();
}
//停止socket
public void stop()
{
TimerCtl.stopTimer(this,eventId);
if(this.isServer) stopServer(); else stopClient();
}
//发送socket消息
public boolean SendCmd(Object socket,String strCmd)
{
SocketEx currSocketEx = (SocketEx)socket;
if(!isServer && currSocketEx==null) currSocketEx = socketEx;
if(currSocketEx == null) return false;
try{
PrintWriter Sender = new PrintWriter(currSocketEx.getOutputStream(),true);
Sender.print(strCmd);
Sender.flush();
return true;
}catch(Exception e)
{
return false;
}
}
//发送socket消息
public boolean SendCmd(Object socket,String FromArea,String ToArea,String ChannNo,String MainFun,String SubFun,String Param)
{
String strCmd = FromArea + ToArea + ChannNo + MainFun+SubFun+"&"+Param+"&";
return SendCmd(socket,strCmd);
}
//获得IP地址
public String getIp()
{
return ip;
}
//获得端口号
public int getPort()
{
return port;
}
protected boolean startClient()
{
if(socketEx != null) {
try{
socketEx.close();
}catch(IOException e){};
socketEx = null;
}
try{
socketEx = new SocketEx(this,ip,port);
TimerCtl.stopTimer(this,eventId);
return true;
}catch(IOException e)
{
socketEx = null;
}
return false;
}
protected boolean startServer()
{
if(serverSocketEx != null) {
try{
serverSocketEx.close();
}catch(IOException e){};
serverSocketEx = null;
}
try{
serverSocketEx = new ServerSocketEx(this,port);
TimerCtl.stopTimer(this,eventId);
return true;
}catch(IOException e)
{
serverSocketEx = null;
}
return false;
}
protected void stopServer()
{
if(serverSocketEx != null) {
try{
serverSocketEx.close();
}catch(IOException e){};
serverSocketEx = null;
}
}
protected void stopClient()
{
if(socketEx != null) {
try{
socketEx.close();
}catch(IOException e){};
socketEx = null;
}
}
public void timerEvent(int id)
{
start();
}
static public String[] DealStr(String strS)
{
int CMDHEAD_LEN = 22;
String[] ret = new String[2];//0留下的字符串1完整的CMD
ret[0]=strS;//
//假如只有一个&或没有&则不完整
int FirstPos=strS.indexOf("&");
if(FirstPos==-1)
return ret;
if(FirstPos != CMDHEAD_LEN-1)
{
strS = strS.substring(FirstPos+1);
return DealStr(strS);
}
int nSecondPos = strS.indexOf("&",FirstPos+1);
if(nSecondPos<0)
return ret;
//可能格式不正确了
if(strS.length()< CMDHEAD_LEN)
return ret;
ret[1] = strS.substring(0,nSecondPos+1);
ret[0]=strS.substring(nSecondPos+1);
return ret;
}
public void OnReceive(Object socket,byte buf[],int nLen){
String ReceiveBuff = sReceiveBuf + (new String(buf,0,nLen));
do//分解成单个的命令串
{
String strCmd[] = DealStr(ReceiveBuff);
ReceiveBuff = strCmd[0];
if(strCmd[1]==null || strCmd[1].equals("")) break;
System.out.println(strCmd[1]);
String FromArea=strCmd[1].substring(0,6);
String ToArea=strCmd[1].substring(6,12);
String ChannNo=strCmd[1].substring(12,15);
String MainFun=strCmd[1].substring(15,18);
String SubFun=strCmd[1].substring(18,21);
String Param =strCmd[1].substring(22,strCmd[1].length()-1);
Vector ParamList=new Vector();
int nLastPos=0;
while(true)
{
int nPos = Param.indexOf(",",nLastPos);
if(nPos <0)
{
ParamList.add(Param.substring(nLastPos));
// System.out.println(Param.substring(nLastPos));
break;
}
String sParam = Param.substring(nLastPos,nPos);
ParamList.add(sParam);
// System.out.println(sParam);
nLastPos = nPos+1;
}
DoProcessCmd(socket,FromArea,ToArea,ChannNo,MainFun,SubFun,ParamList);
}while(true);
sReceiveBuf = ReceiveBuff;
if(sReceiveBuf == null) sReceiveBuf=null;
}
protected void DoProcessCmd(Object socket,String FromArea,String ToArea,String ChannNo,String MainFun,String SubFun,Vector ParamList)
{
if(issh !=null)
issh.OnProcessCmd(socket,FromArea,ToArea,ChannNo,MainFun, SubFun, ParamList);
}
public void OnConnect(Object socket)
{
if(issh !=null) issh.OnConnect(socket);
}
public void OnListen(Object socket){
if(issh !=null) issh.OnListen(socket);
}
public void OnAccept(Object socket,SocketEx ClientSocket) {
if(issh !=null) issh.OnAccept(socket,ClientSocket);
}
public void OnClose(Object socket){
notifyAll();
TimerCtl.startTimer(this,eventId,30*1000,true);
if(issh !=null) issh.OnClose(socket);
}
//Socket
SocketEx socketEx = null;
ServerSocketEx serverSocketEx=null;
final int eventId = 1;
String sReceiveBuf="";
DemoAppSocketHandler issh=null;
boolean isServer=false;
String ip="127.0.0.1";
int port=20000;
}
通过这种方式,可以高效地使用socket通讯,在异步socket版本没有发布以前,不失是一种解决问题的方法。:)
相关文章:
java中异步socket类的实现和源代码
java中异步socket类的实现和源代码 我们知道,java中socket类一般操作都是同步进行,常常在read的时候socket就会阻塞直到有数据可读或socket连接断开的时候才返回,虽然可以设置超时返回,但是这样比较低效,需要做一个循环来不停扫描…...
ElasticSearch7.6入门学习笔记
在学习ElasticSearch之前,先简单了解一下Lucene: Doug Cutting开发 是apache软件基金会4 jakarta项目组的一个子项目 是一个开放源代码的全文检索引擎工具包不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的…...
《面试1v1》ElasticSearch架构设计
🍅 作者简介:王哥,CSDN2022博客总榜Top100🏆、博客专家💪 🍅 技术交流:定期更新Java硬核干货,不定期送书活动 🍅 王哥多年工作总结:Java学习路线总结…...
tomcat和nginx的日志记录请求时间
当系统卡顿时候,我们需要分析时间花费在哪个缓解。项目的后端接口可以记录一些时间,此外,在我们的tomcat容器和nginx网关上也可以记录一些有关请求用户,请求时间,响应时间的数据,可以提供更多的信息以便于排…...
数据结构——红黑树基础(博文笔记)
数据结构在查找这一章里介绍过这些数据结构:BST,AVL,RBT,B和B。 除去RBT,其他的数据结构之前的学过,都是在BST的基础上进行微小的限制。 1.比如AVL是要求任意节点的左右子树深度之差绝对值不大于1,由此引出…...
盘点帮助中心系统可以帮到我们什么呢?
在线帮助中心系统是一种强大的软件系统,可以让我们用来组织、管理、发布、更新和维护企业的宝贵知识库和用户文档。今天looklook就详细讲讲,除了大众所熟知的这些,帮助中心系统还有什么特别作用呢? 帮助中心系统的作用 1.快速自助…...
Web3 solidity编写交易所合约 编写ETH和自定义代币存入逻辑 并带着大家手动测试
上文 Web3 叙述交易所授权置换概念 编写transferFrom与approve函数我们写完一个简单授权交易所的逻辑 但是并没有测试 其实也不是我不想 主要是 交易所也没实例化 现在也测试不了 我们先运行 ganache 启动一个虚拟的区块链环境 先发布 在终端执行 truffle migrate如果你跟着我…...
概念解析 | 生成式与判别式模型在低级图像恢复与点云重建中的角力:一场较量与可能性探索
注1:本文系“概念解析”系列之一,致力于简洁清晰地解释、辨析复杂而专业的概念。本次辨析的概念是:生成式模型与判别式模型在低级图像恢复/点云重建任务中的优劣与特性。 生成式与判别式模型在低级图像恢复与点云重建中的角力:一场较量与可能性探索 1. 背景介绍 机器学习…...
【云原生】kubectl命令的详解
目录 一、陈述式资源管理方式1.1基本查看命令查看版本信息查看资源对象简写查看集群信息配置kubectl自动补全node节点查看日志 1.3基本信息查看查看 master 节点状态查看命名空间查看default命名空间的所有资源创建命名空间app删除命名空间app在命名空间kube-public 创建副本控…...
uniapp两个单页面之间进行传参
1.单页面传参:A --> B url: .....?code JSON.stringify(param), 2.单页面传参B–>Auni.$emit() uni.$on()...
uniapp运行项目到iOS基座
2022年9月,因收到苹果公司警告,目前开发者已无法在iOS真机设备使用未签名的标准基座,所以现在要运行到 IOS ,也需要进行签名。 Windows系统,HBuilderX 3.6.20以下版本,无法像MacOSX那样对标准基座进行签名…...
HTTP——九、基于HTTP的功能追加协议
HTTP 一、基于HTTP的协议二、消除HTTP瓶颈的SPDY1、HTTP的瓶颈Ajax 的解决方法Comet 的解决方法SPDY的目标 2、SPDY的设计与功能3、SPDY消除 Web 瓶颈了吗 三、使用浏览器进行全双工通信的WebSocket1、WebSocket 的设计与功能2、WebSocket协议 四、期盼已久的 HTTP/2.01、HTTP/…...
Redis 在电商秒杀场景中的应用
Redis 在电商秒杀场景中的应用 一、简介1.1 简介1.2 场景应用 二、Redis 优势与挑战2.1 优势2.2 秒杀场景的挑战 三、应用场景分析3.1 库存预热代码示例 3.2 分布式锁3.3 消息队列 四、系统设计方案4.1 架构设计4.2 技术选型4.3 数据结构设计 五、Redis 性能优化5.1 集群部署5.…...
大麦订单生成器 大麦一键生成订单
后台一键生成链接,独立后台管理 教程:修改数据库config/Conn.php 不会可以看源码里有教程 下载源码程序:https://pan.baidu.com/s/16lN3gvRIZm7pqhvVMYYecQ?pwd6zw3...
Java实现Google cloud storage 文件上传,Google oss
storage 控制台位置 创建一个bucket 点进bucket里面,权限配置里,公开访问,在互联网上公开,需要配置角色权限 新增一个访问权限 ,账号这里可以模糊搜索, 角色配置 给allUser配置俩角色就可以出现 在互联…...
适配器模式(AdapterPattern)
适配器模式 适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。 优缺点 优点: 单一职责原则。你可以将接口或数据转换代码从程序主要业务逻辑中分…...
Apache Kafka Learning
目录 一、Kafka 1、Message Queue是什么? 2、Kafka 基础架构 3、Kafka安装 4、Offset自动控制 5、Acks & Retries 6、幂等性 7、事务控制 8、数据同步机制 9、Kafka-Eagle 二、Maven项目测试 1、Topic API 2、生产者&消费者 一、Kafka Kafka是…...
手把手教你用idea实现Java连接MySQL数据库
目录 1.下载MySQL 2.下载mysql 的jdbc驱动 3.将驱动jar包导入idea 4.通过Java测试数据库是否连接成功 1.下载MySQL 首先如果没有mysql的需要先下载MySQL,可以看这个教程 MYSQL安装手把手(亲测好用)_程序小象的博客-CSDN博客 2.下载mysql…...
Ubuntu 22.04安装和使用ROS1可行吗
可行。 测试结果 ROS1可以一直使用下去的,这一点不用担心。Ubuntu会一直维护的。 简要介绍 Debian发行版^_^ AI:在Ubuntu 22.04上安装ROS1是可行的,但需要注意ROS1对Ubuntu的支持只到20.04。因此,如果要在22.04上安装ROS1&am…...
83 | Python可视化篇 —— Bokeh数据可视化
Bokeh 是一种交互式数据可视化库,它可以在 Python 中使用。它的设计目标是提供一个简单、灵活和强大的方式来创建现代数据可视化,同时保持良好的性能。Bokeh 支持多种图表类型,包括线图、散点图、柱状图、饼图、区域图、热力图等。此外,它还支持将这些图表组合在一起以创建…...
SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...
零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?
一、核心优势:专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发,是一款收费低廉但功能全面的Windows NAS工具,主打“无学习成本部署” 。与其他NAS软件相比,其优势在于: 无需硬件改造:将任意W…...
无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...
第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...
Rapidio门铃消息FIFO溢出机制
关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系,以下是深入解析: 门铃FIFO溢出的本质 在RapidIO系统中,门铃消息FIFO是硬件控制器内部的缓冲区,用于临时存储接收到的门铃消息(Doorbell Message)。…...
MySQL账号权限管理指南:安全创建账户与精细授权技巧
在MySQL数据库管理中,合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号? 最小权限原则…...
【Go语言基础【13】】函数、闭包、方法
文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数(函数作为参数、返回值) 三、匿名函数与闭包1. 匿名函数(Lambda函…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
论文阅读笔记——Muffin: Testing Deep Learning Libraries via Neural Architecture Fuzzing
Muffin 论文 现有方法 CRADLE 和 LEMON,依赖模型推理阶段输出进行差分测试,但在训练阶段是不可行的,因为训练阶段直到最后才有固定输出,中间过程是不断变化的。API 库覆盖低,因为各个 API 都是在各种具体场景下使用。…...
Vue ③-生命周期 || 脚手架
生命周期 思考:什么时候可以发送初始化渲染请求?(越早越好) 什么时候可以开始操作dom?(至少dom得渲染出来) Vue生命周期: 一个Vue实例从 创建 到 销毁 的整个过程。 生命周期四个…...
