gpt4 book ai didi

java - 服务器端的 webSockets 连接管理

转载 作者:行者123 更新时间:2023-11-28 22:21:25 25 4
gpt4 key购买 nike

我在服务器端使用网络套接字。我设法建立了从应用程序到服务器的连接,并向每个打开的连接发送消息/通知。我想要的是

-如何识别连接(即打开的 websocket)以便用户可以向特定用户发送消息/通知(通过 websocket)。这是我的代码,首先是桌面客户端代码。

if( e.getSource() == connect ) {
try {
cc = new WebSocketClient( new URI( "http://localhost:8080/webSocket/chatServlet"), (Draft) draft.getSelectedItem() ) {
@Override
public void onMessage( String message ) {
ta.append( "got: " + message + "\n" );
ta.setCaretPosition( ta.getDocument().getLength() );
}
@Override
public void onOpen( ServerHandshake handshake ) {
ta.append( "You are connected to ChatServer: " + getURI() + "\n" );
ta.setCaretPosition( ta.getDocument().getLength() );
}

@Override
public void onClose( int code, String reason, boolean wasClean ) {
ta.append( "You have been disconnected from: " + getURI() + "; Code: " + code + " " + reason + "\n" );
System.out.println("the reason for disconnection is ........ "+wasClean);
ta.setCaretPosition( ta.getDocument().getLength() );
connect.setEnabled( true );
uriField.setEditable( true );
draft.setEditable( true );
close.setEnabled( false );
}

@Override
public void onError( Exception ex ) {
ta.append( "Exception occured ...\n" + ex + "\n" );
ta.setCaretPosition( ta.getDocument().getLength() );
ex.printStackTrace();
connect.setEnabled( true );
uriField.setEditable( true );
draft.setEditable( true );
close.setEnabled( false );
}
};

close.setEnabled( true );
connect.setEnabled( false );
uriField.setEditable( false );
draft.setEditable( false );
cc.connect();
} catch ( URISyntaxException ex ) {
ta.append( uriField.getText() + " is not a valid WebSocket URI\n" );
}
} else if( e.getSource() == close ) {
cc.close();
}
}

现在这是服务器端代码...

public class SocketListener extends WebSocketServlet {

/**
*
*/
private static final long serialVersionUID = 1L;
private static ArrayList<MyStreamBound> mmiList = new ArrayList<MyStreamBound>();
private HttpServletRequest request;
private String clientName;
private String zone;
private String subId;
@Override
protected StreamInbound createWebSocketInbound(String protocol) {
System.out.println("protocol values are..."+protocol);
return new MyStreamBound();

}



private class MyStreamBound extends StreamInbound{
WsOutbound myoutbound;


public MyStreamBound(){
super();

}
@Override
public void onOpen(WsOutbound outbound){
try {


System.out.println("Open Client."+outbound.toString()+" and value of this "+this.toString());
this.myoutbound = outbound;
mmiList.add(this);
outbound.writeTextMessage(CharBuffer.wrap("Hello!"));

} catch (IOException e) {
e.printStackTrace();
}
}


@Override
protected void onBinaryData(InputStream arg0) throws IOException {
// TODO Auto-generated method stub

}

@Override
protected void onTextData(Reader recievedData) throws IOException {
BufferedReader in = new BufferedReader(recievedData);
String line = null;
StringBuilder rslt = new StringBuilder();
while ((line = in.readLine()) != null) {
rslt.append(line);
}
System.out.println(rslt.toString());

for(MyStreamBound mmib: mmiList){
CharBuffer buffer = CharBuffer.wrap(rslt.toString());
mmib.myoutbound.writeTextMessage(buffer);
mmib.myoutbound.flush();

}

}

@Override
protected void onClose(int status){
System.out.println("Close Client."+status);
mmiList.remove(this);
}


}

最佳答案

我最近遇到了同样的问题。

你有一些选择......

  1. 创建您的 MyStreamBound,在构造函数中获取 SessionID,因此您的 mmib 中的每个对象都有一个唯一的 ID。

    protected StreamInbound createWebSocketInbound(String protocol, HttpServletRequest req) {
    System.out.println("protocol values are..."+protocol);
    return new MyStreamBound(req.getSession().getId());
    }
  2. 也许连接到前一个以使其更安全。连接时,发送第一条消息作为握手,发送有关用户的信息。您可以将此信息存储为 MyStreamBound 对象实例中的字段。

对于这两种情况,您都可以根据需要在 for 语句中验证此值。

除了你的问题,作为建议,我对你使用的语法有疑问:

    for(MyStreamBound mmib: mmiList){
CharBuffer buffer = CharBuffer.wrap(rslt.toString());
mmib.myoutbound.writeTextMessage(buffer);
mmib.myoutbound.flush();

}

它从 mmiList 生成一个迭代器,如果您有多个并发访问(这就是 WebSocket 的用途),它将导致异常。我是这样写的(即使它看起来不太好):

    for(int i = 0; i < mmiList.size(); i++) {
MyStreamBound mmib = mmiList.get(i);
CharBuffer buffer = CharBuffer.wrap(rslt.toString());
mmib.myoutbound.writeTextMessage(buffer);
mmib.myoutbound.flush();

}

这样你就不会搞乱创建集合并使代码线程安全。事实上,我对此有点失望,但这就是增强的 for 循环在 Java 中的工作方式。

普通的 for 循环效率不高。我不明白为什么 mmiList 不是线程安全集合,它没有任何意义。您也可以检查这些替代方案:Thread-safe iteration over a collection如果您不想使用普通的 for 循环。

关于java - 服务器端的 webSockets 连接管理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16767016/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com