A) well all depends on the number of players you want the server to support....I'm not familiar with the internal workings of the Indy component pack, but I guess they are using blocking IO (that's why a thread per connection)....and in MMORPG there are a lot of receives/sends, so the threads will be active most of the time making context switching consume quite a lot of CPU power...even select() is not enough when dealing with hundreds of connections....if you plan the server to work only on the Windows platform, I advise you to use I/O Completion Ports....with only a handful of threads you may handle thousands of connections.....

B) not sure what you read here....the client must know the port he should connect to, so a different port cannot be assigned to each client...maybe they ment the so-called local port that is connection-specific and gets assigned automaticly....

when it comes to socket-reuse, it is doable but only when using Overlapped I/O (including I/O Completion Ports)....the idea behind the concept is that creating sockets is an expensive operation....you may create many sockets ahead in a pool and then use those....this works only under Windows as I know (maybe I'm wrong) by using the AcceptEx/DisconnectEx/TransmitFile/TransmitPackets calls....these are not ordinary functions and are not exported by ws2_32.dll....the function pointers must be obtained at runtime using WSAIoctl call....

Code:
const
  { Extension function pointers' GUIDs }
  WSAID_ACCEPTEX: TGUID = '{B5367DF1-CBAC-11CF-95CA-00805F48A192}';
  WSAID_CONNECTEX: TGUID = '{25A207B9-DDF3-4660-8EE9-76E58C74063E}';
  WSAID_DISCONNECTEX: TGUID = '{7FDA2E11-8630-436F-A031-F536A6EEC157}';
  WSAID_GETACCEPTEXSOCKADDRS: TGUID = '{B5367DF2-CBAC-11CF-95CA-00805F48A192}';
  WSAID_TRANSMITFILE: TGUID = '{B5367DF0-CBAC-11CF-95CA-00805F48A192}';
  WSAID_TRANSMITPACKETS: TGUID = '{D9689DA0-1F90-11D3-9971-00C04F68C876}';
  WSAID_RECVMSG: TGUID = '{F689D7C8-6F1F-436B-8A53-E54FE351C322}';

type
  LPACCEPTEX = function(sListenSocket: TSocket; sAcceptSocket: TSocket; lpOutputBuffer: Pointer;
    dwReceiveDataLength: DWORD; dwLocalAddressLength: DWORD; dwRemoteAddressLength: DWORD;
    lpdwBytesReceived: PDWORD; lpOverlapped: POverlapped): BOOL; stdcall;
  TAcceptEx = LPACCEPTEX;

  LPDISCONNECTEX = function(hSocket: TSocket; lpOverlapped: POverlapped; dwFlags: DWORD;
    reserved: DWORD): BOOL; stdcall;
  TDisconnectEx = LPDISCONNECTEX;

  LPCONNECTEX = function(s: TSocket; const name: TSockAddr; namelen: Integer;
    lpSendBuffer: Pointer; dwSendDataLength: DWORD; lpdwBytesSent: PDWORD;
    lpOverlapped: POverlapped): BOOL; stdcall;
  TConnectEx = LPCONNECTEX;

  LPGETACCEPTEXSOCKADDRS = procedure(lpOutputBuffer: Pointer; dwReceiveDataLength: DWORD;
    dwLocalAddressLength : DWORD; dwRemoteAddressLength: DWORD; var LocalSockaddr: PSockAddr;
    LocalSockaddrLength: PDWORD; var RemoteSockaddr: PSockAddr; RemoteSockaddrLength: PDWORD); stdcall;
  TGetAcceptExSockAddrs = LPGETACCEPTEXSOCKADDRS;

  LPTRANSMIT_FILE_BUFFERS = ^TRANSMIT_FILE_BUFFERS;
  TRANSMIT_FILE_BUFFERS = record
    Head: Pointer;
    HeadLength: DWORD;
    Tail: Pointer;
    TailLength: DWORD;
  end;
  TTransmitFileBuffers = TRANSMIT_FILE_BUFFERS;
  PTransmitFileBuffers = LPTRANSMIT_FILE_BUFFERS;

  LPTRANSMITFILE = function(hSocket: TSocket; hFile: THandle; nNumberOfBytesToWrite: DWORD;
    nNumberOfBytesPerSend: DWORD; lpOverlapped: POverlapped; lpTransmitBuffers: PTransmitFileBuffers;
    dwFlags: DWORD): BOOL; stdcall;
  TTransmitFile = LPTRANSMITFILE;

  LPTRANSMIT_PACKETS_ELEMENT = ^TRANSMIT_PACKETS_ELEMENT;
  TRANSMIT_PACKETS_ELEMENT = record
    dwElFlags: DWORD;
    cLength: DWORD;
    case Boolean of
      False: (
        nFileOffset: LARGE_INTEGER;
        hFile: THandle;
      );
      True: (
        pBuffer: Pointer;
      );
  end;
  TTransmitPacketsElement = TRANSMIT_PACKETS_ELEMENT;
  PTransmitPacketsElement = LPTRANSMIT_PACKETS_ELEMENT;

  LPTRANSMITPACKETS = function(hSocket: TSocket; lpPacketArray: PTransmitPacketsElement;
    nElementCount: DWORD; nSendSize: DWORD; lpOverlapped: POverlapped; dwFlags: DWORD): BOOL; stdcall;
  TTransmitPackets = LPTRANSMITPACKETS;

  LPWSAMSG = ^WSAMSG;
  WSAMSG = record
    name: PSockAddr;
    namelen: DWORD;
    lpBuffers: LPWSABUF;
    dwBufferCount: DWORD;
    Control: WSABUF;
    dwFlags: DWORD;
  end;
  PWSAMsg = LPWSAMSG;
  TWSAMsg = WSAMSG;

  LPWSARECVMSG = function(s: TSocket; lpMsg: PWSAMsg; lpNumberOfBytesRecvd: PDWORD;
    lpOverlapped: LPWSAOVERLAPPED; lpCompletionRoutine: LPWSAOVERLAPPED_COMPLETION_ROUTINE): Integer; stdcall;
  TWSARecvMsg = LPWSARECVMSG;

function WSAGetExtensionFunctionPointer(s: TSocket; const gdExFuncGuid: TGUID): Pointer;
var
  lwOut: Longword;
begin
  Result := nil;
  WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, @gdExFuncGuid, SizeOf(gdExFuncGuid),
    @Result, SizeOf(Result), @lwOut, nil, nil);
end;
the GUIDs used to get the function pointers are not declared in the Winsock unit shipped with Delphi nor in JEDI WinApi Header Translation units....so I posted them here along with the function prototypes and a small function which obtains one of those function at runtime (requires a valid socket descriptor)....the AcceptEx function accepts a new connection after you must call GetAcceptExSockAddrs to get the local/remote addresses....DisconnectEx with TF_REUSE_SOCKET disconnect a client so the socket can be used again with the AcceptEx call...note that DisconnectEx is available only under WindowsXP and higher - to support earlier Windows versions, use TransmitFile with all params 0/nil and the TF_REUSE_SOCKET flag specified....

I guess I got carried away a bit ...hope this helps and answers your questions....