Ir al contenido principal
Latest blog post (July 25, 2024): npm package provenance.
Versión: 4.x

Notas finales

Código final del servidor

  • CommonJS
  • ES modules
index.js
const express =require('express');
const{ createServer }=require('node:http');
const{ join }=require('node:path');
const{Server}=require('socket.io');
const sqlite3 =require('sqlite3');
const{ open }=require('sqlite');
const{ availableParallelism }=require('node:os');
const cluster =require('node:cluster');
const{ createAdapter, setupPrimary }=require('@socket.io/cluster-adapter');

if(cluster.isPrimary){
const numCPUs =availableParallelism();
for(let i =0; i < numCPUs; i++){
cluster.fork({
PORT:3000+ i
});
}

returnsetupPrimary();
}

asyncfunctionmain(){
const db =awaitopen({
filename:'chat.db',
driver: sqlite3.Database
});

await db.exec(`
CREATE TABLE IF NOT EXISTS messages (
id INTEGER PRIMARY KEY AUTOINCREMENT,
client_offset TEXT UNIQUE,
content TEXT
);
`);

const app =express();
const server =createServer(app);
const io =newServer(server,{
connectionStateRecovery:{},
adapter:createAdapter()
});

app.get('/',(req, res)=>{
res.sendFile(join(__dirname,'index.html'));
});

io.on('connection',async(socket)=>{
socket.on('chat message',async(msg, clientOffset, callback)=>{
let result;
try{
result =await db.run('INSERT INTO messages (content, client_offset) VALUES (?, ?)', msg, clientOffset);
}catch(e){
if(e.errno===19/* SQLITE_CONSTRAINT */){
callback();
}else{
// nada que hacer, solo dejar que el cliente reintente
}
return;
}
io.emit('chat message', msg, result.lastID);
callback();
});

if(!socket.recovered){
try{
await db.each('SELECT id, content FROM messages WHERE id > ?',
[socket.handshake.auth.serverOffset||0],
(_err, row)=>{
socket.emit('chat message', row.content, row.id);
}
)
}catch(e){
// algo salió mal
}
}
});

const port = process.env.PORT;

server.listen(port,()=>{
console.log(`servidor corriendo en http://localhost:${port}`);
});
}

main();

Código final del cliente

  • ES6
  • ES5
index.html
<!DOCTYPEhtml>
<html>
<head>
<metaname="viewport"content="width=device-width,initial-scale=1.0">
<title>Socket.IO chat</title>
<style>
body{margin:0;padding-bottom:3rem;font-family: -apple-system, BlinkMacSystemFont,"Segoe UI", Roboto, Helvetica, Arial, sans-serif;}

#form{background:rgba(0,0,0,0.15);padding:0.25rem;position: fixed;bottom:0;left:0;right:0;display: flex;height:3rem;box-sizing: border-box;backdrop-filter:blur(10px);}
#input{border: none;padding:01rem;flex-grow:1;border-radius:2rem;margin:0.25rem;}
#input:focus{outline: none;}
#form> button{background:#333;border: none;padding:01rem;margin:0.25rem;border-radius:3px;outline: none;color:#fff;}

#messages{list-style-type: none;margin:0;padding:0;}
#messages> li{padding:0.5rem1rem;}
#messages> li:nth-child(odd){background:#efefef;}
</style>
</head>
<body>
<ulid="messages"></ul>
<formid="form"action="">
<inputid="input"autocomplete="off"/><button>Send</button>
</form>
<scriptsrc="/socket.io/socket.io.js"></script>
<script>
let counter =0;

const socket =io({
ackTimeout:10000,
retries:3,
auth:{
serverOffset:0
}
});

const form =document.getElementById('form');
const input =document.getElementById('input');
const messages =document.getElementById('messages');

form.addEventListener('submit',(e)=>{
e.preventDefault();
if(input.value){
const clientOffset =`${socket.id}-${counter++}`;
socket.emit('chat message', input.value, clientOffset);
input.value='';
}
});

socket.on('chat message',(msg, serverOffset)=>{
const item =document.createElement('li');
item.textContent= msg;
messages.appendChild(item);
window.scrollTo(0,document.body.scrollHeight);
socket.auth.serverOffset= serverOffset;
});
</script>
</body>
</html>

Tarea

Aquí hay algunas ideas para mejorar la aplicación:

  • Difundir un mensaje a los usuarios conectados cuando alguien se conecta o desconecta.
  • Añadir soporte para apodos.
  • No enviar el mismo mensaje al usuario que lo envió. En su lugar, añadir el mensaje directamente tan pronto como presione enter.
  • Añadir funcionalidad de "{usuario} está escribiendo".
  • Mostrar quién está en línea.
  • Añadir mensajería privada.
  • ¡Comparte tus mejoras!

Obteniendo este ejemplo

Puedes encontrarlo en GitHub aquí.

git clone https://github.com/socketio/chat-example.git

Próximos pasos

Por favor revisa:

AltStyle によって変換されたページ (->オリジナル) /