由于一个项目要和第三方软件做接口,第三方软件是Unix的操作系统,所以用了Socket来传输数据。

具体结构是这样的:本项目作为服务器端,第三方软件是客户端,并且有多个客户端。


通常情况下,要开多个线程来处理多个客户端,并且一个客户端要占用一个端口,每个客户端在访问服务端时,服务器端要找到当前空闲的端口返回给客户端进行调用。

msdn上提供了这种的解决方案:

​http://www.microsoft.com/china/msdn/archives/library/dncscol/html/csharp09182003.asp​


但是,经过我今天的摸索,发现用socket异步处理也能解决这个问题,只要一个端口就可以给n个客户端访问了。

并且客户不需要做异步处理,只是服务端做异步处理就可以了。这样的话,第三方软件改动量就很小,主要控制权在我这里。

客户端做法的代码片断:

创建连接:

socket异步处理问题_数组mobj_stSend = new Socket ( AddressFamily.InterNetwork , 

socket异步处理问题_数组                    SocketType.Stream , ProtocolType.Tcp ) ; //初始化一个Socket实例 

socket异步处理问题_数组                

socket异步处理问题_数组                IPEndPoint tempRemoteIP = new IPEndPoint 

socket异步处理问题_数组                    ( IPAddress.Parse ( textBox1.Text ) , mi_port ) ; //根据IP地址和端口号创建远程终结点 

socket异步处理问题_数组                

socket异步处理问题_数组                EndPoint epTemp = ( EndPoint ) tempRemoteIP ; 

socket异步处理问题_数组                mobj_stSend.Connect ( epTemp ) ; //连接远程主机的8000端口号 


发送数据:

socket异步处理问题_数组 int iLength = textBox2.Text.Length ; //获取要发送的数据的长度 

socket异步处理问题_数组            

socket异步处理问题_数组                Byte [ ] bySend = new byte [ iLength ] ; //根据获取的长度定义一个Byte类型数组 

socket异步处理问题_数组            

socket异步处理问题_数组                bySend = System.Text.Encoding.Default.GetBytes 

socket异步处理问题_数组                    ( textBox2.Text ) ; //按照指定编码类型把字符串指定到指定的Byte数组 

socket异步处理问题_数组            

socket异步处理问题_数组                int i = mobj_stSend.Send ( bySend ) ; //发送数据 


服务器端做了一个Socket数组来存放所有客户端的连接:

socket异步处理问题_数组private Socket ListenSoc ; 

socket异步处理问题_数组        public static ManualResetEvent allDone = new ManualResetEvent(false);

socket异步处理问题_数组        private Socket [] SocClient;

socket异步处理问题_数组        private const int MAX_SOCKET= 100;

socket异步处理问题_数组        Thread mobj_thTreadRead;


启动监听线程:

 

socket异步处理问题_数组mobj_thTreadRead = new Thread ( new ThreadStart ( Listen ) ) ;//以Listen过程来初始化Thread实例            

socket异步处理问题_数组            mobj_thTreadRead.Start() ;//启动线程            

socket异步处理问题_数组            button1.Enabled = false  ;


在Listen方法中使用异步访问:

socket异步处理问题_数组void Listen()

