Winfrom 基于TCP的Socket服务端 多线程(进阶版)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using YQ.BLL;
using YQ.Commons;
using YQ.Models;
using System.Configuration; namespace WindowsFormsApplication1
{
public partial class FormMain : Form
{
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;//监听客户端连接的标志 public FormMain()
{
InitializeComponent();
//System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;//设置该属性 为false
} private void Form1_Load(object sender, EventArgs e)
{
try
{
//this.txtPort.Text = "6666";
//this.txtSend.Text = "服务端发送"; }
catch { }
} private void btnStart_Click(object sender, EventArgs e)
{
try
{
if (this.btnStart.Text == "启动服务")
{ this.btnStart.Text = "停止服务"; OpenServer(Int32.Parse(this.txtPort.Text.Trim()));
}
else
{
this.btnStart.Text = "启动服务"; CloseServer(); }
}
catch (Exception ex)
{
CloseServer();
}
} private void btnSend_Click(object sender, EventArgs e)
{
try
{
if (dic_ClientSocket.Count <= )
{
this.lblState.Text = "没有客户端连接";
}
else
{
foreach (var item in dic_ClientSocket)
{
string sendMessage = this.txtSend.Text.Trim();
byte[] message = System.Text.Encoding.UTF8.GetBytes(sendMessage);
SendData(item.Key, message);
}
this.lblState.Text = "已发送客户端";
} }
catch { }
} /// <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); // 接收数据,并返回数据的长度;
if (length != -)
{
#region 处理接收数据
string receiveMsg = System.Text.Encoding.UTF8.GetString(arrMsgRec, , length); //this.txtReceive.Text = "客户端" + socketClient.RemoteEndPoint.ToString()
// + "\r\n" + "接收" + receiveMsg;
//this.txtReceive.SelectionLength = txtReceive.Text.Length;
//this.txtReceive.ScrollToCaret(); //入库操作代码 #endregion
} }
catch(Exception ex)
{
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();
}
} }
Winfrom 基于TCP的Socket服务端 多线程(进阶版)的更多相关文章
- Winfrom 基于TCP的Socket 编程
基于TCP的Socket基础例子 服务端的代码 public partial class Form1 : Form { public Form1() { InitializeComponent(); ...
- 基于netty的socket服务端触发了channelInactive方法,但实际连接没有断开的问题
背景: 一个中小型H5游戏,后端使用基于 netty 的socket服务 服务端 分为 分发服务器 & 业务服务器,业务服务器可负载 用户客户端与分发服务器连接 分发服务器再作为客户端与每台业 ...
- Python进阶(1)_Socket网络编程(基于tcp的socket)
网络协议参考:http://www.cnblogs.com/hedeyong/p/6889774.html 一.TCP/IP五层模型 学习socket一定要先学习互联网协议: 1.首先:本节课程的目标 ...
- 基于TCP协议Socket通信
服务器线程处理类 package demo4; import java.io.*; import java.net.Socket; /** * 服务器线程处理类 * @ClassName Server ...
- 利用多线程使socket服务端可以与多个客户端同时通讯
利用多线程使socket服务端可以与多个客户端同时通讯 server import socket 1. 符合TCP协议的手机 server = socket.socket(socket.AF_INET ...
- Python网络编程基础 ❷ 基于upd的socket服务 TCP黏包现象
TCP的长连接 基于upd的socket服务 TCP黏包现象
- Java Web 基础(一) 基于TCP的Socket网络编程
一.Socket简单介绍 Socket通信作为Java网络通讯的基础内容,集中了异常.I/O流模式等众多知识点.学习Socket通信,既能够了解真正的网络通讯原理,也能够增强对I/O流模式的理解. 1 ...
- AutoCAD.net支持后台线程-Socket服务端
最近因为公司项目的需求,CAD作为服务端在服务器中常驻运行,等待客户端远程发送执行任务的指令,最终确认用Socket-tcp通讯,CAD需要实时监听客户端发送的消息,这时就需要开启线程执行Socket ...
- 网络编程懒人入门(八):手把手教你写基于TCP的Socket长连接
本文原作者:“水晶虾饺”,原文由“玉刚说”写作平台提供写作赞助,原文版权归“玉刚说”微信公众号所有,即时通讯网收录时有改动. 1.引言 好多小白初次接触即时通讯(比如:IM或者消息推送应用)时,总是不 ...
随机推荐
- JAVA 从头开始<二>
一.JAVA_HOME 1.环境变量如果经常变更,就要经常操作到Path,可能会一不小心把什么东西给删了 2.最好新建一个环境变量 3.如果使用新环境变量 ①原来的写法 ②现在的写法 新建环境变量JA ...
- 基于Easyui框架的datagrid绑定数据,新增,修改,删除方法(四)
@{ ViewBag.Title = "xxlist"; } <script type="text/javascript" language=" ...
- SSE sqrt还是比C math库的sqrtf快了不少
#include <stdio.h> #include <xmmintrin.h> #define NOMINMAX #include <windows.h> #i ...
- MaxScript调用DotNet时命名空间的问题
Fn GetSpecialFolder argEnumName = (DotNetClass "System.Environment").GetFolderPath (Execut ...
- 在QT中用git做版本管理时遇到的一些问题
1. 安装git sudo apt-get install git 2. 安装gitk sudo apt-get install gitk 要提交代码,点击 工具->git->local ...
- docker 网络实践
#docker 网络模式 环境 centos7. , Docker version -ce docker自带网络类型 bridge,host,none,container,overlay,macvla ...
- Oracle性能问题sql调优脚本集
---------------------------------------------------------------------------------------------------- ...
- webpack初学者(1)
最近在学习webpack的总结,不完善的希望各位提出宝贵的建议.本篇是以webpack3.0版本为基础的学习总结. 一.webpack的概念及作用 wepack是一个模块打包兼优化工具.往往一个项目中 ...
- 字蛛fontSpider的使用
字蛛官方文档 http://font-spider.org/index.html 首先安装全局包 npm install font-spider -g 然后下载字体 ,本次需要的是 "造 ...
- node 利用http和cheerio编写简易爬虫
首先cnpm init创建一个package.json 引入cheerio模块 cnpm install --save cheerio 然后开始编写代码 let cheerio = require(' ...