博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
socket异步处理问题
阅读量:4190 次
发布时间:2019-05-26

本文共 2525 字,大约阅读时间需要 8 分钟。

由于一个项目要和第三方软件做接口,第三方软件是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

你可能感兴趣的文章
Elasticsearch Java API总汇
查看>>
SearchRequestBuilder常用方法说明
查看>>
为什么有的程序员的代码结构混乱
查看>>
查看数据库
查看>>
SQLite 数据库
查看>>
行业应用
查看>>
工作的常识
查看>>
java里面获取map的key和value的方法
查看>>
积累20180203
查看>>
MySQL里获取当前week、month、quarter的start_date/end_date
查看>>
Mysql中DATE_SUB 使用方法结合查询一天内,一周内,一月内的信息实例讲解
查看>>
异构数据源海量数据交换工具-Taobao DataX 下载和使用
查看>>
代理模式解析,静态代理、动态代理一文全都告诉你
查看>>
我是如何从电脑小白走上编程之路
查看>>
想成为优秀的Java程序员,你需要读哪些书?
查看>>
Java并发| Atomic包下的原子操作类使用与原理解析
查看>>
Mac M1 安装 iTerm2+Oh My Zsh+zsh-syntax-highlighting 真香!
查看>>
M1芯片Mac 安装git
查看>>
M1芯片Mac Homebrew 安装
查看>>
一篇文章看懂ZooKeeper内部原理
查看>>