首页 > 解决方案 > UDP 请求未连接到 repl.it 服务器

问题描述

我正在尝试使用 node.js 和 repl.it 上的数据报编写一个简单的 UDP 服务器,但我无法连接到服务器,我尝试了不同的端口,但没有建立任何连接。在服务器上运行“npm start”后,我得到:服务器正在侦听 0.0.0.0:3000 仅此而已,这似乎是什么问题?该代码在本地服务器上运行良好,建立了连接并发送了数据包,但是当我尝试在 repl.it 上运行它时没有任何反应。

const _ = require('lodash');
const dgram = require('dgram');
const server = dgram.createSocket('udp4');


const serverConfig = {
    welcome: 'Welcome to the game!',
    serverPort: 3000,       //heroku server port!
    clientPort: 6510,
    sendingInterval: 500, //msec
    inactivityCheckInterval: 30, //sec
    pingAfter: 60, //sec
    deactivateAfter: 150, //sec
    debug: true
}

const users = [];
const messages = [];
const outerQueue = [];
const gameSlots = [0,0,0,0,0,0,0,0];
const gameSlotsNumber = [2,2,2,4,4,4,6,6];

const scheduleQueue = () => setTimeout(processQueue, serverConfig.sendingInterval);

const debug = txt => { if (serverConfig.debug) console.log(txt) };


const processQueue = () => {
    if (outerQueue.length > 0) {
        const m = outerQueue.shift();
        //console.log(m);
        server.send(m.body, m.port, m.address, scheduleQueue);
    } else {
        scheduleQueue();
    }
}

const setName = (rinfo, name) => {
    debug(`Auth request from ${rinfo.address}:${rinfo.port}`);
    if (nameInUse(name)) {
        addToQueue(`<M${String.fromCharCode(0)} >** Name in use. Type /nick to set new one`, rinfo.port, rinfo.address);
    } else {
        addToQueue(`<M${String.fromCharCode(1)} >** Authorization OK`, rinfo.port, rinfo.address);
        addToQueue(`<A  >${name}`, rinfo.port, rinfo.address);
        const user = getUser(rinfo);
        if (user) {
            user.name = name;
            registerUserAction(user);
            debug(`Name updated`);
        } else {
            const gmSlot = 20;  //out of regular 8 slots
            users.push({
                address: rinfo.address,
                port: rinfo.port,
                name: name,
                lastAction: nowStamp(),
                gameSlot: gmSlot, 
                active: true
            })
            debug(`User Added`);
        }        
        broadcastStatus();
    }
}


const parseDatagram = (msg, rinfo) => {
    msg = msg || '';
    const header = getHeader(msg);
    if (validateHeader(header)) {
        switch (header.command) {
            case 'S':  // status
                sendStatus(rinfo);
            break;
            case 'A':  // auth
                setName(rinfo, header.body);
            break;
            case 'M':  // message
                sendMessage(rinfo, header);
            break;
//            case 'C':  // command
//                runCommand(rinfo, header);
//            break;
            case 'P':  // ping
                const user = getUser(rinfo);
                if (user) registerUserAction(user);
            break;
            case 'O':                               //set gameslot of the user
                setUserSlot(rinfo,header.body);     //first byte of the message is the number of the slot
                checkForFullSlots(rinfo);
                broadcastUsersInSlots();
            break;          
            case 'X':                               //player lost the battle
                const user2 = getUser(rinfo);
                playerLost(rinfo,user2);        //first byte of the message is the number of the slot
            break;
            case 'Q':                               //lost player quit the game
                const user3 = getUser(rinfo);
                playerQuitGame(user3);
            break;                                  
        }
    } else {
        debug(`Invalid header: ${msg} from ${rinfo.address}:${rinfo.port}`);
    }
}


const sendStatus = rinfo => {
    debug(`Status request from ${rinfo.address}:${rinfo.port}`);
    const user = getUser(rinfo);
    addToQueue(`<S${String.fromCharCode(user && user.active?1:0)}${String.fromCharCode(getActive().length)}>${serverConfig.welcome}`, rinfo.port, rinfo.address);
    if (user && user.active)
        addToQueue(`<A  >${user.name}`, rinfo.port, rinfo.address);
}

const sendMessage = (rinfo, header) => {
    debug(`Message from ${rinfo.address}:${rinfo.port}: ${header.body}`);
    const user = getUser(rinfo);
    if (user) {
        broadcast(`<M  ><${user.name}>${header.body}`);
        registerUserAction(user);
        debug(`Message broadcasted`);
    } else {
        addToQueue(`<M  >** Unauthorized. Type /nick to set name.`, rinfo.port, rinfo.address);
    }
}

const setUserSlot = (rinfo,slotAndUser) => {
    const user = getUser(rinfo)
    if(user){
    user.gameSlot = slotAndUser.msg[5]; //after 4 byte header
    }
    
}

const broadcast = msg => {
    _.each(users, user => {
        if (user.active) {
            addToQueue(`${msg}`, user.port, user.address);
        }
    });
}

const playerQuitGame = (user) => {
    if(user){
    user.gameSlot = 20; //after 4 byte header
    }   
    broadcastUsersInSlots();
}

