<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
  <id>tag:www.refactormycode.com,2007:users1435</id>
  <link type="application/atom+xml" href="http://www.refactormycode.com/users/1435" rel="self"/>
  <title>teariok.myopenid.com</title>
  <updated>Sun Apr 05 23:18:18 -0700 2009</updated>
  <entry>
    <id>tag:www.refactormycode.com,2007:Refactor154333</id>
    <published>2009-04-05T23:18:18-07:00</published>
    <title>[C#] On C# Socket</title>
    <content type="html">&lt;p&gt;It was simply a learning exercise. I haven't used C# a great deal and I enjoy this kind of programming. Plus for another project I will likely be using sockets for TCP communication using a custom protocol, so working on improving my socket code would help with that.&lt;/p&gt;

&lt;pre&gt;&lt;/pre&gt;</content>
    <author>
      <name>teariok.myopenid.com</name>
      <email></email>
    </author>
    <link type="text/html" href="http://www.refactormycode.com/codes/813-c-socket/refactors/154333" rel="alternate"/>
  </entry>
  <entry>
    <id>tag:www.refactormycode.com,2007:Code813</id>
    <published>2009-04-05T18:48:01-07:00</published>
    <updated>2009-10-26T15:47:01-07:00</updated>
    <title>[C#] C# Socket</title>
    <content type="html">&lt;p&gt;This is a HTTP socket that I use in one of my projects. It can't handle anything other than 200 OK, but for the purpose it was intended anything other than that should fail anyway, so I don't need proper HTTP response code handling. I'm just hoping really that if there is a way it could be tidied up, sped up or otherwise improved that someone can show how and then learning can happen. My particular problem is reading the header a byte at a time, I am sure there is a better way but such a method escapes me.&lt;/p&gt;

&lt;p&gt;Oh and before you say it, I know I can just use WebRequest. If that is your only criticism, please keep it to yourself.&lt;/p&gt;

&lt;pre&gt;using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Net.Sockets;
using System.Collections;

namespace LPT_5.HTTPSocket
{
    class Socket
    {
        private System.Net.Sockets.Socket msSock = null;
        private String msHost = null;
        private int miPort = 80;
        private Hashtable mhHeaders=null;

        public Socket(String sHost, int iPort)
        {
            msHost = sHost;
            miPort = iPort;
            
            //Initialise Standard Headers
            mhHeaders = new Hashtable();
            AddHeader(&amp;quot;Connection&amp;quot;,&amp;quot;Close&amp;quot;); //We wont need to do any pipelining
            AddHeader(&amp;quot;Host&amp;quot;, sHost);
        }

        public void AddHeader(String sKey, String sValue)
        {
            if(!mhHeaders.ContainsKey(sKey))
                mhHeaders.Add(sKey,sValue);
        }

        private void RemoveHeader(String sKey)
        {
            if(mhHeaders.ContainsKey(sKey))
                mhHeaders.Remove(sKey);
        }

        public String GetURL(String sURL)
        {
            msSock = new System.Net.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            msSock.Connect(msHost, miPort);
            String sReq = &amp;quot;GET &amp;quot; + sURL + &amp;quot; HTTP/1.1&amp;quot;;
            sReq = TagHeaders(sReq);
            msSock.Send(System.Text.Encoding.ASCII.GetBytes(sReq));

            Hashtable htHeadParams = new Hashtable();
            int iResult = ReceiveHeader(ref htHeadParams);
            String sBody = null;
            if(htHeadParams.ContainsKey(&amp;quot;Content-Length&amp;quot;))
            {
                int iLen = Convert.ToInt32((String)htHeadParams[&amp;quot;Content-Length&amp;quot;],10);
                int iOffs = 0;
                byte[] bBuff = new byte[iLen];
                while (iOffs &amp;lt; iLen)
                {
                    iOffs += msSock.Receive(bBuff,iOffs,iLen-iOffs,SocketFlags.None);
                }
                sBody += System.Text.Encoding.ASCII.GetString(bBuff);
            }
            msSock.Close();

            return sBody;
        }

        public byte[] GetRaw(String sURL)
        {
            msSock = new System.Net.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            msSock.Connect(msHost, miPort);
            String sReq = &amp;quot;GET &amp;quot; + sURL + &amp;quot; HTTP/1.1&amp;quot;;
            sReq = TagHeaders(sReq);
            msSock.Send(System.Text.Encoding.ASCII.GetBytes(sReq));

            Hashtable htHeadParams = new Hashtable();
            if(ReceiveHeader(ref htHeadParams) == 200) //If we got the data with no problems
            {
                int iLen = Convert.ToInt32((String)htHeadParams[&amp;quot;Content-Length&amp;quot;], 10);
                byte[] bBuff = new byte[iLen];
                if (htHeadParams.ContainsKey(&amp;quot;Content-Length&amp;quot;))
                {
                    int iOffs = 0;
                    while (iOffs &amp;lt; iLen)
                    {
                        iOffs += msSock.Receive(bBuff, iOffs, iLen - iOffs, SocketFlags.None);
                    }
                }
                msSock.Close();

                return bBuff;
            }
            return null;
        }

        private String TagHeaders(String sReq)
        {
            IDictionaryEnumerator deEnumer = mhHeaders.GetEnumerator();
            while(deEnumer.MoveNext())
            {
                sReq += &amp;quot;\r\n&amp;quot; + deEnumer.Key + &amp;quot;: &amp;quot; + deEnumer.Value;
            }
            return sReq + &amp;quot;\r\n\r\n&amp;quot;;
        }

        private int ReceiveHeader(ref Hashtable htHash)
        {
            String sHead = null;
            byte[] buff = new byte[1];

            /*
             We dont know the size of the header, but we do know that header and
             body are separated by a double newline, so read a byte at a time until
             we receive double newline.
            */
            do
            {
                msSock.Receive(buff, 0, 1, SocketFlags.None);
                sHead += (char)buff[0];
            }
            while (!sHead.Contains(&amp;quot;\r\n\r\n&amp;quot;));
            int iResult = ProcessHeaders(sHead,ref htHash);

            return iResult;
        }

        private int ProcessHeaders(String sHead, ref Hashtable htHash)
        {
            //Split wont work with \r\n, so just regex away the carriage return
            String sToSplit = Regex.Replace(sHead,&amp;quot;\r&amp;quot;,&amp;quot;&amp;quot;);
            String[] sParams = sToSplit.Split('\n');

            foreach (String sItem in sParams)
            {
                String[] sKeyVal = sItem.Split(':');
                if(sKeyVal.Length &amp;gt;= 2)
                {
                    String sKey = sKeyVal[0].Trim();
                    String sVal = sKeyVal[1].Trim();
                    if (htHash.ContainsKey(sKey))
                        htHash[sKey] += ',' + sVal; //Group multiple headers
                    else
                        htHash.Add(sKey, sVal);
                }
            }

            String[] sResultParams = sParams[0].Split(' ');
            return Convert.ToInt32(sResultParams[1]); //Return the HTTP Response Code
        }
    }
}&lt;/pre&gt;</content>
    <author>
      <name>teariok.myopenid.com</name>
      <email>no-email@refactormycode.com</email>
    </author>
    <link type="text/html" href="http://www.refactormycode.com/codes/813-c-socket" rel="alternate"/>
  </entry>
</feed>

