понедельник, 9 апреля 2012 г.

TCP Non-Blocking

Ниже преведен пример не блокируемого TCP клиента




using System;
using System.Collections;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace TcpSock
{
class TcpSock
{
int    tcpIndx = 0;
int    tcpByte = 0;
byte[] tcpRecv = new byte[1024];

////////////////////////////////////////
public Socket tcpSock;
////////////////////////////////////////

public int Recv  (ref string tcpRead)
{
    tcpByte = tcpSock.Available;
    if (tcpByte > tcpRecv.Length - tcpIndx)
        tcpByte = tcpRecv.Length - tcpIndx;

    tcpByte = tcpSock.Receive(tcpRecv, tcpIndx, tcpByte, 
        SocketFlags.Partial);
    tcpRead = Encoding.ASCII.GetString
        (tcpRecv, tcpIndx, tcpByte);
    tcpIndx+= tcpByte;
    return    tcpRead.Length;
}

public int RecvLn(ref string tcpRead)
{
    tcpRead = Encoding.ASCII.GetString
        (tcpRecv, 0, tcpIndx);
    tcpIndx = 0;
    return    tcpRead.Length;
}

public int Send  (string tcpWrite)
{
    return tcpSock.Send(Encoding.ASCII.GetBytes(tcpWrite));
}

public int SendLn(string tcpWrite)
{
    return tcpSock.Send(Encoding.ASCII.GetBytes(tcpWrite + "\r\n"));
}
}


class Tcp
{
[STAThread]
static void Main()
{
    ////////////////////////////////////////////////////////////////////////////////////////////
    ///class IPHostEntry : Stores information about the Host and is required 
    ///for IPEndPoint.
    ///class IPEndPoint  : Stores information about the Host IP Address and 
    ///the Port number.
    ///class TcpSock     : Invokes the constructor and creates an instance.
    ///class ArrayList   : Stores a dynamic array of Client TcpSock objects.

    IPHostEntry Iphe   = Dns.Resolve   (Dns.GetHostName());
    IPEndPoint  Ipep   = new IPEndPoint(Iphe.AddressList[0], 4444);
    Socket      Server = new Socket    (Ipep.Address.AddressFamily, 
    SocketType.Stream, ProtocolType.Tcp);

    ////////////////////////////////////////////////////////////////////////////////////////////
    ///Initialize
    ///Capacity : Maximux number of clients able to connect.
    ///Blocking : Determines if the Server TcpSock will stop code execution 
    ///to receive data from the Client TcpSock.
    ///Bind     : Binds the Server TcpSock to the Host IP Address and the Port Number.
    ///Listen   : Begin listening to the Port; it is now ready to accept connections.

    ArrayList Client = new ArrayList ();
    string    rln    = null;

    Client.Capacity =   256;
    Server.Blocking = false;
    Server.Bind  (Ipep);
    Server.Listen( 32 );

    Console.WriteLine("{0}: listening to port {1}", Dns.GetHostName(), 
        Ipep.Port);

    ////////////////////////////////////////////////////////////////////////////////////////////
    ///Main loop
    ///1. Poll the Server TcpSock; if true then accept the new connection.
    ///2. Poll the Client TcpSock; if true then receive data from Clients.

    while (true)
    {
        //Accept
        if (Server.Poll(0, SelectMode.SelectRead))
        {
            int i = Client.Add(new TcpSock());
            ((TcpSock)Client[i]).tcpSock = Server.Accept ();
            ((TcpSock)Client[i]).SendLn("Welcome.");
            Console.WriteLine("Client {0} connected.", i  );
        }

        for (int i = 0; i < Client.Count; i++)
        {
            //check for incoming data
            if (((TcpSock)Client[i]).tcpSock.Poll(0, SelectMode.SelectRead))
            {
                //receive incoming data
                if (((TcpSock)Client[i]).Recv(ref rln) > 0)
                {
                    //echo incoming data
                    ((TcpSock)Client[i]).Send(rln);

                    //check for new line
                    if (rln == "\r\n")
                    {
                       ///receive line
                     ((TcpSock)Client[i]).RecvLn(ref rln);

                     //send the line to all clients
                     for (int y = 0; y < Client.Count; y++)
                        if (y != i)
                        ((TcpSock)Client[y]).Send(i.ToString() + ": " + rln);

                         Console.Write("{0}: {1}", i, rln);
                     }
                }
                    //recv returned <= 0; close the socket
                else
                {
                    ((TcpSock)Client[i]).tcpSock.Shutdown(SocketShutdown.Both);
                    ((TcpSock)Client[i]).tcpSock.Close();
                    Client.RemoveAt (i);
                    Console.WriteLine("Client {0} disconnected.", i);
                }
            }
        }
    }
}
}
}

Комментариев нет:

Отправить комментарий