创建一个socket服务类,绑定监听端口,

然后创建一个线程listen连接的客户端,

把监听到的客户端加入dictionary里面,以便于管理,

同时创建receive线程,循环接收数据加入list缓存区,解决粘包或者分包的情况,

关闭服务时,需要将连接上的socket逐个shutdown。

/*
*
* 该类用于管理tcp连接通讯
*
*/ using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Threading;
using System.Net; namespace Communication
{
/// <summary>
/// 服务端
/// </summary>
public class MyTcpServer
{ private Socket ServerSocket = null;//服务端
public Dictionary<string, MySession> dic_ClientSocket = new Dictionary<string, MySession>();//tcp客户端字典
private Dictionary<string, Thread> dic_ClientThread = new Dictionary<string, Thread>();//线程字典,每新增一个连接就添加一条线程
private bool Flag_Listen = true;//监听客户端连接的标志 /// <summary>
/// 启动服务
/// </summary>
/// <param name="port">端口号</param>
public bool OpenServer(int port)
{
try
{
Flag_Listen = true;
// 创建负责监听的套接字,注意其中的参数;
ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// 创建包含ip和端口号的网络节点对象;
IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, port);
try
{
// 将负责监听的套接字绑定到唯一的ip和端口上;
ServerSocket.Bind(endPoint);
}
catch
{
return false;
}
// 设置监听队列的长度;
ServerSocket.Listen();
// 创建负责监听的线程;
Thread Thread_ServerListen = new Thread(ListenConnecting);
Thread_ServerListen.IsBackground = true;
Thread_ServerListen.Start(); return true;
}
catch
{
return false;
}
}
/// <summary>
/// 关闭服务
/// </summary>
public void CloseServer()
{
lock (dic_ClientSocket)
{
foreach (var item in dic_ClientSocket)
{
item.Value.Close();//关闭每一个连接
}
dic_ClientSocket.Clear();//清除字典
}
lock (dic_ClientThread)
{
foreach (var item in dic_ClientThread)
{
item.Value.Abort();//停止线程
}
dic_ClientThread.Clear();
}
Flag_Listen = false;
//ServerSocket.Shutdown(SocketShutdown.Both);//服务端不能主动关闭连接,需要把监听到的连接逐个关闭
if (ServerSocket != null)
ServerSocket.Close(); }
/// <summary>
/// 监听客户端请求的方法;
/// </summary>
private void ListenConnecting()
{
while (Flag_Listen) // 持续不断的监听客户端的连接请求;
{
try
{
Socket sokConnection = ServerSocket.Accept(); // 一旦监听到一个客户端的请求,就返回一个与该客户端通信的 套接字;
// 将与客户端连接的 套接字 对象添加到集合中;
string str_EndPoint = sokConnection.RemoteEndPoint.ToString();
MySession myTcpClient = new MySession() { TcpSocket = sokConnection };
//创建线程接收数据
Thread th_ReceiveData = new Thread(ReceiveData);
th_ReceiveData.IsBackground = true;
th_ReceiveData.Start(myTcpClient);
//把线程及客户连接加入字典
dic_ClientThread.Add(str_EndPoint, th_ReceiveData);
dic_ClientSocket.Add(str_EndPoint, myTcpClient);
}
catch
{ }
Thread.Sleep();
}
}
/// <summary>
/// 接收数据
/// </summary>
/// <param name="sokConnectionparn"></param>
private void ReceiveData(object sokConnectionparn)
{
MySession tcpClient = sokConnectionparn as MySession;
Socket socketClient = tcpClient.TcpSocket;
bool Flag_Receive = true; while (Flag_Receive)
{
try
{
// 定义一个2M的缓存区;
byte[] arrMsgRec = new byte[ * * ];
// 将接受到的数据存入到输入 arrMsgRec中;
int length = -;
try
{
length = socketClient.Receive(arrMsgRec); // 接收数据,并返回数据的长度;
}
catch
{
Flag_Receive = false;
// 从通信线程集合中删除被中断连接的通信线程对象;
string keystr = socketClient.RemoteEndPoint.ToString();
dic_ClientSocket.Remove(keystr);//删除客户端字典中该socket
dic_ClientThread[keystr].Abort();//关闭线程
dic_ClientThread.Remove(keystr);//删除字典中该线程 tcpClient = null;
socketClient = null;
break;
}
byte[] buf = new byte[length];
Array.Copy(arrMsgRec, buf, length);
lock (tcpClient.m_Buffer)
{
tcpClient.AddQueue(buf);
}
}
catch
{ }
Thread.Sleep();
}
}
/// <summary>
/// 发送数据给指定的客户端
/// </summary>
/// <param name="_endPoint">客户端套接字</param>
/// <param name="_buf">发送的数组</param>
/// <returns></returns>
public bool SendData(string _endPoint, byte[] _buf)
{
MySession myT = new MySession();
if (dic_ClientSocket.TryGetValue(_endPoint, out myT))
{
myT.Send(_buf);
return true;
}
else
{
return false;
}
}
} /// <summary>
/// 会话端
/// </summary>
public class MySession
{
public Socket TcpSocket;//socket对象
public List<byte> m_Buffer = new List<byte>();//数据缓存区 public MySession()
{ } /// <summary>
/// 发送数据
/// </summary>
/// <param name="buf"></param>
public void Send(byte[] buf)
{
if (buf != null)
{
TcpSocket.Send(buf);
}
}
/// <summary>
/// 获取连接的ip
/// </summary>
/// <returns></returns>
public string GetIp()
{
IPEndPoint clientipe = (IPEndPoint)TcpSocket.RemoteEndPoint;
string _ip = clientipe.Address.ToString();
return _ip;
}
/// <summary>
/// 关闭连接
/// </summary>
public void Close()
{
TcpSocket.Shutdown(SocketShutdown.Both);
}
/// <summary>
/// 提取正确数据包
/// </summary>
public byte[] GetBuffer(int startIndex, int size)
{
byte[] buf = new byte[size];
m_Buffer.CopyTo(startIndex, buf, , size);
m_Buffer.RemoveRange(, startIndex + size);
return buf;
} /// <summary>
/// 添加队列数据
/// </summary>
/// <param name="buffer"></param>
public void AddQueue(byte[] buffer)
{
m_Buffer.AddRange(buffer);
}
/// <summary>
/// 清除缓存
/// </summary>
public void ClearQueue()
{
m_Buffer.Clear();
}
}
}

