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的状态,无需考虑线程同步。因为这个辅助类实例化后,是被驻留在内存里面的,有可能会被多次使用。为了线程安全,所以写在了里面。

c# 创建socket连接辅助类-可指定超时时间的更多相关文章

  1. c# 创建socket连接辅助类

    using AD.SocketForm.Model; using NLog; using System; using System.Net; using System.Net.Sockets; nam ...

  2. Socket超时时间设置

    你知道在 Java 中怎么对 Socket 设置超时时间吗?他们的区别是什么?想一想和女朋友打电话的场景就知道了,如果实在想不到,那我们就一起来来看一下是咋回事吧 设置方式 主要有以下两种方式,我们来 ...

  3. Http和Socket连接区别

    相信不少初学手机联网开发的朋友都想知道Http与Socket连接究竟有什么区别,希望通过自己的浅显理解能对初学者有所帮助. 1.TCP连接 要想明白Socket连接,先要明白TCP连接.手机能够使用联 ...

  4. Http、tcp、Socket连接区别

    转自Http.tcp.Socket连接区别 相信不少初学手机联网开发的朋友都想知道Http与Socket连接究竟有什么区别,希望通过自己的浅显理解能对初学者有所帮助. 1.TCP连接 要想明白Sock ...

  5. Http和Socket连接的区别

    Http和Socket连接区别 相信不少初学手机联网开发的朋友都想知道Http与Socket连接究竟有什么区别,希望通过自己的浅显理解能对初学者有所帮助. 1.TCP连接 要想明白Socket连接,先 ...

  6. Http和Socket连接

    转自http://hi.baidu.com/%D2%B9%D1%A9%B3%E6/blog/item/d6a72d2bbf467cf2e7cd406d.html 相信不少初学手机联网开发的朋友都想知道 ...

  7. TCP连接、Http连接与Socket连接

    1.TCP连接 手机能够使用联网功能是因为手机底层实现了TCP/IP协议,可以使手机终端通过无线网络建立TCP连接.TCP协议可以对上层网络提供接口,使上层网络数据的传输建立在“无差别”的网络之上. ...

  8. Socket设置超时时间

    主要有以下两种方式,我们来看一下方式1: Socket s=new Socket(); s.connect(new InetSocketAddress(host,port),10000); 方式2: ...

  9. timeout Timeout时间已到.在操作完成之前超时时间已过或服务器未响应

    Timeout时间已到.在操作完成之前超时时间已过或服务器未响应 问题 在使用asp.net开发的应用程序查询数据的时候,遇到页面请求时间过长且返回"Timeout时间已到.在操作完成之间超 ...

随机推荐

  1. 阿里云Centos7用putty ssh链接掉线

    解决方法:修改云服务器 ssh 配置文件(修改前一定要先备份) (1)打开配置文件: vim /etc/ssh/sshd_config 1 (2)找到下面两行: ClientAliveInterval ...

  2. Python学习笔记之将数据写入到文件中

    10-3 访客:编写一个程序,提示用户输入其名字:用户作出响应后,将其名字写入到文件guest.txt 中. 编写Python代码: username = input("Please ent ...

  3. Eureka重要对象简介

    在进行分析EurekaClient和EurekaServer之间通信的源码之前,我们首先需要熟悉一下几个实体类 InstanceInfo 这个类代表着EurekaClient实例,客户端向服务端请求注 ...

  4. windows10风格 springboot vue.js html 跨域 前后分离 activiti 整合项目框架源码

    官网:www.fhadmin.org 此项目为Springboot工作流版本 windows 风格,浏览器访问操作使用,非桌面应用程序. 1.代码生成器: [正反双向](单表.主表.明细表.树形表,快 ...

  5. css的尺寸、display的属性、以及浮动和清除浮动的方法

    css的尺寸width heightline-height 行高是由三部分构成,上间距 文本高度 下间距,且上下间距相等.所以文字居中.行高:一旦设置了行高,元素内部必须有内容.line-height ...

  6. QML MouseArea学习小结

    QML中的MouseArea类型为用户进行简单的鼠标操作提供了方便. MouseArea是一个不可见的Item,通常与可见项目结合使用,以便为该项目提供鼠标处理.通过有效地充当代理,鼠标处理的逻辑可以 ...

  7. 用jTessBoxEditorFX训练字库

    软件下载:https://sourceforge.net/projects/vietocr/files/jTessBoxEditor/ 官方字库下载:https://github.com/tesser ...

  8. Odoo field字段标签属性详解

    转载请注明原文地址:https://www.cnblogs.com/ygj0930/p/10826356.html 标签属性 1) name:标识字段名称 2)string:标签文本,如果我们想要覆盖 ...

  9. Vim文本编辑器详细用法

    1 Vi.Vim文本编辑器 1.Vi.Vim Vi是Visual interface的简称. Vim是Vi的增强版,即Vi Improved.在后面的实例中将介绍Vim的使用. 为什么学vi? 1)所 ...

  10. Tram POJ - 1847

    题目链接:https://vjudge.net/problem/POJ-1847 思路:想从A到B使用开关少,想清楚了就是个简单的最短路,可以把不用开开关为权值0, 要开开关为权值1,就是求A到B开开 ...