Reputation: 75
story behind all of this
I'm trying to write an open source RPG inventory server, usable for more than 1 RPG at once, and will make a game for it later on. My first version doesn't support a lot of security or encryption. But I'd like to have a solid start.
Problem
It does accept one connection, drop in drop out. But my implementation of threading only seems to accept one connection. Is someone who can give me a guideline on how to do this properly? I've commented the code I will supply for your reading ease.
Setup I use visual studio 2010 with SP1 enabled. I only tried it within my home network so IP forwarding is not needed. It accepts both PC's separately.
A lot of thanks to the ones helping, if you help and want to be credited in the end result just let me know. and if someone has general comments I'd love to hear them;)
EDIT: it has something to do with the NewIPEP() method.
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
namespace TCPServer1
{
class ServerV1
{
static int maxthreads = 4;
static bool[] threadavailable = new bool[maxthreads];
static Thread[] listenThread = new Thread[maxthreads];
static IPEndPoint[] ipep = new IPEndPoint[maxthreads];
static bool[] threadconnected = new bool[maxthreads];
static Socket[] newsock = new Socket[maxthreads];
static Socket[] client = new Socket[maxthreads];
static ItemListClassV1 parent;
static Login loginin;
static ProtoColV1[] protocol = new ProtoColV1[maxthreads];
/// <summary>
/// initialises variables and starts a first thread.
/// </summary>
/// <param name="args"></param>
public ServerV1(ItemListClassV1 parentid, Login login)
{
for (int i = 0; i < maxthreads; i++)
{
threadavailable[i] = true;
}
parent = parentid;
loginin = login;
StartThread();
}
/// <summary>
/// should be split but handles the servershit look further for seperate "method" comments
/// </summary>
static void Server()
{
int recv = 0;
byte[] data = new byte[1024];
//looks for incoming connections
ipep[Convert.ToInt32(System.Threading.Thread.CurrentThread.Name)] = NewIPEP();
newsock[Convert.ToInt32(System.Threading.Thread.CurrentThread.Name)] = new
Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
newsock[Convert.ToInt32(System.Threading.Thread.CurrentThread.Name)].Bind(ipep[Convert.ToInt32(System.Threading.Thread.CurrentThread.Name)]);
newsock[Convert.ToInt32(System.Threading.Thread.CurrentThread.Name)].Listen(10);
Console.WriteLine("Waiting for a client...");
client[Convert.ToInt32(System.Threading.Thread.CurrentThread.Name)] = newsock[Convert.ToInt32(System.Threading.Thread.CurrentThread.Name)].Accept();
//if connected
IPEndPoint clientep =
(IPEndPoint)client[Convert.ToInt32(System.Threading.Thread.CurrentThread.Name)].RemoteEndPoint;
Console.WriteLine("Connected with {0} at port {1}",
clientep.Address, clientep.Port);
//if connection start a new thread
StartThread();
//send welcome message to client
string welcome = "Welcome to my test server";
data = Encoding.ASCII.GetBytes(welcome);
client[Convert.ToInt32(System.Threading.Thread.CurrentThread.Name)].Send(data, data.Length,
SocketFlags.None);
while (true)//this looks for incoming data and sends reply.
{
try
{
data = new byte[1024];
recv = client[Convert.ToInt32(System.Threading.Thread.CurrentThread.Name)].Receive(data);
}
catch (SocketException e)
{
if (e != null)
break;
}
if (client[Convert.ToInt32(System.Threading.Thread.CurrentThread.Name)].Connected != true)//when not connected break the loop
{
break;
}
////EXECUTES moet wer trug
//byte[][] packets = protocol[Convert.ToInt32(System.Threading.Thread.CurrentThread.Name)].Execute(data,recv);//EXECUTES THE DATA EXTERNALLY
byte[][] packets = new byte[1][];
packets[0] = data;
for (int i = 0; i < packets.Length; i++)//stuurt vervolgens alle pakketjes
{
client[Convert.ToInt32(System.Threading.Thread.CurrentThread.Name)].Send(packets[i], packets[i].Length,
SocketFlags.None);
}
}
//when not connected this continues
Console.WriteLine("Disconnected from {0}",
clientep.Address);
//close socket
client[Convert.ToInt32(System.Threading.Thread.CurrentThread.Name)].Close();
newsock[Convert.ToInt32(System.Threading.Thread.CurrentThread.Name)].Close();
bool full = true;
//if the server was full now a slot opened
for (int l = 0; l < maxthreads; l++)
{
if (threadavailable[l])
{
full = false;
}
if (!threadavailable[l] && !threadconnected[l])
{
full = false;
}
}
//closes thread, deletes information
threadavailable[Convert.ToInt32(System.Threading.Thread.CurrentThread.Name)] = true;
ipep[Convert.ToInt32(System.Threading.Thread.CurrentThread.Name)] = null;
protocol[Convert.ToInt32(System.Threading.Thread.CurrentThread.Name)] = null;
if (full)
{
StartThread();
}
//stops thread
listenThread[Convert.ToInt32(System.Threading.Thread.CurrentThread.Name)] = null;
System.Threading.Thread.CurrentThread.Abort();
}
/// <summary>
/// keeps searching for incoming connections and returns the found connection when found.
/// </summary>
/// <returns></returns>
static IPEndPoint NewIPEP()
{
IPEndPoint temp = null;
bool newconnection = false;
while (!newconnection)
{
temp = new IPEndPoint(IPAddress.Any, 9050);
for (int k = 0; k < maxthreads; k++)
{
if (!threadavailable[k] && ipep[k] != null && ipep[k].Address != null )
{
if (temp.Address == ipep[k].Address)
{
k = maxthreads;
break;
}
}
if (k == maxthreads - 1)
{
newconnection = true;
threadconnected[Convert.ToInt32(System.Threading.Thread.CurrentThread.Name)] = true;
}
}
}
return temp;
}
/// <summary>
/// finds the first unstarted thread and starts it
/// </summary>
static void StartThread()
{
for (int i = 0; i < maxthreads; i++)
{
if (threadavailable[i])
{
threadavailable[i] = false;
threadconnected[i] = false;
protocol[i] = new ProtoColV1(parent,loginin);
listenThread[i] = new Thread(Server);
listenThread[i].Name = Convert.ToString(i);
listenThread[i].Start();
break;
}
}
}
}
}
Upvotes: 1
Views: 548
Reputation: 261
This is not an answer, but I dont know how to add comments... Have you checked out Lidgren? Why re-invent the wheel? http://code.google.com/p/lidgren-network-gen3/
He has same great examples on how to use the library.
Good luck!
Linuxx
Upvotes: 1
Reputation: 283684
You only called Socket client = newsock.Accept();
once, that's why only one client is accepted.
Upvotes: 1