using AD.SocketForm.Model;
using NLog;
using System;
using System.Net.Sockets;
using System.Threading; namespace AD.SocketForm.Service
{
/// <summary>
/// Socket连接类-可指定超时时间
/// 参考网址://www.cnblogs.com/weidagang2046/archive/2009/02/07/1385977.html
/// </summary>
public class SocketNewService
{
private Logger _logger = LogManager.GetCurrentClassLogger(); /// <summary>
/// 连接socket
/// </summary>
/// <param name="model"></param>
/// <param name="timeout">单位:毫秒</param>
/// <returns></returns>
public Socket Create(HubModel model, int timeout)
{
var isConnected = false;
var manualResetEvent = new ManualResetEvent(false);
var tcpClient = new TcpClient(); #region 异步方法委托
Action<IAsyncResult> action = (asyncresult) =>
{
try
{
TcpClient tcpclient = asyncresult.AsyncState as TcpClient; if (tcpclient.Client != null)
{
tcpclient.EndConnect(asyncresult);
isConnected = true;
}
//Thread.Sleep(1000);
}
catch (Exception ex)
{
_logger.Error(string.Format("获取socket异常,message:{0},stacktrace:{1}", ex.Message, ex.StackTrace));
isConnected = false;
}
finally
{
manualResetEvent.Set();
}
};
#endregion tcpClient.BeginConnect(model.IP, model.Port, new AsyncCallback(action), tcpClient); //判断在指定的时间以内是否收到释放锁的通知
if (manualResetEvent.WaitOne(timeout, false))
{
//Console.WriteLine("连接成功");
if (isConnected)
{
return tcpClient.Client;
}
else
{
return null;
}
}
else
{
//Console.WriteLine("超时");
tcpClient.Close();
return null;
}
} /// <summary>
/// 关闭socket
/// </summary>
/// <param name="socket"></param>
public void Close(Socket socket)
{
if (socket != null)
{
socket.Close();
socket = null;
}
} /// <summary>
/// 判断Socket是否已连接
/// </summary>
/// <param name="socket"></param>
/// <returns></returns>
public bool IsConnected(Socket socket)
{
if (socket == null || socket.Connected == false)
{
return false;
} bool blockingState = socket.Blocking;
try
{
byte[] tmp = new byte[];
socket.Blocking = false;
socket.Send(tmp, , );
return true;
}
catch (SocketException e)
{
// 产生 10035 == WSAEWOULDBLOCK 错误,说明被阻止了,但是还是连接的
if (e.NativeErrorCode.Equals())
{
return true;
}
else
{
return false;
}
}
catch (Exception ex)
{
_logger.Error(string.Format("检查Socket是否可连接时异常,message:{0},stacktrace:{1}", ex.Message, ex.StackTrace));
return false;
}
finally
{
socket.Blocking = blockingState; // 恢复状态
}
}
}
}

主要是通过两点:

1、通过if (manualResetEvent.WaitOne(timeout, false))来处理。它的作用是:阻止当前线程N毫秒,期间如果有调用manualResetEvent.Set()立即取消当前线程的阻塞,并且返回true;如果没有调用,时间到了后依然取消当前线程的阻塞,但是返回false。

2、通过tcpClient.BeginConnect(model.IP, model.Port, new AsyncCallback(action), tcpClient)建立tcp连接。这句话的意思是以异步的方式建立tcp连接,成功之后调用指定的回调方法。即new AsyncCallback(action)。

另外,这个类把回调方法写在了Create方法里面,原因是方便处理isConnected的状态,无需考虑线程同步。因为这个辅助类实例化后,是被驻留在内存里面的,有可能会被多次使用。为了线程安全,所以写在了里面。

最新文章

  1. call指令的一个细节
  2. windows系统下ftp上传下载和一些常用命令
  3. ADO.NET 快速入门(八):处理 Errors
  4. jQuery图片延迟加载插件
  5. linux+nginx+mysql+php
  6. jmeter里json path postprocessor的用法
  7. python生成二维码
  8. [日推荐] 『闲聊助手』人工智能小程序,仅此一款!-极乐商店store.dreawer.com
  9. formData 对象 与 Content-Type 类型
  10. Redhat Linux 配置Xmanager
  11. Eclipse关于怎么调出web project
  12. Yapi学习笔记
  13. android搜索框列表布局,流程及主要步骤思维导图
  14. $mount方法是用来挂载我们的Vue.extend扩展的
  15. mybatis 使用merge into
  16. SQL编写-谁和谁是好朋友
  17. Git - 必知必会
  18. 【BZOJ3139】[HNOI2013]比赛(搜索)
  19. 山东第四届省赛: Boring Counting 线段树
  20. GCD HDU - 1695 莫比乌斯反演入门

热门文章

  1. NIO ByteBuffer的allocate与allocateDirect区别(HeapByteBuffer与DirectByteBuffer的区别)
  2. VUE面刷新
  3. 【翻译】Tusdotnet中文文档(2)事件
  4. iOS11里判断Safari浏览器是无痕模式还是正常模式?
  5. 一个判断js数据类型的函数
  6. stdin,stdout 和 STDOUT_FILENO,STDIN_FILENO
  7. Python:日常应用汇总
  8. Java实现Redis的消息订阅和发布
  9. 2-剑指offer: 最小的K个数
  10. Python多线程采集百度相关搜索关键词