.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. entityframework

    entityframework扩展: http://entityframework-plus.net/

  2. 码云以及git使用

    码云的使用方法以及git的连用 创建公钥的方法 打开码云,点击个人资料---->SSH公钥---->点击怎样生成公钥 SSH Keys ssh keys可以让你在你的电脑和Git@OSC知 ...

  3. 关于GridView中控件的问题

    最近做项目报表时,会遇到在Gridview中有一些控件,报表中也会有更新.删除等一系列的操作,但往往会遇到一些控件取值取不到或者找不到控件得问题,通过网上查阅资料对其中的一些做一总结: 前台代码如下: ...

  4. 在firefox浏览器下,scrollTop始终为0的问题

    firefox下,带dtd文档申明: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" " ...

  5. Servlet技术(使用myeclipse)

    Servlet跟JavaBean本质上都是严格遵循规则的java包. Servlet基本结构: Public class Servlet 类名称 extends HttpServlet{     Pu ...

  6. jquery.extend

    经常在插件中看到jquery.extend 方法,最近在尝试写一些简单的插件,顺便研究一下这个方法. 原文:http://www.cnblogs.com/RascallySnake/archive/2 ...

  7. CPrimerPlus第11章第10题

    题目: 编写一个程序,读取输入,直到读入了10个字符串或遇到EOF,由二者中最先被满足的那个终止读取过程.这个程序可以为用户提供一个有5个选项的菜单:输出初始字符串列表.按ASCII顺序输出字符串.按 ...

  8. Div 定时移动

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http ...

  9. Maven之安装与简单入门一

    Maven 是一个项目管理和构建自动化工具,我们最关心的是它的项目构建功能.Maven 使用惯例优于配置的原则. 1,下载安装包,并根据文档说明安装: http://maven.apache.org/ ...

  10. unity的固定管线shader

    最近shader学习中,看的视频. 练习的固定管线的shader如下: ps.在unity5中半透明不好用,其他的还好 //不区分大小写 //这是固定管线的Shader Shader "Sh ...