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或者消息推送应用)时,总是不 ...
随机推荐
- SQLServer 2014 AlwaysOn
一.安装故障转移群集的准备 确保群集中的节点都已加入到域(本例中为2节点) 确保将域帐户添加到本机管理员组 二.安装故障转移群集(所有节点都需要安装该功能) 1)单击任务栏”服务器管理器”,打开服务器 ...
- C# 获取Url 请求方式 域名 端口 路径
Example there's an given url: http://localhost:4800/account/login 获取整个url地址: 在页面(cstml)中 Microsoft.A ...
- windows下MySQL的安装(非安装包)
命令代码 "C:\Program Files\MySQL\MySQL Server 5.6\bin\mysqld.exe" --install MySQL56_3308 --def ...
- dpdk EAL: Error reading from file descriptor 23: Input/output error
执行test程序时输出: EAL: Error reading from file descriptor 23: Input/output error 原因: 在虚拟机添加的网卡,dpdk不支持导致的 ...
- iOS 多Target, Other link Flag
在创建多个马甲包或者多个App间只有很小的差异是使用多Target是一种很好的方法 https://www.jianshu.com/p/18db54655246 1:选中原始的Target, 点击右键 ...
- jzoj5878
tj:這道題可以想到排列組合 對於第一問,我們知道,左轉的次數比右轉次數多4,所以答案是c(n,n/2-2) 對於第二問,我們發現,不能出現下凹的情況,所以不能同時出現2個左拐,且路徑可以分為4段,且 ...
- storm配置详解
storm的配置文件在${STORM_HOME}/conf/storm.yaml.下面详细说明storm的配置信息. java.libary.path:storm本身依赖包的路径,有多个路径的时候使用 ...
- node 无脑生成小程序二维码图
RT 新建createwxaqrcode.js: const request = require('request') const fs = require('fs') // eg:生成购物车列表圆形 ...
- J07-Java IO流总结七 《 InputStreamReader和OutputStreamWriter 》
前面在介绍FileReader和FileWriter的时候有说到,FileReader的读取字符功能,以及FileWriter的写出字符的功能,都不是它们自己实现的,而是,它们分别继承了InputSt ...
- Scala中使用implict 扩展现有类的方法
Scala中implict的一种用法就是扩展现有类的方法,有点类似于.Net中的扩展方法(MS对扩展方法的介绍:扩展方法使你能够向现有类型“添加”方法,而无需创建新的派生类型.重新编译或以其他方式修改 ...