the end

c#Socket Tcp服务端编程的更多相关文章

  1. Java网络编程(TCP服务端)

    /* * TCP服务端: * 1.创建服务端socket服务,并监听一个端口 * 2.服务端为了给客户端提供服务,获取客户端的内容,可以通过accept方法获取连接过来的客户端对象 * 3.可以通过获 ...

  2. python网络编程:socket、服务端、客户端

    本文内容: socket介绍 TCP: 服务端 客户端 UDP: 服务端 客户端 首发时间:2018-02-08 01:14 修改: 2018-03-20 :重置了布局,增加了UDP 什么是socke ...

  3. tcp服务端socket

    import socket if __name__ == '__main__': # 创建tcp服务端socket tcp_server_socket = socket.socket(socket.A ...

  4. python编程系列---tcp服务端的简单实现

    流程如下: """tcp服务端创建流程1. 创建服务端的tcp socket : server_socket 用于监听客户端的请求2. 绑定端口3. server_soc ...

  5. python网络编程-TCP服务端的开发

    #TCP服务端开发 2 #方法说明 3 """ 4 bind(host,port)表示绑定端口号,host是ip地址,ip地址一般不进 行绑定,表示本机的任何一个ip地址 ...

  6. 《Linux多线程服务端编程:使用muduo C++网络库》上市半年重印两次,总印数达到了9000册

    <Linux多线程服务端编程:使用muduo C++网络库>这本书自今年一月上市以来,半年之内已经重印两次(加上首印,一共是三次印刷),总印数达到了9000册,这在技术书里已经算是相当不错 ...

  7. 基于Select模型的Windows TCP服务端和客户端程序示例

    最近跟着刘远东老师的<C++百万并发网络通信引擎架构与实现(服务端.客户端.跨平台)>,Bilibili视频地址为C++百万并发网络通信引擎架构与实现(服务端.客户端.跨平台),重新复习下 ...

  8. C++封装的基于WinSock2的TCP服务端、客户端

    无聊研究Winsock套接字编程,用原生的C语言接口写出来的代码看着难受,于是自己简单用C++封装一下,把思路过程理清,方便自己后续翻看和新手学习. 只写好了TCP通信服务端,有空把客户端流程也封装一 ...

  9. 利用select实现IO多路复用TCP服务端

    一.相关函数 1.  int select(int maxfdp, fd_set *readset, fd_set *writeset, fd_set *exceptset,struct timeva ...

随机推荐

  1. 关于使用format()方法格式化字符串,读这一篇就够了!

    从Python 2.6开始,又出现了另外一种格式化字符串的方法——format()方法.format()方法是字符串众多方法中的一个,调用这个方法时要使用点操作符(.),该方法返回一个格式化好的字符串 ...

  2. python 操作excel

    操作excel安装的三种方式: 1.pip instaill xlwt    #写excel   pip instaill  xlrd    #读excel      pip instaill  xl ...

  3. Tomcat修改service.xml性能调优 增加最大并发连接数

    详细配置: <Connector executor="tomcatThreadPool"               port="80" protocol ...

  4. LTS本地搭建详述

    由于工作项目中使用LTS作为消息队列,这几天有空正好研究一下. 1. 先去GitHub上下载源码:https://github.com/ltsopensource/light-task-schedul ...

  5. Oracle两个数据库联合查询,使用Oracle DBLink

    创建dblink -- Create database link create shared database link COPYCITY_BZTOMY connect to db_A identif ...

  6. DLC 数制与数制的转换

    进位计数值:用进位的方法进行计数 常用数值有十进制.二进制.八进制.十六进制等. 进位计数制把包括基数与权两个基本问题.

  7. [持续交付实践] Jenkins 中国用户大会参会见闻

    前言 上周日在上海召开了Jenkins中国用户大会(Jenkins User Confluence China),这应该是Jenkins在中国第一次举办吧.Jenkins的创始人Kohsuke Kaw ...

  8. mySQL的表操作

    1.新建表 CREATE TABLE 表名 ( 属性名 数据类型 [完整约束条件], 属性名 数据类型 [完整约束条件], ... ... 属性名 数据类型 [完整约束条件] ); 2.删除表 DRO ...

  9. 三剑客之awkd的基本使用

    1.awk的使用 1.1 基本的awk执行过程 #passwd文件的第二行的第一列和第二列 [root@xiaojin oldboy]# awk -F ":" 'NR==2{pri ...

  10. Could not read document: Can not deserialize instance of java.lang.String out of START_ARRAY

    线上问题: { "timestamp": "1544510665", "status": 400, "error": & ...