El servidor TomCat7.0 utiliza la función de mensaje de mensaje completada por WebSocket y Java. Algunas cosas son consideradas por usted, y no sé si son apropiados o inapropiados. Por favor, perdóname y señala.
En términos simples, el cliente A puede enviar mensajes al cliente B, pero hay muchos lugares que se pueden ampliar.
Por ejemplo
1. Si después de unirse a la base de datos, cuando A envía el mensaje, el Cliente B no está en línea, el servidor almacenará el mensaje en la base de datos. Después de que el cliente B esté en línea, el mensaje se recuperará y se enviará al cliente B.
2. El servidor también puede enviar mensajes a cualquier cliente.
La captura de pantalla del efecto de ejecución del programa es el siguiente (probado bajo Chrome, Sogou y Firefox): el código se administrará al final
Primero, abrimos un navegador y visitamos para ingresar su nombre. Aquí entro Soar
Al abrir el segundo navegador, aquí ingreso a Bill
Esto es si envío hello bill, estoy saliendo a factura, haga clic en enviar
Puedes verlo en otro navegador
Websocket
1. ¿Qué es WebSocket?
WebSocket es una tecnología que se genera para resolver la comunicación en tiempo real entre clientes y servidores. La esencia es crear una conexión TCP para intercambiar datos después del apretón de manos a través del protocolo HTTP/HTTPS.
Después de eso, el servidor y el cliente se comunican en tiempo real a través de esta conexión TCP.
2. Ventajas de WebSocket
En el pasado, implementamos Push Technology, utilizando la encuesta. En el intervalo de tiempo característico, el navegador emite automáticamente una solicitud y retira activamente los mensajes del servidor. En este caso, necesitamos enviar constantemente solicitudes al servidor. Sin embargo, el encabezado de la solicitud HTTP es muy largo, y los datos contenidos en él pueden ser solo un pequeño valor, que ocupará mucho ancho de banda y recursos del servidor. Consumirá mucho ancho de banda y recursos del servidor.
Lo mejor de la API de WebSocket es que el servidor y el cliente pueden impulsar información entre sí en cualquier momento dentro de un rango de tiempo determinado. Después de establecer la conexión, el servidor puede transmitir activamente datos al cliente.
Además, la información del encabezado intercambiada entre el servidor y el cliente es muy pequeña.
WebSocket no se limita a la comunicación en el modo Ajax (o XHR), porque la tecnología AJAX requiere que los clientes inicien solicitudes, mientras que los servidores y clientes de WebSocket pueden impulsar la información entre sí;
Para obtener una introducción detallada a los mensajes AJAX, Comet, WebSocket y WebSocket, puede consultar http://www.shaoqun.com/a/54588.aspx Web Design] Ajax, Comet y WebSocket.
Si tengo tiempo en el futuro, lo escribiré.
3. Cómo usar WebSocket
Cliente
En un navegador que admite WebSocket, después de crear el socket. Puede responder a los sockets a través de cuatro eventos: Onopen, OnMessage y OnClose, es decir, OnError.
Un ejemplo simple
var ws = new WebSocket (ws: // localhost: 8080); ws.onopen = function () {console.log (Open); ws.send (hola);}; ws.onmessage = function (evt) {console.log (evt.data)}; ws.onclose = function (evt) {console.log (WebSocketClosed!);}; ws.onerror = function (evt) {console.log (WebSocketerRor!);};};1.Var ws = nuevo WebSocket (ws: // localhost: 8080);
Para solicitar un objeto WebSocket, los parámetros son la dirección del servidor que debe conectarse. Al igual que el protocolo HTTP, la URL del protocolo WebSocket comienza con ws: //, y el protocolo Secure WebSocket comienza con wss: //.
ws.send (hola);
Se usa para enviar mensajes al servidor
2.ws.onopen = function () {console.log (open)};
Cuando el WebSocket se crea con éxito, el evento Onopen se activará
3.ws.onmessage = function (evt) {console.log (evt.data)};
Cuando el cliente recibe un mensaje enviado por el servidor, el evento OnMessage se activará. El parámetro EVT.Data contiene los datos transmitidos por el servidor.
4.ws.onclose = function (evt) {console.log (WebSocketClosed!); };
Cuando el cliente recibe una solicitud para cerrar la conexión enviada por el servidor, el evento OnClose se activa
5.ws.onerror = function (evt) {console.log (WebSocketError!); };
Si la conexión, el procesamiento, la recepción y el envío de datos de datos, el evento OnError se activará
Podemos ver que todas las operaciones se activan por eventos, de modo que la interfaz de usuario no bloquee, lo que permite que la interfaz de usuario tenga un tiempo de respuesta más rápido y una mejor experiencia de usuario.
Lado del servidor
Hoy en día, hay muchos software de servidor que admite WebSocket, como Node.js, Jetty, Tomcat, etc.
Aquí estoy usando Tomat 7.0 y Eclipse4.2
Tomcat, use WebSocket primero para importar el jar relevante
Las clases relacionadas con WebSocket proporcionadas por TomCat7 están ubicadas en el paquete org.apache.catalina.websocket (la implementación del paquete org.apache.catalina.webSocket está contenida en el archivo catalina.jar
Aquí solo importamos todo Tomcat
En la ruta de compilación-> Configurar ruta de compilación-> bibliotecas-> agregar biblioteca-> servidor de ejecución-> apache tomcat v7.0
imagen
Además, importe los siguientes paquetes
importar org.apache.catalina.websocket.messageInbound;
importar org.apache.catalina.websocket.streaminbound;
importar org.apache.catalina.websocket.wsoutBound;
importar org.apache.catalina.websocket.websocketservlet;
Necesitamos dos clases
El primero se utiliza para manejar las solicitudes de WebSocket
El segundo se usa para manejar cada tarea de WebSocket específica
La primera categoría
SocketServer de clase pública extiende WebSocketServlet {
Private static final Long SerialVersionUid = 1L;
// ...
@Anular
CreateWebSocketInbound de createBsocketInbound protegido (String Arg0,
HttpservletRequest arg1) {
// TODO STUB de método generado automático
devolver nuevo chatwebSocket (usuarios);
}
}
Este servlet hereda de WebSocketServlet e implementa el método CreateWebSocketInbound. Este método devuelve una instancia de la segunda clase.
La segunda categoría
ChatWebSocket de clase pública extiende MessageInbound {
@Anular
Vacío protegido OnTextMessage (mensaje Charbuffer) lanza ioexception {
}
@Anular
Onopen vacío protegido (WSoutbound ourbound) {
}
@Anular
protegido vacío onClose (int status) {
}
@Anular
Vacío protegido OnbinaryMessage (Bytebuffer Arg0) lanza ioexception {
}
// El resto es solo un poco
}
Vacío protegido OnTextMessage (Mensaje Charbuffer) lanza ioexception {}
Respuesta de mensaje de texto
Vacío protegido OnbinaryMessage (Bytebuffer Arg0) lanza ioexception {}
Respuesta de mensajes binarios
Onopen vacío protegido (wsoutbound outbound) {}
Eventos activados estableciendo una conexión
protegido nulo onClose (int status) {}
Eventos disparados al cerrar la conexión
4. Código de programa
parte html
<! Doctype html>
<html>
<Evista>
<meta charset = utf-8>
<script type = text/javaScript src = js/jQuery.js> </script>
<script type = text/javaScript src = js/socket.js> </script>
<title> un documento titulado </title>
</ablo>
<Script Language = JavaScript>
</script>
<Body>
<Table>
<tr>
<TD> Mensaje </td>
<td> <input type = text id = mensaje> </td>
</tr>
<tr>
<TD> Nombre </td>
<td> <input type = text id = otherName> </td>
</tr>
<tr>
<TD> <input id = sendButton type = button value = send onClick = Click DISABLED = True>
</input> </td>
</tr>
</table>
<script>
</script>
</body>
</html>
JS Part (sin explicación sobre la parte jQuery)
var userName = window.prompt (ingrese su nombre :);
document.write (bienvenido <p id =/username/>+nombre de usuario+</p>);
if (! window.websocket && window.mozwebsocket)
Window.WebSocket = Window.MozWebSocket;
if (! Window.webSocket)
alerta (sin soporte);
var ws;
$ (documento) .Ready (function () {
$ (#sendButton) .attr (discapacitado, falso);
$ (#sendButton) .Click (sendMessage);
startWebSocket ();
})
función sendMessage ()
{
var otro Name = $ (#OTRONAME) .Val ();
var msg = msg/t+nombre de usuario+_+otro nombre de nombre+_+$ (#mensaje) .val ();
enviar (msg);
}
Función Enviar (datos)
{
console.log (enviar:+datos);
ws.send (datos);
}
función startWebSocket ()
{
ws = nuevo WebSocket (ws: // + ubicación.host +/webSocket/socketserver);
ws.onopen = function () {
console.log (éxito de éxito);
$ (#sendButton) .attr (discapacitado, falso);
};
ws.onmessage = function (evento)
{
console.log (recibir:+event.data);
HandleData (event.data);
};
ws.onclose = function (evento) {
console.log (el cliente notificado ha cerrado, evento);
};
}
función handledata (datos)
{
var vals = data.split (/t);
var msgtype = vals [0];
Switch (msgtype)
{
Nombre del caso:
var msg = vals [1];
var mes = nombre+/t+msg+_+nombre de usuario;
enviar (mes);
romper;
Case MSG:
var val2s = vals [1] .split (_);
var from = val2s [0];
Mensaje var = val2s [2];
alerta (de+:+mensaje);
romper;
por defecto:
romper;
}
}
Parte de Java
import java.io.ioException;
import java.nio.bytebuffer;
import java.nio.charbuffer;
import javax.servlet.http.httpservletRequest;
import java.util.set;
import java.util.concurrent.CopyOnWriteArraySet;
importar org.apache.catalina.websocket.messageInbound;
importar org.apache.catalina.websocket.streaminbound;
importar org.apache.catalina.websocket.wsoutBound;
importar org.apache.catalina.websocket.websocketservlet;
SocketServer de clase pública extiende WebSocketServlet {
Private static final Long SerialVersionUid = 1L;
Public Final Set <CHATWEBSOCKETS> USERS = new CopyOnWriteArraySet <CHATWebSocket> ();
Public static int usernumber = 1;
@Anular
CreateWebSocketInbound de createBsocketInbound protegido (String Arg0,
HttpservletRequest arg1) {
// TODO STUB de método generado automático
devolver nuevo chatwebSocket (usuarios);
}
ChatWebSocket de clase pública extiende MessageInbound {
nombre de usuario de cadena privada;
set private <CHATWEBSOCKECHE> USERS = new CopyOnWriteArraySet <CHATWEBSOCKECHE () ;;
Public chatWebSocket () {
}
Public ChatWebSocket (set <atWebSocket> usuarios) {
this.users = usuarios;
}
@Anular
Vacío protegido OnTextMessage (mensaje Charbuffer) lanza ioexception {
// Lo que se procesa aquí son datos de texto
}
public void onMessage (datos de cadena) {
Cadena [] val1 = data.split (// t);
if (val1 [0] .equals (nombre))
{
Cadena [] val2 = val1 [1] .split (_);
para (usuario de chatwebsocket: usuarios) {
if (user.username.equals (val2 [0])) {
user.username = val2 [1];
}
}
}
else if (val1 [0] .equals (msg))
{
Cadena [] val2 = val1 [1] .split (_);
para (usuario de chatwebsocket: usuarios) {
if (user.username.equals (val2 [1])) {
intentar {
Charbuffer temp = charbuffer.wrap (datos);
user.getWSoutBound (). WriteTextMessage (temp);
} Catch (ioException e) {
// bloque de captura generado automático
E.PrintStackTrace ();
}
}
}
}
demás
{
System.out.println (error);
}
}
@Anular
Onopen vacío protegido (WSoutbound ourbound) {
// this.connection = conexión;
this.Username = # + String.ValueOf (UserNumber);
UserNumber ++;
intentar {
Mensaje de cadena = nombre + /t + this.username;
Charbuffer buffer = charbuffer.wrap (mensaje);
this.getWSoutBound (). WriteTextMessage (buffer);
} Catch (ioException e) {
// bloque de captura generado automático
E.PrintStackTrace ();
}
ussers.add (esto);
}
@Anular
protegido vacío onClose (int status) {
usuarios.remove (esto);
}
@Anular
Vacío protegido OnbinaryMessage (Bytebuffer Arg0) lanza ioexception {
}
}
}
explicar
Mi idea aquí es
1 Al acceder, cada usuario primero debe ingresar su nombre y luego enviar una solicitud de conexión al servidor.
2 Después de que el servidor acepta la solicitud de conexión del cliente, será nuevo ChatWebSocket (usuarios); Para procesar esta solicitud y agregarla a la lista de usuarios en línea. En este momento, el servidor aún no conoce el nombre del cliente. Asumirá un nombre para este usuario, #1, y el servidor enviará el nombre + /t + #1 al cliente, ¿cuál es su nombre?
3 Cuando el cliente recibe este mensaje, sabrá que el servidor está preguntando cuál es su nombre, por lo que el cliente enviará el nombre+/t+#1+_+su propio nombre al servidor, (mi nombre es xxx)
4 Después de recibir este mensaje, el servidor busca en la lista de usuarios en línea actualmente en línea basada en el n. ° 1 y reemplaza el n. ° 1 con el nombre del cliente, para que el servidor conozca el nombre del cliente.
5 Cuando el cliente se va, el servidor activará el evento OnClose y el servidor eliminará al usuario actual de la lista en línea.
Use imágenes para dibujar algo como esto (dibujado mal, -_- !!)
Código
js
ws = nuevo WebSocket (ws: // + ubicación.host +/webSocket/socketserver);
Conectarse al servidor
Java
CreateWebSocketInbound de createBsocketInbound protegido (String Arg0,
HttpservletRequest arg1) {
// TODO STUB de método generado automático
devolver nuevo chatwebSocket (usuarios);
}
Cree un chatwebsocket para manejar esta solicitud y active el evento Onopen del objeto ChatWebSocket
@Anular
Onopen vacío protegido (WSoutbound ourbound) {
// this.connection = conexión;
this.Username = # + String.ValueOf (UserNumber);
UserNumber ++;
intentar {
Mensaje de cadena = nombre + /t + this.username;
Charbuffer buffer = charbuffer.wrap (mensaje);
this.getWSoutBound (). WriteTextMessage (buffer);
} Catch (ioException e) {
// bloque de captura generado automático
E.PrintStackTrace ();
}
ussers.add (esto);
}
Suponiendo un nombre para este cliente, enviando el nombre supuesto de nombre+/t+ al cliente y agregando el cliente a la lista del cliente conectado actualmente
js
función handledata (datos)
{
var vals = data.split (/t);
var msgtype = vals [0];
Switch (msgtype)
{
Nombre del caso:
var msg = vals [1];
var mes = nombre+/t+msg+_+nombre de usuario;
enviar (mes);
romper;
// ………
}
}
Acepte y procese el mensaje enviado por el servidor, y descubra que el servidor le preguntó cuál es su nombre, por lo que envió el nombre+/t+el nombre asumido+_+al servidor.
Java
public void onMessage (datos de cadena) {
Cadena [] val1 = data.split (// t);
if (val1 [0] .equals (nombre))
{
Cadena [] val2 = val1 [1] .split (_);
para (usuario de chatwebsocket: usuarios) {
if (user.username.equals (val2 [0])) {
user.username = val2 [1];
}
}
}
// ………
}
Procese y acepte el mensaje enviado por el cliente y encuentre que el cliente respondió a su nombre, por lo que busque en la lista de clientes conectada actualmente en función del nombre supuesto previamente y convierte el seudónimo en el nombre real
js
función sendMessage ()
{
var otro Name = $ (#OTRONAME) .Val ();
var msg = msg/t+nombre de usuario+_+otro nombre de nombre+_+$ (#mensaje) .val ();
enviar (msg);
}
El cliente inicia una conversación con otra persona, y el formato de mensaje es: Msg+su propio nombre+_+Nombre opuesto+_+Mensaje
Java
public void onMessage (datos de cadena) {
/// …………
else if (val1 [0] .equals (msg))
{
Cadena [] val2 = val1 [1] .split (_);
para (usuario de chatwebsocket: usuarios) {
if (user.username.equals (val2 [1])) {
intentar {
Charbuffer temp = charbuffer.wrap (datos);
user.getWSoutBound (). WriteTextMessage (temp);
} Catch (ioException e) {
// bloque de captura generado automático
E.PrintStackTrace ();
}
}
}
}
/// …………
}
Se encuentra que el mensaje es enviado por el cliente. Según el nombre de la otra parte, busque en la lista de clientes conectadas actualmente y envíe el mensaje.
js
función handledata (datos)
{
var vals = data.split (/t);
var msgtype = vals [0];
Switch (msgtype)
{
/// ...
Case MSG:
var val2s = vals [1] .split (_);
var from = val2s [0];
Mensaje var = val2s [2];
alerta (de+:+mensaje);
romper;
por defecto:
romper;
}
}
Se descubrió que era un mensaje enviado por otro cliente, y se mostró a través de la alerta.
Java
@Anular
protegido vacío onClose (int status) {
usuarios.remove (esto);
}
Descubrir que el cliente se ha ido, elimine al cliente de la lista de clientes conectados
Donde mejorar
1. Si el Cliente A envía un mensaje a B y B no está en línea, el mensaje se puede almacenar en la base de datos. Cuando se encuentra que B está en línea, se recuperará de la base de datos y se enviará a B.
2 Cuando el servidor envía su nombre, puede agregar un mecanismo de tiempo de espera. Si el cliente no responde a cómo se llama dentro de un cierto período de tiempo, el cliente puede eliminar al cliente de la lista en línea.