在Windows8下的Windows App Store应用由于采用了不同于传统桌面应用的机制所以引进了一些新的机制,比如现在看到的StreamSocket就是用来替代以前的Socket的套接字连接对象。
那么在StreamSocket对象中如何与服务器建立连接呢?先看看下面的代码吧
StreamSocket _socket = new StreamSocket(); string hostIp="127.0.0.1";//需要连接的远程主机IP string port="6789";//远程主机的端口号 HostName hostName = new HostName(hostIp); try { //建立与服务区的连接 //该连接是由系统托管的,无法通过StreamSocket对象实例直接获取当前状态,如果在向实例中写入数据时发生异常则说明连接断开了 //由于ConnectAsync是一个异步方法,所以我们需要在前面加上await关键字来让线程等待链接完成后才继续执行。 await _socket.ConnectAsync(hostName, port); } catch (Exception exception) { //如果是未知异常则直接抛出 if (SocketError.GetStatus(exception.HResult) == SocketErrorStatus.Unknown) { throw; } } finally { }
这里关键的方法就是 _socket.ConnectAsync(hostName, port) ,用这句代码可以让StreamSocket实例向指定的地址发起一个长链接。
当需要关闭这个长连接时只需要调用 StreamSocket实例的Dispose()方法就行了,代码如下:
_socket.Dispose();
可是我做到这里的时候有一个问题,因为我需要将我的通信库是从老的Socket模型移植到新的StreamSocket模型中来,而在老的Socket模型中连接操作是同步执行的,而await关键字受限于只能在注册为async的异步方法中执行,这样就造成我的连接方法还没执行完成就继续执行接下来的发送方法。在这里我折腾了好久之后终于用线程锁的方式将连接转换成了同步方法,具体代码如下:
string _host=string.Empty; string _port=string.Empty; AutoResetEvent autore = new AutoResetEvent(false); public virtual void Connect(String host, string port) { this._host = host; this._port = port; //由于建立连接时需要收到握手信息,而握手信息只能在发起线程接收,所以这里我们另启一个线程来做链接操作。 Windows.System.Threading.ThreadPool.RunAsync(new Windows.System.Threading.WorkItemHandler(DoAsyncConnect)); //挂起当前线程 autore.WaitOne(); } //这是中间的委托方法,用来调用异步的连接方法 void DoAsyncConnect(object obj) { AsyncConnect(_host, _port); } public async virtual void AsyncConnect(string host, string port) { HostName hostName = new HostName(host); try { await _socket.ConnectAsync(hostName, port); } catch (Exception exception) { //如果是未知异常则直接抛出 if (SocketError.GetStatus(exception.HResult) == SocketErrorStatus.Unknown) { throw; } } finally { //链接执行完毕后继续执行线程 autore.Set(); } }
至此,StreamSocket与服务器的连接就已经建立完成。