const playerLost = (rinfo,msx,user) => {
    if(user){
        _.each(users,usr => {
        if(user.gamePort == usr.gamePort)   addToQueue(`<X  >${user.name}`, usr.port, usr.address);
        });         
    }
    
}

const addToQueue = (bodyy, portt, addresss) => outerQueue.push({body:bodyy, port: serverConfig.clientPort,address: addresss});

const checkForFullSlots = (rinfo) => {
        countSlots();
        for(var x=0;x<8;x++){
            if(gameSlots[x]==gameSlotsNumber[x]){
            broadcastBegin(x);      //B->begin the game in the slot     
            }
            
        }
}

const countSlots = () => {
    const slots = [0,0,0,0,0,0,0,0];
        _.each(users, user => {
            if(user.gameSlot<8)         //number f slots equals 8;
            slots[user.gameSlot]++;
        });
        gameSlots = slots;  
    
}
const broadcastBegin = slot => {
    _.each(users, user => {
        if(user.active && user.gameSlot== slot) {
            addToQueue(`<B  >game started, place your ships!`, user.port, user.address);
        }
    });
}   


const getHeader = msg => {
    const msg8 = Uint8Array.from(msg)
    return {
        h1: String.fromCharCode(msg[0]),  //"<"
        command: String.fromCharCode(msg[1]),
        paramL: msg8[2],
        paramH: msg8[3],
        h2: String.fromCharCode(msg[4]), //">"
        body: msg.toString().substring(5)
    }
}
const validateHeader = header => {
    return (header.h1 == '<') && (header.h2 == '>')
}

const getUser = rinfo => _.find(users, {'address': rinfo.address});

const getActive = () => _.filter(users, {'active': true});


const broadcastUsersInSlots = () => {
    
    var usersNames = ["","","","","","","",""];
    for(var i=0;i<8;i++){
        _.each(users, user => {
            if(user.gameSlot == i){
                usersNames[i]+=user.name+"|||";
            }
        });
    }
    _.each(users, user => {
        if (user.active && user.gameSlot <8) {
        var msx = usersNames[user.gameSlot];
            if(msx==""){
                msx="empty";
            }
            addToQueue(`<Y  >${msx}`, user.port, user.address);         //Y equals total users in slots
        }
    });
    broadcastGameSlots();   
}

const broadcastGameSlots = () => {
        _.each(users, user => {
            if(user.active && user.gameSlot > 7) {
            addToQueue(`<W  >${gameSlots[0]}${gameSlots[1]}${gameSlots[2]}${gameSlots[3]}${gameSlots[4]}${gameSlots[5]}${gameSlots[6]}${gameSlots[7]}`,
            user.port,user.address);
            }
        }); 
}
const broadcastShipsUser = (rinfo,userSending,msx) => {
    
    _.each(users, user => {
        if(userSending.gameSlot == user.gameSlot){
            addToQueue(`<Z  >${msx.body}`, user.port, user.address);    //Z equals new ships set by the user, 2 bytes-X,Y pos, 3rd byte-rotation
        }
        
    });
                userSending.status = 1; //ships have been set
}

const broadcastShot = (userSending, msx) => {           // msx contains 2 bytes: x position of the bullet, y position of the bullet
    _.each(users, user => {
        if(userSending.gameSlot == user.gameSlot){
        addToQueue(`<R  >${userSending.name}|||${msx}`,user.port,user.address); 
        }
    });
    
}

const broadcastStatus = msg => {
    _.each(users, user => {
        if (user.active) {
            addToQueue(`<S ${String.fromCharCode(getActive().length)}>`, user.port, user.address);
        }
    });
}

const traceInactivity = () => {
    const now = nowStamp();
    _.each(users, user => {
        if  (user.active) {
            if (now - user.lastAction > serverConfig.pingAfter) {
                pingUser(user);
            };
            if (now - user.lastAction > serverConfig.deactivateAfter) {
                registerUserAction(user, false);
                user.gameSlot= 20;
                broadcastUsersInSlots();
                debug(`deactivated user ${user.name}`);
                broadcastStatus();
            };
        };
    });
    setTimeout(traceInactivity, serverConfig.inactivityCheckInterval * 1000);
}

const pingUser = user => {
    debug(`Pinging user: ${user.name}`);
    addToQueue(`<P  >PING!`, user.port, user.address);
}

const nameInUse = name => _.find(users, {'name': name, 'active': true});


const registerUserAction = (user, active = true) => {
    user.lastAction = nowStamp();
    user.active = active;
}

const nowStamp = () => Math.floor(Date.now() / 1000);

server.on('error', (err) => {
    console.log(`server error:\n${err.stack}`);
    server.close();
});

server.on('message', (msg, rinfo) => {
    debug(`server got: ${msg} from ${rinfo.address}:${rinfo.port}`);
    parseDatagram(msg, rinfo);
});

server.on('listening', () => {
    const address = server.address();
    console.log(`server listening ${address.address}:${address.port}`);
});

server.bind(serverConfig.serverPort);

scheduleQueue();
traceInactivity();

标签: node.jsudprepl.it

解决方案


推荐阅读