socket异步处理问题_客户端_26socket异步处理问题_异步处理_27        socket异步处理问题_异步处理_28{

socket异步处理问题_ipad_29            int nPort = 8000;            

socket异步处理问题_ipad_29            IPEndPoint ipLocalEndPoint;

socket异步处理问题_ipad_29            try

socket异步处理问题_服务器端_32socket异步处理问题_客户端_33            socket异步处理问题_异步处理_28{

socket异步处理问题_ipad_29//                IPAddress ipAddress = Dns.Resolve("localhost").AddressList[0];

socket异步处理问题_ipad_29                ipLocalEndPoint = new IPEndPoint(GetServerIP(), nPort); 

socket异步处理问题_ipad_37            }

socket异步处理问题_ipad_29            catch(SocketException socErr )

socket异步处理问题_服务器端_32socket异步处理问题_客户端_33            socket异步处理问题_异步处理_28{

socket异步处理问题_ipad_29                MessageBox.Show(socErr.Message);

socket异步处理问题_ipad_29                return;

socket异步处理问题_ipad_37            }

socket异步处理问题_ipad_29           

socket异步处理问题_ipad_29            try

socket异步处理问题_服务器端_32socket异步处理问题_客户端_33            socket异步处理问题_异步处理_28{                

socket异步处理问题_ipad_29                ListenSoc = new Socket(AddressFamily.InterNetwork, SocketType.Stream,ProtocolType.Tcp );

socket异步处理问题_ipad_29                ListenSoc.Bind(ipLocalEndPoint);

socket异步处理问题_ipad_29                ListenSoc.Listen(100);

socket异步处理问题_ipad_29                while (true)

socket异步处理问题_服务器端_32socket异步处理问题_客户端_33                socket异步处理问题_异步处理_28{

socket异步处理问题_ipad_29                    allDone.Reset();

socket异步处理问题_ipad_29                    ListenSoc.Soc.BeginAccept(new AsyncCallback(AcceptCallback),ListenSoc); //异步访问,并定义回调方法

socket异步处理问题_ipad_29                    allDone.WaitOne();

socket异步处理问题_ipad_29

socket异步处理问题_ipad_37                }

socket异步处理问题_ipad_37            }

socket异步处理问题_ipad_29            catch(Exception err) 

socket异步处理问题_服务器端_32socket异步处理问题_客户端_33            socket异步处理问题_异步处理_28{

socket异步处理问题_ipad_29                MessageBox.Show(err.Message);

socket异步处理问题_ipad_37            }

socket异步处理问题_ipad_69        }


实现回调方法:

socket异步处理问题_数组public void AcceptCallback(IAsyncResult ar) 

socket异步处理问题_客户端_26socket异步处理问题_异步处理_27        socket异步处理问题_异步处理_28{

socket异步处理问题_ipad_29            try

socket异步处理问题_服务器端_32socket异步处理问题_客户端_33            socket异步处理问题_异步处理_28{

socket异步处理问题_ipad_29                allDone.Set();

socket异步处理问题_ipad_29                WSocket listener = (WSocket) ar.AsyncState;

socket异步处理问题_ipad_29                int nSoc = GetAvailbleSocket(); //获取有效的Socket,即一个新的Socket实例

socket异步处理问题_ipad_29SocClient[nSoc] = (Socket)ListenSoc.EndAccept(ar);

socket异步处理问题_ipad_29//在这里处理接收过来得数据

socket异步处理问题_ipad_37}

socket异步处理问题_ipad_69}


socket异步处理问题_数组private int GetAvailbleSocket()

socket异步处理问题_客户端_26socket异步处理问题_异步处理_27        socket异步处理问题_异步处理_28{

socket异步处理问题_ipad_29            int i=-1;

socket异步处理问题_ipad_29            for( i=0;i<MAX_SOCKET;i++)

socket异步处理问题_服务器端_32socket异步处理问题_客户端_33            socket异步处理问题_异步处理_28{

socket异步处理问题_ipad_29                try

socket异步处理问题_服务器端_32socket异步处理问题_客户端_33                socket异步处理问题_异步处理_28{

socket异步处理问题_ipad_29                    if (SocClient[i]==null)

socket异步处理问题_ipad_29                        break;

socket异步处理问题_ipad_29                    else

socket异步处理问题_服务器端_32socket异步处理问题_客户端_33                    socket异步处理问题_异步处理_28{

socket异步处理问题_ipad_29                        if (!SocClient[i].Soc.Connected)

socket异步处理问题_ipad_29                            break;

socket异步处理问题_ipad_37                    }

socket异步处理问题_ipad_37                }

socket异步处理问题_ipad_29                catch (Exception err) 

socket异步处理问题_服务器端_32socket异步处理问题_客户端_33                socket异步处理问题_异步处理_28{

socket异步处理问题_ipad_29                    MessageBox.Show("GetSock :"+err.Message);

socket异步处理问题_ipad_37                }

socket异步处理问题_ipad_29

socket异步处理问题_ipad_37            }

socket异步处理问题_ipad_29

socket异步处理问题_ipad_29            if ((i>-1)&& (i <MAX_SOCKET))  

socket异步处理问题_ipad_29                InitSocket(ref SocClient[i],i);

socket异步处理问题_ipad_29            return i;

socket异步处理问题_ipad_69        }