I'm embarrassed to even ask this question, but after an exhausting search in google (starting to have MSDN...), I've decided to post it:
Just now started learning client-server programming (using C#), and trying to write my first code using tcpClient. I'm writing both the server side and the client side.
here's my question: Constantly, the client sends one String to the server, and then the server sends a String back to the client and so forth.
Can't the server send 2 Strings in a row? he has to wait for the client response? is this the principle of client-server??
Once again, sorry for the lousy question.
Thanks...
<>
I'll try to post some of my code (a long one...).
I tryed to cut the redandent parts, so hope the code makes any sense... (i marked the main problam with //*********)
public class MServer2
{
Dictionary<String, String> nameAndPass = new Dictionary<String, String>();
Dictionary<String, List<String> > nameAndMail = new Dictionary<String, List<String>>();
public static void Main()
{
new MServer2();
}
public MServer2()
{
TcpListener server = new TcpListener(8500);
try
{
server.Start();
Console.WriteLine("started " + server);
while (true)
{
TcpClient client = server.AcceptTcpClient();
Console.WriteLine("connection accepted " + client);
new Server1(client, nameAndPass, nameAndMail);
}
}
catch (Exception e)
{
Console.WriteLine("exception" + e);
}
finally
{
server.Stop();
}
}
class Server1
{
TcpClient client;
NetworkStream netStream;
Dictionary<String, String> nameAndPass1 = new Dictionary<String, String>();
Dictionary<String, List<String>> nameAndMail1 = new Dictionary<String, List<String>>();
internal Server1(TcpClient client, Dictionary<String, String> nameandPassFromFile, Dictionary<String, List<String> > nameAndMailsFromFile)
{
nameAndPass1 = nameandPassFromFile;
nameAndMail1 = nameAndMailsFromFile;
this.client = client;
Thread thr = new Thread(new ThreadStart(Run));
thr.Start();
}
public void Run()
{
try
{
netStream = client.GetStream();
StreamReader reader = new StreamReader(netStream);
StreamWriter writer = new StreamWriter(netStream);
writer.AutoFlush = true;
Console.WriteLine("beginning to receive loop");
writer.WriteLine("Choose your user name.");
strFromClient = reader.ReadLine();
userName = strFromClient;
writer.WriteLine("Choose your user password.");
strFromClient = reader.ReadLine();
password = strFromClient;
writer.WriteLine("Do you want to see the list of email addresses? (y/n)");
strFromClient = reader.ReadLine();
//***********************************************************************************
//HERE'S MY PROBLAM:
//HERE THE CLIENT WILL GET A STRING SHOWING HIS EMAILS, AND I WANT HIM TO GET ANOTHER STRING ASKING "Do you want to add an email address? (y/n)", BUT IT LOOKS LIKE THE SERVER "WAITS" FOR A RESPONSE FROM THE CLIENT TO SHOW THE NEXT STRING...
if (strFromClient == "y")
{
String tmpStr = null;
List<String> tmp = nameAndMail1[userName];
for(int i=0; i<nameAndMail1[userName].Count; i++)
{
tmpStr += tmp[i] + " ";
}
writer.WriteLine(tmpStr);
}
writer.WriteLine("Do you want to add an email address? (y/n)");
strFromClient = reader.ReadLine();
}
}
catch (Exception e)
{
Console.WriteLine("{0} Exception caught.", e);
}
EDIT VOL 2
OK! After 2 hours of misery, I think I found the problam thanks to Phil Frost (the genius!) --- the problam is probably in the client... (Im souch an a-hole!).
The server does send 2 string in a row, but my stupid implementation of the client side doesn't show a message (which recived from the server) that doesn't follow a message sent by the client...
So once again I need your help. Here's a view of how I designed the client form:
My lack of experience led me to connect to the server when the "connect to server" button is pressed, and only when the "send Message" button is pressed, a message from the server is desplayed. The problam is when 2 (or more) messages from the server are recived without sending a message from the client to the server- the client doesn't know that a new message is recived!
Where do I suppose to recive the messages from the server? ('where' means under which function, for example- right now it happens in the sendMessage_click function).
thanks again for all the help so far!!
This question is neither lousy nor trivial. You are touching an important point in protocol design.
AFAIK, there are 2 ways to skin this particular cat:
"Dialog" (your way) ... Request is followed by reply, is followed by next request and so on. This has the big advantage of being easy, but the big disadvantage of only one command per connection being processed at any point in time
"Async" (Both parties can send without waiting for an answer) ... This has the implementation difficulty, that you need some sort of request-ID to make it possible to know, which reply belongs to which request: Imagine the client sending two requests, the first taking longer to process than the second: The replies would be in a different order than the requests.
The choice between these variants is not allways an easy one, but the trend goes towards the async model.
Additional difficulties in the async flavour include a mechanism to make sure, only one message is sent at a time (interweaving messages will most likely result in an unparseable stream) and timeout considerations.
Yes, the server can send two strings in a row. But probably not if your server is blocked on read(). Perhaps if you included some more details about your program, a more specific answer could be provided.
In TCP the client-to-server and server-to-client channels are two independent streams. Either party can send at any time.
Related
I've created a simple client/server program which takes an input from the client and returns a answer to the input by looking in the text file to see if there is an answer associated with the input.
The issue I'm having is that I get the response on the server side but I don't know how to send it back to the client (it just returns the input on the client side).
The second issue is that it will execute once, as in, it will only take in one input. I tried adding a loop but couldn't get it to work.
Server.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Net;
namespace server
{
class server
{
const string SERVER_IP = "127.0.0.1";
static void Main(string[] args)
{
//Create Dictionary
Dictionary<string, string> dict = new Dictionary<string, string>();
//---Read Text File containing commands ---
StreamReader sr = new StreamReader(#"C:\Users\Desktop\potato.txt");
string line;
//Splits the text into commands:responses
while ((line = sr.ReadLine()) != null)
{
string[] arr = line.Split(';');
dict.Add(arr[0], arr[1]);
}
//Print dictionary TESTING FUNCTION
foreach (KeyValuePair<string, string> kvp in dict)
{
Console.WriteLine("Command = {0} Response = {1}", kvp.Key, kvp.Value);
}
//---Input the port number for clients to conect---
Console.Write("Input port" + System.Environment.NewLine);
int PORT_NO = int.Parse(Console.ReadLine());
//---listen at the specified IP and port no.---
IPAddress localAdd = IPAddress.Parse(SERVER_IP);
TcpListener listener = new TcpListener(localAdd, PORT_NO);
Console.WriteLine("Listening for Commands");
listener.Start();
//---incoming client connected---
TcpClient client = listener.AcceptTcpClient();
//---get the incoming data through a network stream---
NetworkStream nwStream = client.GetStream();
byte[] buffer = new byte[client.ReceiveBufferSize];
//---read incoming stream---
int bytesRead = nwStream.Read(buffer, 0, client.ReceiveBufferSize);
//---convert the command data received into a string---
string dataReceived = Encoding.ASCII.GetString(buffer, 0, bytesRead);
Console.WriteLine("Received Command : " + dataReceived);
//---Search Command and send a response
string Response;
if (dict.TryGetValue(dataReceived, out Response))
{
Console.WriteLine(Response);
}
//---write back the response to the client---
Console.WriteLine("Sending Response : " + Response);
nwStream.Write(buffer, 0, bytesRead);
Console.ReadLine();
}
}
}
You need to convert Response to a byte[] just as you do in the client sending your request (i.e. bytesToSend). E.g.:
Console.WriteLine("Sending Response : " + Response);
byte[] bytesToSend = ASCIIEncoding.ASCII.GetBytes(Response);
nwStream.Write(bytesToSend, 0, bytesToSend.Length);
Console.ReadLine();
That said, you have made the classic mistake every person does who tries to write TCP code without first reading references about TCP and sockets: you mistakenly believe that when you read from a socket, you will always receive in that single operation every byte that was read. So even with the above fix (which does address the issue on the server side), it is possible you will see partial responses on the client side (not as likely when testing locally, but much more likely if you move to running on the Internet or across LANs, and especially as the message size increases).
For low-volume network interaction, you may want to consider wrapping your NetworkStream with StreamReader and StreamWriter objects, and use ReadLine() and WriteLine() to receive and send data (i.e. use line-breaks as the delimiter for the data).
As for dealing with multiple requests, given the code you have presented here, the simplest approach is to add a loop around the server code after the listener.Start() method. I.e. containing all the code after that statement, starting with the call to listener.AcceptTcpClient() and going to the last statement in the method. However, again this is only appropriate for low-volume network code. If you anticipate clients will need your server to handle multiple requests and especially if in quick succession, what you really want is for the client to maintain the connection, i.e. only connect once and then have it send multiple requests on that same connection.
Similarly, if you want to be able to handle multiple clients at once, you cannot run the server in a single thread. Instead, at the very least you'll need to use the thread-blocking logic you're using now, where you have a new thread created for each client. Better, would be to use the non-blocking API (e.g. NetworkStream.BeginRead(), StreamReader.ReadLineAsync(), etc. … there are many asynchronous options to choose from), and let .NET deal with the threading for you.
Doing it that way will require significant changes to the server code. You really should look carefully at various samples on MSDN and Stack Overflow to see how this sort of thing is done. I also strongly recommend you read through the Winsock Programmer's FAQ. It is not specifically about .NET at all, but does cover all of the key details you'll need to know in order to effectively and correctly use the .NET API.
Alright, so I'm pretty new to C# and I'm definitely pretty new to graphical programming. I'm using Visual Studio 2015 and writing my application in C#.
I have this hunk of code that I've been toying around with for a while. Essentially my program will send the HELLO, to the server, but the server isn't sending HELLO back. I have no firewall in the middle of client and server right now, but the process is getting hung waiting for the reply back. I honestly don't even want to do it this way, I want the listener to always run in the background while the user does other stuff so that my program functions, well normal. So I come to you oh great Stackoverflow... because I am definitely doing it wrong! Could someone please point me the right direction?
Current Code:
private void button1_Click(object sender, EventArgs e)
{
byte[] data = new byte[512];
byte[] result;
SHA512 shaM = new SHA512Managed();
result = shaM.ComputeHash(Encoding.UTF8.GetBytes(this.password.Text));
var hash = BitConverter.ToString(result).Replace("-", "");
this.send_message("127.0.0.1", 10545, 10545, "HELLO");
this.send_message("127.0.0.1", 10545, 10545, "AUTH:" + this.login.Text + ":" + hash);
//ListenForData.Start();
}
private void send_message(string server, int localPort, int remotePort, string message)
{
label4.Text = "Listening on port:" + localPort;
IPEndPoint lep = new IPEndPoint(IPAddress.Any, localPort);
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPAddress loginServer = IPAddress.Parse(server.ToString());
byte[] sendbuf = Encoding.ASCII.GetBytes(message);
IPEndPoint ep = new IPEndPoint(loginServer, remotePort);
s.SendTo(sendbuf, ep);
try
{
UdpClient udpClient = new UdpClient(lep);
byte[] bytes = udpClient.Receive(ref lep);
label4.Text = ep.ToString();
} catch ( Exception ex )
{
Console.WriteLine(ex.ToString());
}
}
UDPATE:
private static void UDPListener(object obj)
{
Task.Run(async () =>
{
using (var udpClient = new UdpClient(10545))
{
string rMessage = "";
string[] rArgs = new string[0];
while (true)
{
//IPEndPoint object will allow us to read datagrams sent from any source.
var receivedResults = await udpClient.ReceiveAsync();
rMessage += Encoding.ASCII.GetString(receivedResults.Buffer);
rArgs = rMessage.Split(new char[] { ':' });
if( rArgs[0] == "HELLO")
{
Console.Write("Received HELLO from server.");
byte[] data = new byte[512];
byte[] result;
SHA512 shaM = new SHA512Managed();
result = shaM.ComputeHash(Encoding.UTF8.GetBytes(obj.password.Text));
var hash = BitConverter.ToString(result).Replace("-", "");
send_message("127.0.0.1", 10545, 10545, "AUTH:" + obj.login.Text + ":" + hash);
}
}
}
});
}
You can safely ignore the advice from Blindy. The UdpClient.ReceiveAsync() method is specifically designed around the Task paradigm, and is much more efficient than dedicating a thread to receiving data. Because the Task is awaitable, it's also easier to integrate the ReceiveAsync() approach with a GUI program (e.g. Winforms or WPF). That said, for all that to work, you want to execute the ReceiveAsync() call in the UI thread, rather than in another Task.
Unfortunately, lacking a good, minimal, complete code example that clearly illustrates your question, it's not possible to say for sure how that would look. But it most likely would involve making your UDPListener() method an async method and calling it from the UI thread. Also, since you say the method can't access non-static members, the obvious solution to that is to make the method itself non-static. E.g.:
private static async Task UDPListener(object obj)
{
using (var udpClient = new UdpClient(10545))
{
string rMessage = "";
string[] rArgs = new string[0];
while (true)
{
//IPEndPoint object will allow us to read datagrams sent from any source.
var receivedResults = await udpClient.ReceiveAsync();
rMessage += Encoding.ASCII.GetString(receivedResults.Buffer);
rArgs = rMessage.Split(new char[] { ':' });
if( rArgs[0] == "HELLO")
{
Console.Write("Received HELLO from server.");
byte[] data = new byte[512];
byte[] result;
SHA512 shaM = new SHA512Managed();
result = shaM.ComputeHash(Encoding.UTF8.GetBytes(obj.password.Text));
var hash = BitConverter.ToString(result).Replace("-", "");
send_message("127.0.0.1", 10545, 10545, "AUTH:" + obj.login.Text + ":" + hash);
}
}
}
}
It is not clear from your updated question whether you have fixed your failed to receive a reply yet. But if you have not changed your send_message() method, it has some obvious problems, especially in the context of creating a separate UdpClient instance to receive datagrams.
The most obvious issue is that you do not create the UdpClient instance which you're expecting to use to receive the response until after you have sent the message. This is wrong for two reasons:
It's entirely possible that the remote endpoint will send the response before you've created the socket. If that happens, the datagram will just be dropped.
More importantly, the usual design for a server is to send a response to the remote endpoint that sent it the message in the first place. I.e. in this case that would be the socket s. Even if you did create the udpClient object before calling s.SendTo(), the reply would actually be sent to the s socket, not the udpClient.Client socket.
Again, without a good code example it's not possible to know what your server actually does. But whether it behaves like a normal server, or is some non-standard implementation, the code you've posted cannot reliably receive a response from the server.
You should fix your design so that your client creates only a single socket (e.g. an initial UdpClient instance). You would prepare for communication by calling ReceiveAsync(), and only once you've done that, thus ensuring you're ready to receive a response, then you can send data.
Make sure that you create only this single object.
Note also that client-side implementations typically do not bind to a specific port. Instead, you let the OS assign a port. Only the server needs to bind to a specific port, so that inbound requests from unknown endpoints can know to what port to send their request. The server's receive operation will include the port number of the client, so the server will know to what port to send its response, without the client having selected any special port number.
Finally, I strongly recommend you study existing socket programming tutorials, and especially the Winsock Programmer's FAQ. None of the material there is directly applicable to the .NET socket API, but most of the issues you will have trouble with are exactly the kinds of things documented there. It is not possible to use the .NET socket API without also having a good basic comprehension of socket programming generally.
If the above does not get you headed in the right direction, please make sure that any future questions you ask include a good code example, as described in the link I provided above. Note that for any networking question, a complete code example includes both the client and server. It is not possible for anyone to fully understand your question, never mind to test and fix your code example, without implementations of both.
Recently, I was given an assignment...
"To develop a Windows Forms application which can be installed on various windows machines at an office or enterprise. There would be a database in just one machine(ALPHA machine).. This database would be used by applications on other Beta machines to access data. The application would itself manage to check if it is an Alpha or a Beta (Has Database file with it?) and hence has to act as a server or a client."
I can do everything except the Network and Inter-Application Communication requirements. So, I started to learn Socket Programming over the Internet and I have gone through this link...
The idea I am working on is...
To have the client send the message to server.
To have the server accept this message and put this message in queue.
Read the message to get Client's IP Address and the its Request for Data.
Apply this request on database and get the result.
Convert the result in string.
Send it to the requesting client.
I can manage to perform steps 3,4 & 5. I am stuck on 1, 2 & 6.
Towards this...
I have created a function for Server as well as for client who return the Sockets when called. I create a separate function as I like my code to be clean, tidy and understandable after years.
Check my code below...
For Server...
private Socket GetServerReady()
{
IPEndPoint RemoteEP = new IPEndPoint(IPAddress.Any, 8000);
Socket newSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
newSock.Connect(RemoteEP);
newSock.Listen(10);
return (newSock);
}
You will notice there is no Accept() method anywhere, This is because I wish to call it like below for further use...
Socket CltSock = GetServerReady().Accept();
The Code for Client is...
private Socket GetClientReady()
{
IPEndPoint RemoteEP = new IPEndPoint(IPAddress.Parse(txtBxHost2.Text.Trim()), 8000);
Socket ServerSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
ServerSock.Connect(RemoteEP);
return (ServerSock);
}
Finally, The questions are....
"Where is the appropriate place to call the functions I wrote above?"
"Should I call the Server and Client Function in Form_Load() Event?"
"What must be the next step towards my main intention which is point 1,2 & 6 mentioned above?"
I don't expect the full code that I can just copy as it is. Just the correct procedure and a little detail over the concept would do.
I would be using just a single PC for testing purpose. Also, another limitation is, It would all be coded in a single application. I don't want to write two separate applications for client & server.
I hope I made it all clear for you to understand.
Thanks a Lot.
Awaiting the response.
I was struggling to get things done and somehow managed to get the solution.
Below is my solution:
Server Side code:
(I put this code in a function which loops back the execution if any exception is caught)
private void Looper()
{
int i = 0;
int AttemptCount = 1;
while (i == 0)
{
try
{
TcpListener tL = new TcpListener(Network.GetLocalIPAddress(), 56009);
tL.Start(10);
Socket tS = tL.AcceptSocket();
if (tS.Connected)
{
NetworkStream nS = new NetworkStream(tS);
StreamReader Reader = new StreamReader(nS);
Output = Reader.ReadToEnd().Trim();
Reader.Close();
nS.Close();
tS.Close();
tL.Stop();
//If Done, End Execution
i = 1;
}
else
{
MessageBox.Show("The connection to the client is broken or failed..!!\n\nPlease check connection and try again.","Error",MessageBoxButtons.OK,MessageBoxIcon.Error);
}
}
catch (SystemException ex)
{
//If Not, Loop Execution Again
if (MessageBox.Show("Exception: " + ex.Message + "\n\nAttempt Count: " + AttemptCount + "\n\nDo you want to terminate the transmission?", "Error", MessageBoxButtons.YesNo, MessageBoxIcon.Error) == DialogResult.Yes)
{
i = 1;
ResetTimer.Stop();
}
else
{
i = 0;
AttemptCount++;
}
}
}
}
When above function is called, The server waits to accept any incoming socket. If there is any error somewhere due to port re-usage or anything, It loops back itself and resets the server. (So, we don't have to manually call the server function again & again.)
Once the server accepts any incoming socket, the execution ends up successfully. Lot's of time we don't want to keep invoking server even after a successful reception. So, I, instead of calling this function in a button "click_event", I called it in a timer Tick_Event. So, the human need is eliminated at server side.
This leads to a problem. Once the server starts waiting to accept, It is in blocking mode.
It hangs all the processes and controls in same thread. So, I moved the call to above function to BackgroundWorker's "Do_Work" Event.
Check below Code:
private void GetServerReady()
{
if (!bW.IsBusy)
{
bW.RunWorkerAsync();
txtBxHistory.Text += "\r\n" + Output;
}
}
private void bW_DoWork(object sender, DoWorkEventArgs e)
{
Looper();
}
private void ResetTimer_Tick(object sender, EventArgs e)
{
GetServerReady();
}
"bW" is "BackgroundWorker".
"Output" is a variable I defined globally.
The reason we need a variable is that,
BackgroundWorker has its own thread to execute the code placed in its "Do_Work" Event. So, a TextBox from our application's thread can't be used by BackgroundWorker to store the received output. Doing this to a variable and then setting TextBox's Text property to this variable does the trick.
Client Side code:
private void btnSend_Click(object sender, EventArgs e)
{
TcpClient socketForServer;
try
{
socketForServer = new TcpClient(txtBxDestIP.Text.Trim(), 56009);
}
catch
{
MessageBox.Show("Failed to connect to server at " + txtBxDestIP.Text.Trim() + ":999", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
NetworkStream networkStream = socketForServer.GetStream();
StreamWriter streamWriter = new System.IO.StreamWriter(networkStream);
try
{
string InputString;
InputString = Network.GetLocalIPAddress() + ": " + txtBxData.Text;
streamWriter.Write(InputString);
streamWriter.Flush();
socketForServer.Close();
txtBxHistory.Text += "\r\nMe: " + txtBxData.Text.Trim();
txtBxData.Clear();
}
catch
{
MessageBox.Show("Exception reading from Server.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
streamWriter.Close();
networkStream.Close();
socketForServer.Close();
}
"txtBxDestIP" is a TextBox having the Destination IP address as Text.
"txtBxData" is a TextBox having the text to be sent.
This code works flawless for me. With above solution I can achieve all my motives from step 1 to 6 (Mentioned in the question above.)
I hope it helps others too. Please suggest if there is a better and efficient way to perform this.
Thanks.
Regards.
I have created TCP Server application in Java, and a client application in C#. When i am sending data, the client sometimes receives data out of order, and sometimes parts miss entirely. Basically, the code i use in the server (java) looks like this (stripped):
ServerSocket welcomeSocket = new ServerSocket(port);
Socket connectionSocket = welcomeSocket.accept();
outputStream = new DataOutputStream(socket.getOutputStream()); //Create stream
outputStream.writeBytes(message + "\n");
outputStream.flush();
I use "\n" as a delimiter. On the client side (C#) i use the following code:
private const char Delimiter = '\n';
tcpclnt = new TcpClient();
tcpclnt.NoDelay = true;
tcpclnt.Client.DontFragment = true;
tcpclnt.Connect(ip, port);
//This function is executed in a separate thread
public void Receive()
{
try
{
stream = tcpclnt.GetStream();
streamreader = new StreamReader(stream);
this.Connected = true;
while (Connected)
{
string line = ReadLine(streamreader);
Console.WriteLine("Received data: " + line);
}
}
}
private string ReadLine(StreamReader reader)
{
bool finished = false;
string line = "";
while (finished == false)
{
int asciiNumber = reader.Read();
char character = Convert.ToChar(asciiNumber);
if (!character.Equals(Delimiter))
line += character;
else finished = true;
}
return line;
}
The code is not very complicated. However, the data sent from the server is not always received correctly in the client. As an example, I should receive the following two strings:
"5_8_1" and "6_LEVELDATA"
What i get (sometimes) however, is this: "5_8_61" and "_LEVELDATA"
Another example: "5_4_1" and "6_LEVELDATA" result in one single string: "5_6_LEVELDATA"
This seems like some small problem, but it does in fact pretty much ruin my application. I have read a lot of posts, but the only answers i have read are either "this shouldnt happen with TCP" or "send the length of the tcp message first" which would not help in any way in this case, because the problem isn't the data being split up in multiple packages, it simply isn't arriving in the right order, which is something TCP should do.
I am 100% sure the string is always complete before it is being sent by the Java application.
I really wonder what i'm doing wrong here. Is something messed up bad in my code? I would appreciate any help with this problem. Thanks in advance.
After trying Wireshark, it appears my problem existed in the server. Apparently every TCP-message was sent in a seperate thread. Thank you for all of your comments! My problem is solved now.
So, for a bit of background :
This class is created to accept and respond to calls made remotely in an HTTP format.
The problem is when the method of the request is POST, sometimes the request is processed correctly, but most of the times the class just ends up being irresponsive.
Also, the line "Debug1" and "Debug2" are never written to the console, even when the request is processed correctly.
The line "Debug3" appears only when the request is processed correctly.
I know this will probably look messy, C# is only a hobby for me, and I'm learning :)
Thanks for spending some time to go through this code!
Here is the code:
class WebServer
{
private TcpListener myListener;
public WebServer(int port)
{
//Threading the listener
try
{
myListener = new TcpListener(IPAddress.Any, port) ;
myListener.Start();
Thread th = new Thread(new ThreadStart(StartListen));
th.Start() ;
}
catch(Exception e)
{
Logs.Add("WebServer|An Exception Occurred while Listening :" +e.ToString());
}
}
private void StartListen()
{
int iStartPos = 0;
string sHttpVersion;
string sResponse = "";
string sCode = " 200 OK";
while(true)
{
//Accept a new connection
Socket mySocket = myListener.AcceptSocket();
if(mySocket.Connected)
{
Byte[] bReceive = new Byte[1024];
int i = mySocket.Receive(bReceive,bReceive.Length,SocketFlags.None);
string sBuffer = Encoding.ASCII.GetString(bReceive).TrimEnd('\0');
iStartPos = sBuffer.IndexOf("HTTP",1);
sHttpVersion = sBuffer.Substring(iStartPos,8); //http version (ex: "HTTP/1.1")
if (sBuffer.StartsWith("GET / "))
{
Logs.Add("WebServer|Connected:" + mySocket.RemoteEndPoint.ToString());
sResponse = ArrayToJson();
}
else if (sBuffer.StartsWith("POST"))
{
Console.WriteLine("Debug1");
//This is a POST request, so more data is waiting to be retreived...
bReceive = new Byte[2048];
i = mySocket.Receive(bReceive,bReceive.Length,SocketFlags.None);
sBuffer = Encoding.ASCII.GetString(bReceive).TrimEnd('\0');
Console.WriteLine("Debug2");
//Parsing the request
string[] sParams = sBuffer.Split(',');
Console.WriteLine(sParams.Length);
Console.WriteLine("Debug3: {0} - {1} - {2} - {3} - {4}", sParams[0], sParams[1], sParams[2], sParams[3], sParams[4]);
//I do what needs to be done here
Logs.Add("WebServer|BotStartRequest:" + mySocket.RemoteEndPoint.ToString());
sResponse = "Accepted";
}
//Sending response and closing socket
SendHeader(sHttpVersion, "text/html", sResponse.Length, sCode, ref mySocket);
SendToBrowser(sResponse, ref mySocket);
mySocket.Close();
}
}
}
}
}
Implementing HTTP/1.1 is not a simple task. The basic protocol looks quite simple, but it's really hard to get even a minimal server implementation right: You have at least to think about persistent connections, in the case of POST of the Expect: 100-continue header, correctly parsing the header, and much more.
I strongly recommend you have a look at existing libraries/code. For example, the HttpListener class is built into the .NET Framework and probably already provides all you'll ever need.
If you really want to implement a server from scratch, have a look at Microsoft Cassini, a simple HTTP server written in C# licensed under Ms-PL.