.Net Socket通讯可以使用Socket类,也可以使用 TcpClient、 TcpListener 和 UdpClient类。我这里使用的是Socket类,Tcp协议。

  程序很简单,一个命令行的服务端,一个命令行的客户端。服务端启动后根据输入的端口号绑定本机端口并启动侦听,客户端启动后根据输入的客户端数量、服务IP、服务端口号连接服务端。客户端连接成功后启动新线程随机发送消息到服务端并等待接收服务端返回的消息,服务端和客户端成功创建连接后启动新线程接收客户端消息并返回客户端一个消息,如此循环下去……

  上图:

图1. 客户端运行界面

图2. 服务端运行界面

图3. 项目结构

  

  

服务端关键代码

  启动侦听:

 var endPoint = new IPEndPoint(, port);
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Bind(endPoint);
socket.Listen(int.MaxValue);

  启动新线程接收客户端连接:

 // 启动新线程负责接受客户端连接
var socketThread = new Thread(OnSocketAccept) {IsBackground = true};
socketThread.Start(socket);
Show("服务准备就绪");

  接收客户端连接细节:

 /// <summary>
/// 建立Socket连接
/// </summary>
/// <param name="obj"></param>
private static void OnSocketAccept(object obj)
{
try
{
var socket = obj as Socket;
while (true)
{
try
{
Socket clientSocket = socket.Accept();
...
// 尝试获取锁,超时则关闭当前连接并继续下次循环
if (!Monitor.TryEnter(ClientDictLock, LockTimeOut))
{
CloseSocket(socket, key);
continue;
}
try
{
// 当然连接已存在则先关闭再缓存新连接
if (ClientDict.ContainsKey(key))
{
CloseSocket(ClientDict[key], key);
ClientDict[key] = clientSocket;
}
else
{
ClientDict.Add(key, clientSocket);
}
}
finally
{
Monitor.Exit(ClientDictLock);
}
// 启动线程池线程执行接收和发送操作
ThreadPool.QueueUserWorkItem(OnSendOrReceive, clientSocket);
}
catch (ThreadAbortException)
{
throw;
}
catch (Exception exception)
{
...
}
}
}
catch (ThreadAbortException)
{
...
}
catch (Exception exception)
{
...
}
}

  发送/接收数据:

 /// <summary>
/// 接收/发送数据
/// </summary>
/// <param name="obj"></param>
private static void OnSendOrReceive(object obj)
{
try
{
var socket = obj as Socket;
...
while (true)
{
try
{
...
// 接收数据
var receiveLength = socket.Receive(receiveBuffer);
...
// 发送数据
var sendLength = socket.Send(sendBuffer);
...
}
catch (ThreadAbortException)
{
throw;
}
catch (SocketException exception)
{
CloseSocket(socket, key);
break;
}
catch (Exception exception)
{
...
}
}
}
catch (ThreadAbortException)
{
}
catch (Exception exception)
{
...
}
}

  关闭连接:

 /// <summary>
/// 关闭连接
/// </summary>
/// <param name="socket"></param>
/// <param name="key"></param>
private static void CloseSocket(Socket socket, IPEndPoint key)
{
socket.Shutdown(SocketShutdown.Both);
socket.Disconnect(true);
socket.Close();
socket.Dispose();
...
}

客户端关键代码

  连接服务端:

// 根据客户端数量建立Socket连接
for (int i = ; i <= clientNum; i++)
{
ConnetServer(address, port, i);
} /// <summary>
/// 建立Socket连接
/// </summary>
/// <param name="address"></param>
/// <param name="port"></param>
/// <param name="id"></param>
static void ConnetServer(IPAddress address, int port, int id)
{
try
{
var clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// 连接服务端
clientSocket.Connect(address, port);
...
// 启动线程池线程开始发送数据和接收数据
ThreadPool.QueueUserWorkItem(OnSendOrReceive, clientSocket);
}
catch (Exception exception)
{
...
}
}

  发送/接收数据、关闭连接代码同服务端一样。

  优先使用线程池线程,服务端接受客户端连接使用独立线程(socketThread)是考虑到可能需要手工停止该线程。

  使用 Monitor.TryEnter(ClientDictLock, LockTimeOut) 和 Monitor.Exit(ClientDictLock); 是考虑到 lock 可能形成死锁,使用lock需要注意。

  本人才疏学浅,欢迎大家批评指正!

源代码下载

  

