0.虽然之前在项目中也有用过Socket,但始终不是自己搭建的,所以对Server,Clinet端以及心跳,断线重连总没有很深入的理解,现在自己搭建了一遍加深一下理解。

服务端使用WPF界面,客户端使用控制台。实现了心跳,断线重连,一个服务端对应多个客户端的功能。

一.服务端

1.1 先创建一个Socket实例,并绑定到20000端口号;通过Listen方法开始监听并设置最大监听数量。

//新建一个Socket服务端实例,并绑定到20000端口
socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socketServer.Bind(new IPEndPoint(IPAddress.Any, )); //设置最大监听数量
socketServer.Listen();

1.2 当有客户端成功连接,则会通过Accept方法生产一个新的Socket实例;此时可开启心跳定时器,并开启一个线程接收消息。

//开启一个线程监听客户端
Thread thd = new Thread(new ThreadStart(ListenSocket));
thd.Start(); /// <summary>
/// 开始监听
/// </summary>
private void ListenSocket()
{
try
{
while (true)
{
Socket _socket = socketServer.Accept(); //开始心跳
System.Timers.Timer heartbeatTimer = new System.Timers.Timer();
heartbeatTimer.Interval = ;
heartbeatTimer.Elapsed += new System.Timers.ElapsedEventHandler((s, e) => heartbeatTimerIsUp(s, e, _socket));
heartbeatTimer.Start(); Thread thdReceive = new Thread(new ParameterizedThreadStart(thdRevMethod));
thdReceive.Start(_socket);
}
}
catch (Exception ex)
{
MessageBox.Show("程序出现异常:" + ex);
}
}

1.3 接收消息与发送消息的代码如下

/// <summary>
/// 接收消息
/// </summary>
/// <param name="obj"></param>
private void thdRevMethod(object obj)
{
Socket _socket = obj as Socket;
try
{
while (true)
{
byte[] resByte = new byte[];
int resInt = _socket.Receive(resByte);
if (resInt > )
{
string res = Encoding.Default.GetString(resByte, , resInt);///接收消息后操作
}
}
}
catch (SocketException sex)
{
if (sex.SocketErrorCode == SocketError.ConnectionReset)
{
//当客户端断开连接,从客户端列表中移除该客户端
}
}
catch (Exception ex)
{
MessageBox.Show("程序出现异常:" + ex);
}
} /// <summary>
/// 发送消息
/// </summary>
/// <param name="msg"></param>
/// <param name="ipAndPord"></param>
public bool sendMsg(string msg,string ipAndPord)
{
try
{
Socket _socket = socketTimerDic.SingleOrDefault(r => string.Equals(r.Key.RemoteEndPoint.ToString(), ipAndPord)).Key;
if (_socket != null)
{
byte[] byteStr = Encoding.Default.GetBytes(msg);
_socket.Send(byteStr);
return true;
}
else
{
return false;
}
}
catch (Exception)
{
return false;
}
}

二.客户端

2.1 先创建一个Socket实例,并连接到服务端所在的ip端口;连接成功后开启心跳定会器并开启发送和接收消息的两个线程。

// 新建客户端实例,并连接到服务端所在的端口号
socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); socketClient.Connect("127.0.0.1", );
Console.WriteLine("成功连接到服务端");
heartbeatTimer.Start(); //开启一个线程发送消息
Thread thdSend = new Thread(new ThreadStart(thdSendMethod));
thdSend.Start(); //开启一个线程接收信息
Thread thdRev = new Thread(new ThreadStart(thdRevMethod));
thdRev.Start();

2.2 发送消息和接收消息的代码如下,当服务端断开会在接收消息的线程中触发sex.SocketErrorCode == SocketError.ConnectionReset的异常,此时捕获到后开启重连定时器即可

