闲来无事,写个基于TCP协议的Socket通讯Demo
.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的更多相关文章
- 闲来无事,写个基于UDP协议的Socket通讯Demo
项目一期已经做完,二期需求还没定稿,所以最近比较闲. 上一篇写的是TCP协议,今天写一下UDP协议.TCP是有连接协议,所以发送和接收消息前客户端和服务端需要建立连接:UDP是无连接协议,所以发送消息 ...
- 网络编程——基于TCP协议的Socket编程,基于UDP协议的Socket编程
Socket编程 目前较为流行的网络编程模型是客户机/服务器通信模式 客户进程向服务器进程发出要求某种服务的请求,服务器进程响应该请求.如图所示,通常,一个服务器进程会同时为多个客户端进程服务,图中服 ...
- 基于TCP 协议的socket 简单通信
DNS 服务器:域名解析 socket 套接字 : socket 是处于应用层与传输层之间的抽象层,也是一组操作起来非常简单的接口(接受数据),此接口接受数据之后,交由操作系统 为什么存在 soc ...
- 基于TCP协议的socket套接字编程
目录 一.什么是Scoket 二.套接字发展史及分类 2.1 基于文件类型的套接字家族 2.2 基于网络类型的套接字家族 三.套接字工作流程 3.1 服务端套接字函数 3.2 客户端套接字函数 3.3 ...
- Java:基于TCP协议网络socket编程(实现C/S通信)
目录 一.前言:TCP原理简介 二.Socket编程通信 三.TCP服务器端(具体代码) 四.TCP客户端(具体代码) 五.通信效果演示 六."创意"机器人:价值一个亿的AI核心代 ...
- 基于TCP协议的网络通讯流程
不多说了,先上个图: 从上面的图中可以看出来,基于TCP协议进行通讯可以大致分成以下几个阶段: 1. 首先是在服务器端, TCP Sever调用socket(), bind(), listen()完成 ...
- 基于TCP实现的Socket通讯详解
Socket通信是基于TCP协议进行的传输层通信,是在应用和应用之间的通信,一般应用在即时通讯上. 建立连接 用Socket创建连接需要在客户端和服务端都使用socket套接字. Linux内存创建S ...
- 基于TCP协议的socket编程
什么是socket Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口.在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面, ...
- 网络编程: 基于TCP协议的socket, 实现一对一, 一对多通信
TCP协议 面向连接 可靠的 面向字节流形式的 tcp是基于链接的,必须先启动服务端,然后再启动客户端去链接服务端 TCP协议编码流程: 服务器端: 客户端 实例化对 ...
随机推荐
- Spark 官方文档(4)——Configuration配置
Spark可以通过三种方式配置系统: 通过SparkConf对象, 或者Java系统属性配置Spark的应用参数 通过每个节点上的conf/spark-env.sh脚本为每台机器配置环境变量 通过lo ...
- 编程轶事-java中的null-遁地龙卷风
1.null是个奇妙的东西,可以理解为对象占位符 User user = null; System.out.println(user.getCredits()); 可以通过编译, User user; ...
- MarkdownPad2.5 注册码
邮箱: Soar360@live.com 授权秘钥: GBPduHjWfJU1mZqcPM3BikjYKF6xKhlKIys3i1MU2eJHqWGImDHzWdD6xhMNLGVpbP2M5SN6b ...
- c++中的继承与初始化
1.在c++中构造函数.析构函数.=运算符.友元无法继承 2.const 成员.引用成员.类的对象成员没有默认构造函数时,需在类的构造函数初始化列表中对其进行初始化 3.基类无默认构造函数,派生类需在 ...
- java后台对前端输入的特殊字符进行转义
转自:http://www.cnblogs.com/yangzhilong/p/5667165.html java后台对前端输入的特殊字符进行转义 HTML: 常见的帮助类有2个:一个是spring的 ...
- 高性能MySQL(一):基本数据类型
更多交流及资料,请加群 :
- RSA非对称性前端加密后端解密
前端加密代码 <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> ...
- Python全栈开发【基础四】
Python全栈开发[基础四] 本节内容: 匿名函数(lambda) 函数式编程(map,filter,reduce) 文件处理 迭代器 三元表达式 列表解析与生成器表达式 生成器 匿名函数 lamb ...
- ACM/ICPC 之 机器调度-匈牙利算法解最小点覆盖集(DFS)(POJ1325)
//匈牙利算法-DFS //求最小点覆盖集 == 求最大匹配 //Time:0Ms Memory:208K #include<iostream> #include<cstring&g ...
- 配置VMware虚拟机用绕过校园网达到无线上网配置方法
因为平时要用到Vmware这样的工具上虚拟机上网, 但是本人是学生狗,学生狗在学校就要面对大学毒瘤软件--锐捷,而锐捷是不允许有虚拟网卡的存在的,所以上网只能用wifi上.之前试了很久,反正是怎么开都 ...