socket异步处理问题

news/2024/7/3 14:37:41
由于一个项目要和第三方软件做接口,第三方软件是Unix的操作系统,所以用了Socket来传输数据。
具体结构是这样的:本项目作为服务器端,第三方软件是客户端,并且有多个客户端。

通常情况下,要开多个线程来处理多个客户端,并且一个客户端要占用一个端口,每个客户端在访问服务端时,服务器端要找到当前空闲的端口返回给客户端进行调用。
msdn上提供了这种的解决方案:
http://www.microsoft.com/china/msdn/archives/library/dncscol/html/csharp09182003.asp

但是,经过我今天的摸索,发现用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;
        }
 



http://www.niftyadmin.cn/n/3652867.html

相关文章

Linux挂载windows 共享文件

Linux挂载windows 共享文件学习目标操作步骤学习目标 Linux挂载window 共享文件 操作步骤 windows端共享权限设定: 1.解禁Guest 右击我的电脑选择管理–>本地用户和组–>在用户项中双击Guest用户–>取消账号已禁用选项 2.设置共享目录权限 右击共享目录点属性–…

.Net Remoting中Remote Server的Port占用/释放问题

这一问题一般出现在Console application/Windows Service承载Remote Objects时&#xff0c;要求Remote Server指定特定port。IIS在承载Remote Objects并不需要指定特定port&#xff0c;因此一般不会出现SocketException异常信息。1. 启动承载Remote Objects的Console applicati…

LVM逻辑卷管理和磁盘配额

LVM逻辑卷管理和磁盘配额一. LVM逻辑卷管理1. 逻辑卷管理2. LVM机制的基本概念2.1 LVM主要命令2.2 LVM应用实例2.3 扩容二. 磁盘配额1. 磁盘配额基本2. 命令3. 查看磁盘容量和文件数的报告4. 磁盘配额步骤及验证一. LVM逻辑卷管理 1. 逻辑卷管理 ●能够在保持现有数据不变的情…

信道、接收器、接收链和信道接受提供程序

Channel, Sink, Sink Chain and Channel Sink Provider为了扩展.Net Remoting&#xff0c;定制接收器&#xff08;Sink&#xff09;和信道接受提供程序&#xff08;Channel Sink Provider&#xff09;&#xff0c;改变.Net Remoting的缺省行为&#xff0c;需要先了解.Net Remot…

Linux操作系统引导过程及启动类故障,服务控制,运行级别和优化启动过程

Linux操作系统引导过程及启动类故障&#xff0c;服务控制&#xff0c;运行级别和优化启动过程一. Linux操作系统引导过程1.开机自检2.MBR引导3. GRUB菜单4. 加载Linux 内核5. init 进程初始化5.1 系统初始化进程5.2 Systemd 单元类型5.3 运行级别所对应的Systemd目标二. 排除启…

用AS3调用摄像头(附源代码下载)

用as3调用摄像头&#xff0c;代码如下&#xff1a;package { import flash.display.Sprite; import flash.text.*; import flash.media.Camera; import flash.events.StatusEvent; import flash.events.ActivityEvent; import flash.media.Video; public class CameraEx extend…

Linux之进程信息及定时任务设置

进程信息及定时任务设置一. 查看进程1. 程序和进程的关系2. 查看进程信息2.1 ps 查看静态的进程统计信息2.2 top 查看动态的进程排名信息2.3 pgrep 命令根据特定条件查询进程 PID 信息2.4 pstree 查看进程数二. 控制进程三. at 一次性任务设置四. crontab 周期性任务设置1. cro…