/// <summary>
/// 接收消息
/// </summary>
private static void thdRevMethod()
{
try
{
while (true)
{
byte[] resByte = new byte[];
int resInt = socketClient.Receive(resByte);
if (resInt > )
{
Console.WriteLine(Encoding.Default.GetString(resByte,, resInt));
}
} }
catch (SocketException sex)
{
if (sex.SocketErrorCode == SocketError.ConnectionReset)
{
Console.WriteLine("服务端断开!5s后重连!");
reconnectTimer.Start();
heartbeatTimer.Stop();
}
}
catch (Exception ex)
{
Console.WriteLine("程序出现异常:" + ex);
heartbeatTimer.Stop();
}
} //发送信息
private static void thdSendMethod()
{
try
{
while (true)
{
string res = Console.ReadLine();
byte[] resByte = Encoding.Default.GetBytes(res);
socketClient.Send(resByte);
}
}
catch (Exception ex)
{
Console.WriteLine("程序出现异常:" + ex);
heartbeatTimer.Stop();
}
}

三.运行示例

四..总结

假如代码中有错误的地方,希望可以帮忙指出来改之。

其中要注意的地方如下:
1.WPF关闭窗口后,需要通过 Environment.Exit(0);来结束掉当前整个服务端进程,否则Socket开启的接收和发送进程将还在,客户端也不会检测到服务端断开。

2.在SocketException中捕获异常sex.SocketErrorCode == SocketError.ConnectionReset时说明客户端/服务端连接断开了,需要进行重连等操作。

3.在接收到消息时候需要用GetString(byte[] bytes, int index, int count)指定长度,而不该使用GetString(byte[] bytes),否则可能出现很多空格。

4.定时器假如需要传递参数,可以通过设置全局变量,或者(s, e) => heartbeatTimerIsUp(s, e, _socket)单独传递一个变量到方法中。

源码下载地址如下:SocketDemo.rar

C#之Socket通信的更多相关文章

  1. 我看不下去鸟。。。。Java和C#的socket通信真的简单吗?

    这几天在博客园上看到好几个写Java和C#的socket通信的帖子.但是都为指出其中关键点. C# socket通信组件有很多,在vs 使用nuget搜索socket组件有很多类似的.本人使用的是自己 ...

  2. php简单实现socket通信

    socket通信的原理在这里就不说了,它的用途还是比较广泛的,我们可以使用socket来做一个API接口出来,也可以使用socket来实现两个程序之间的通信,我们来研究一下在php里面如何实现sock ...

  3. Socket通信类

    package com.imooc; import java.io.BufferedReader; import java.io.IOException; import java.io.InputSt ...

  4. AgileEAS.NET SOA 中间件平台.Net Socket通信框架-介绍

    一.前言 AgileEAS.NET SOA 中间件平台是一款基于基于敏捷并行开发思想和Microsoft .Net构件(组件)开发技术而构建的一个快速开发应用平台.用于帮助中小型软件企业建立一条适合市 ...

  5. socket通信

    socket通信 一:socket基于Tcp连接,数据传输有保证 二:socket连接的建立过程: 1:服务器监听 2:客户端发出请求 3:建立连接 4:通信 三:一个简单的例子:服务器端每隔一段时间 ...

  6. Android之Socket通信、List加载更多、Spinner下拉列表

    Android与服务器的通信方式主要有两种,一是Http通信,一是Socket通信.两者的最大差异在于,http连接使用的是“请求—响应方式”,即在请求时建立连接通道,当客户端向服务器发送请求后,服务 ...

  7. .NET开源高性能Socket通信中间件Helios介绍及演示

    一:Helios是什么 Helios是一套高性能的Socket通信中间件,使用C#编写.Helios的开发受到Netty的启发,使用非阻塞的事件驱动模型架构来实现高并发高吞吐量.Helios为我们大大 ...

  8. iOS开发之Socket通信实战--Request请求数据包编码模块

    实际上在iOS很多应用开发中,大部分用的网络通信都是http/https协议,除非有特殊的需求会用到Socket网络协议进行网络数 据传输,这时候在iOS客户端就需要很好的第三方CocoaAsyncS ...

  9. AgileEAS.NET SOA 中间件平台.Net Socket通信框架-简单例子-实现简单的服务端客户端消息应答

    一.AgileEAS.NET SOA中间件Socket/Tcp框架介绍 在文章AgileEAS.NET SOA 中间件平台Socket/Tcp通信框架介绍一文之中我们对AgileEAS.NET SOA ...

  10. AgileEAS.NET SOA 中间件平台.Net Socket通信框架-完整应用例子-在线聊天室系统-下载配置

    一.AgileEAS.NET SOA中间件Socket/Tcp框架介绍 在文章AgileEAS.NET SOA 中间件平台Socket/Tcp通信框架介绍一文之中我们对AgileEAS.NET SOA ...

