pythonnetwork-programminglualuasocket

Lua client, Python server, everything's fine in local, timeout on the net


So, I'm coding a lua mod for Binding of Isaac. I made a lua client (using luasocket), and a python server.

In local, everything works fine, but when I test it using my public ip (I did the port forwarding on my router), the lua client times out at its second reception. I don't know what causes it, the log says "timeout at CID".

Edit (forgotten to add this) : What is weird is that for the python server, it's as if he already sent it, because when I add a timeout on the server, it's only the reception of the message "[RCID]\n" that times out.

Here is the network part of the lua mod:

local socket = require("socket")
local connectIP = ""
local currentPort = 21666

local loopTimeout = 10
function Network.SendData(data)
    if currentBehaviour == Behaviour.CLIENT then
        client:send(data.."\n")
    end
end
function Network.StartClient()
if currentBehaviour == Behaviour.IDLE then
    client = assert(socket.tcp())
    client:connect(connectIP,currentPort)
    currentBehaviour = Behaviour.CLIENT
    client:settimeout(loopTimeout)
    local seed,errs = client:receive()
    if errs~="timeout" and errs~=nil then
      Network.CloseConnection();
      Isaac.DebugString("seederror:"..errs);
    elseif errs=="timeout" then
      Network.CloseConnection();
      Isaac.DebugString("timeout at seed");
    elseif errs==nil then
      Isaac.DebugString("Seed: : "..seed);
      Isaac.ExecuteCommand("seed "..seed)
    end

    local CID,err = client:receive()
    if err~="timeout" and err~=nil then
      Network.CloseConnection();
      Isaac.DebugString("ciderror:"..err);
    elseif err=="timeout" then
      Network.CloseConnection();
      Isaac.DebugString("timeout at CID");
    elseif err==nil then
      Isaac.DebugString("CID : "..CID);
      ClientID = tonumber(CID)
      Network.SendData("[RCID]")
    end

end
end

Here is the server :

import socket
import select
from parse import *



IsaacClients = {}

seed = b"98BN MJ4D\n"

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('', 21666))
server.listen(10)

num_clients = 0

server_launched = True
connected_clients = []
while server_launched:

    connections_asked, wlist, xlist = select.select([server],
        [], [], 0.05)

    for connection in connections_asked:
        connection_client, info_client = connection.accept()
        print(info_client)

        connected_clients.append(connection_client)
        print("Sending Seed")
        connection_client.sendall(seed) # send the seed
        print("Seed Sent")

        num_clients = num_clients +1
        check = ""
        counter = 0
        while check != "[RCID]\n" and counter<100: # try 100 times to send the ClientID
            print("Sending ClientID")
            try:
                connection_client.settimeout(0.1)
                connection_client.sendall((str(num_clients)+"\n").encode())
                check = connection_client.recv(7).decode() # try to check if it has received it
                connection_client.settimeout(None)
            except:
                pass
            counter=counter+1
            if counter == 100:
                server_launched = False
        print("ClientID Sent")



    clients_to_read = []
    try:
        clients_to_read, wlist, xlist = select.select(connected_clients,
                [], [], 0.05)
    except select.error:
        pass
    else:
        for client in clients_to_read:
            msg_recved = client.recv(1024)
            msg_recved = msg_recved.decode()
            print("[] {}".format(msg_recved))
            if msg_recved.find("[END]")!= -1 :
                server_launched = False
            msg_recved = msg_recved.split('\n') # split into lines

            for line in msg_recved:
                data = parse("[ID]{ID}[POS]{x};{y}[ROOM]{RoomIndex}[CHAR]{CharacterName}[REDM]{MaxHeart}[RED]{Hearts}[SOUL]{SoulHearts}", line)
                if data != None :
                    IsaacClients[data['ID']] = data
            luaTable = "{" # start the generation of the lua table that will be sent
            for player in IsaacClients.values():
                luaTable = luaTable + "[" + player['ID'] +"]={ID=" + player['ID'] + ",POS={x=" +player['x']+ ",y=" +player['y']+ "},ROOM=" +player['RoomIndex']+ ",CHAR='" +player['CharacterName']+ "',REDM=" +player['MaxHeart']+ ",RED=" +player['Hearts']+ ",SOUL=" +player['SoulHearts']+ "}"
            luaTable = luaTable + "}\n"
            print(luaTable)
            print("Sending Table")
            client.sendall(luaTable.encode())
            print("Table Sent")
print("Server closing")
for client in connected_clients:
    client.close()

Solution

  • So, finally, there was no issue, the thing was : my router didn't support hairpinning, making weird bugs when trying to use the public ip from the local network. It works fine whith PCs outside of the network.