由于一个项目要和第三方软件做接口,第三方软件是Unix的操作系统,所以用了Socket来传输数据。
具体结构是这样的:本项目作为服务器端,第三方软件是客户端,并且有多个客户端。
通常情况下,要开多个线程来处理多个客户端,并且一个客户端要占用一个端口,每个客户端在访问服务端时,服务器端要找到当前空闲的端口返回给客户端进行调用。
msdn上提供了这种的解决方案:
但是,经过我今天的摸索,发现用socket异步处理也能解决这个问题,只要一个端口就可以给n个客户端访问了。
并且客户不需要做异步处理,只是服务端做异步处理就可以了。这样的话,第三方软件改动量就很小,主要控制权在我这里。
客户端做法的代码片断:
创建连接:
mobj_stSend = new Socket ( AddressFamily.InterNetwork , SocketType.Stream , ProtocolType.Tcp ) ; // 初始化一个Socket实例 IPEndPoint tempRemoteIP = new IPEndPoint ( IPAddress.Parse ( textBox1.Text ) , mi_port ) ; // 根据IP地址和端口号创建远程终结点 EndPoint epTemp = ( EndPoint ) tempRemoteIP ; mobj_stSend.Connect ( epTemp ) ; // 连接远程主机的8000端口号 发送数据:
int iLength = textBox2.Text.Length ; // 获取要发送的数据的长度 Byte [ ] bySend = new byte [ iLength ] ; // 根据获取的长度定义一个Byte类型数组 bySend = System.Text.Encoding.Default.GetBytes ( textBox2.Text ) ; // 按照指定编码类型把字符串指定到指定的Byte数组 int i = mobj_stSend.Send ( bySend ) ; // 发送数据 服务器端做了一个Socket数组来存放所有客户端的连接:
private Socket ListenSoc ; public static ManualResetEvent allDone = new ManualResetEvent( false ); private Socket [] SocClient; private const int MAX_SOCKET = 100 ; Thread mobj_thTreadRead; 启动监听线程:
mobj_thTreadRead = new Thread ( new ThreadStart ( Listen ) ) ; // 以Listen过程来初始化Thread实例 mobj_thTreadRead.Start() ; // 启动线程 button1.Enabled = false ; 在Listen方法中使用异步访问:
void Listen() { int nPort = 8000; IPEndPoint ipLocalEndPoint; try { // IPAddress ipAddress = Dns.Resolve("localhost").AddressList[0]; ipLocalEndPoint = new IPEndPoint(GetServerIP(), nPort); } catch(SocketException socErr ) { MessageBox.Show(socErr.Message); return; } try { ListenSoc = new Socket(AddressFamily.InterNetwork, SocketType.Stream,ProtocolType.Tcp ); ListenSoc.Bind(ipLocalEndPoint); ListenSoc.Listen(100); while (true) { allDone.Reset(); ListenSoc.Soc.BeginAccept(new AsyncCallback(AcceptCallback),ListenSoc); //异步访问,并定义回调方法 allDone.WaitOne(); } } catch(Exception err) { MessageBox.Show(err.Message); } } 实现回调方法:
public void AcceptCallback(IAsyncResult ar) { try { allDone.Set(); WSocket listener = (WSocket) ar.AsyncState; int nSoc = GetAvailbleSocket(); //获取有效的Socket,即一个新的Socket实例SocClient[nSoc] = (Socket)ListenSoc.EndAccept(ar);//在这里处理接收过来得数据}} private int GetAvailbleSocket() { int i=-1; for( i=0;i<MAX_SOCKET;i++) { try { if (SocClient[i]==null) break; else { if (!SocClient[i].Soc.Connected) break; } } catch (Exception err) { MessageBox.Show("GetSock :"+err.Message); } } if ((i>-1)&& (i <MAX_SOCKET)) InitSocket(ref SocClient[i],i); return i; } Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1793977