随机推荐

  1. js如何开发游戏(聊天篇)

    公司最近有这方面的需求,期望我们能搞出点有趣的小游戏来帮助公司进行推广,公司没有专门做游戏开发的员工,很不幸这件事情掉到了前端头上. 我记得我以前在学习的时候曾经见过一些厉害的前端工程师编写过一些网页 ...

  2. 学习ASP.NET Core Razor 编程系列一

    一. 概述 .NET Core 1.0发布的时候就想进行学习的,不过根据微软的以往的发布规律1.0版可以认为是大众测试版,2.0才算稳定.现在2.1都已经发布了预览版,之前对其"不稳定&qu ...

  3. Scala编程快速入门系列(二)

    目    录 一.Scala概述 二.Scala数据类型 三.Scala函数 四.Scala集合 五.Scala伴生对象 六.Scala trait 七.Actor 八.隐式转换与隐式参数 九.Sca ...

  4. jQuary学习の一の初期准备

    jQuery 的功能概括: 1.html 的元素选取 2.html的元素操作 3.html dom遍历和修改 4.js特效和动画效果 5.css操作 6.html事件操作 7.ajax异步请求方式 通 ...

  5. Lintcode227 Mock Hanoi Tower by Stacks solution 题解

    [题目描述] In the classic problem of Towers of Hanoi, you have 3 towers and N disks of different sizes w ...

  6. jmockito模拟方法中参数如何指定

    在做单元测试的时候,经常会遇到mock类的方法的情景.在写单测过程中,遇到一些问题,比较困惑,便做了一些测试,并得出一个结论: 在mock类的方法时,当符合 (mock参数).equals(实际调用过 ...

  7. 轮评审用例,写用例的重要性-----(python单元测试反思)

    时间过的真快,3月底了,更新一次博客吧,算是对三月份忙碌的一个总结. 吃过饭,习惯登录qq,看到我群里的一个大神,碎冰发的一个作业 不就是写个代码吗,然后写完再进行测试这个代码是否实现了这个功能. 于 ...

  8. 使用kafka connect,将数据批量写到hdfs完整过程

    版权声明:本文为博主原创文章,未经博主允许不得转载 本文是基于hadoop 2.7.1,以及kafka 0.11.0.0.kafka-connect是以单节点模式运行,即standalone. 首先, ...

  9. c++ dynamic_cast 和 static_cast 的区别

    今天在看王道宝典的时候看到dynamic_cast ,一直都没用过,也不了解,今天来总结一下. dynamic_cast 和 static_cast 都可以用来强制转换指针类型,但不同的是dynami ...

  10. JAVAEE——BOS物流项目08:配置代理对象远程调用crm服务、查看定区中包含的分区、查看定区关联的客户

    1 学习计划 1.定区关联客户 n 完善CRM服务中的客户查询方法 n 在BOS项目中配置代理对象远程调用crm服务 n 调整定区关联客户页面 n 实现定区关联客户 2.查看定区中包含的分区 n 页面 ...