闲来无事,写个基于TCP协议的Socket通讯Demo的更多相关文章

  1. 闲来无事,写个基于UDP协议的Socket通讯Demo

    项目一期已经做完,二期需求还没定稿,所以最近比较闲. 上一篇写的是TCP协议,今天写一下UDP协议.TCP是有连接协议,所以发送和接收消息前客户端和服务端需要建立连接:UDP是无连接协议,所以发送消息 ...

  2. 网络编程——基于TCP协议的Socket编程,基于UDP协议的Socket编程

    Socket编程 目前较为流行的网络编程模型是客户机/服务器通信模式 客户进程向服务器进程发出要求某种服务的请求,服务器进程响应该请求.如图所示,通常,一个服务器进程会同时为多个客户端进程服务,图中服 ...

  3. 基于TCP 协议的socket 简单通信

    DNS 服务器:域名解析 socket 套接字 : ​ socket 是处于应用层与传输层之间的抽象层,也是一组操作起来非常简单的接口(接受数据),此接口接受数据之后,交由操作系统 为什么存在 soc ...

  4. 基于TCP协议的socket套接字编程

    目录 一.什么是Scoket 二.套接字发展史及分类 2.1 基于文件类型的套接字家族 2.2 基于网络类型的套接字家族 三.套接字工作流程 3.1 服务端套接字函数 3.2 客户端套接字函数 3.3 ...

  5. Java:基于TCP协议网络socket编程(实现C/S通信)

    目录 一.前言:TCP原理简介 二.Socket编程通信 三.TCP服务器端(具体代码) 四.TCP客户端(具体代码) 五.通信效果演示 六."创意"机器人:价值一个亿的AI核心代 ...

  6. 基于TCP协议的网络通讯流程

    不多说了,先上个图: 从上面的图中可以看出来,基于TCP协议进行通讯可以大致分成以下几个阶段: 1. 首先是在服务器端, TCP Sever调用socket(), bind(), listen()完成 ...

  7. 基于TCP实现的Socket通讯详解

    Socket通信是基于TCP协议进行的传输层通信,是在应用和应用之间的通信,一般应用在即时通讯上. 建立连接 用Socket创建连接需要在客户端和服务端都使用socket套接字. Linux内存创建S ...

  8. 基于TCP协议的socket编程

    什么是socket Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口.在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面, ...

  9. 网络编程: 基于TCP协议的socket, 实现一对一, 一对多通信

    TCP协议  面向连接 可靠的 面向字节流形式的 tcp是基于链接的,必须先启动服务端,然后再启动客户端去链接服务端 TCP协议编码流程: 服务器端:                 客户端 实例化对 ...

随机推荐

  1. linux centos 6.5下安装nodejs

    1.将文件下载或拷贝至/usr/local/src目录下,可使用xshell工具上传文件 2.解压缩文件: tar xvf /usr/local/src/node-v6.9.2-linux-x64 3 ...

  2. YII 错误 SQLSTATE[HY000] [2002] No such file or directory

    在使用yii的yii\db\Connnection时发生错误 <?php namespace app\controllers; use yii\web\Controller; use yii\d ...

  3. JS打开新页面跳转

      有时候使用js进行页面跳转,想使用 a 标签中 target="_blank" 形式,跳转打开一个新的页面. 可以使用以下脚本,创建一个 a标签,然后模拟点击操作. 代码如下: ...

  4. js 控制文本只能输入数字

    代码如下: <input onkeypress="setNumber()"><script> function setNumber(){ var keyCo ...

  5. (原创)RecyclerView结合xUtils2.6实现滚动时不加载item,xUtils2.6的源码分析与改造

    我们知道xUtils中的bitmapUtils与listview相配合可以实现滚动时暂停加载 只需要一句话: listview.addOnScrollListener(new PauseOnScrol ...

  6. java中HttpServletRequest常用获取url、资源名等方法总结

    HttpServletRequest客户端获取请求,客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中.所以我们能够从对象中获取相应信息   端口 request.get ...

  7. 基础知识《十》unchecked异常和checked异常

    运行时异常在运行期间才能被检查出来,一般运行期异常不需要处理.也称为unchecked异常.Checked异常在编译时就能确定,Checked异常需要自己处理. checked 异常也就是我们经常遇到 ...

  8. a标签填充父容器

    body>div>a{Join} div{ width:150px; height:35px; } a{ display:block; line-height:35px; height:3 ...

  9. selenium测试框架篇,页面对象和元素对象的管理

    前期已经做好使用Jenkins做buildhttp://www.cnblogs.com/tobecrazy/p/4529399.html 做自动化框架,不可避免的就是对象库. 有一个好的对象库,可以让 ...

  10. VC++ : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall std::basic_string<wchar_t,struct std::char_traits<wchar_t>

    最近学习Google Breakpad,将其用在了自己的项目中,编译的版本为VS2010,没有什么问题.但是为了和之前的程序兼容,需要使用VS2008版本的程序,于是又编译了VS2008版本的代码,但 ...