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或者消息推送应用)时,总是不 ...
随机推荐
- HDU 1710Binary Tree Traversals(已知前序中序,求后序的二叉树遍历)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1710 解题思路:可以由先序和中序的性质得到 : 先序的第一个借点肯定是当前子树的根结点, 那么在 中序 ...
- Debian&&ubuntu系安装MegaCli
MegaCli这个命令可以用来监控raid状态.磁盘状况等,最近上了一批ubuntu系统跑openstack,问题是MegaCli在官网上只有rpm格式的包,没有deb的包,但是还是有办法解决的,rp ...
- ReentrantLock总体概括
一.锁的实现原理: JAVA concurrent包下面的锁是通过AbstractQueuedSynchronizer内的Node类下面的state属性来实现的,并且锁的可重入属性也是通过state实 ...
- POJ 2242
#include <iostream> #include <cmath> #include <iomanip> using namespace std; #defi ...
- django 高级
1.使用form: django的form提供了统一的结构化的后台验证机制,错误信息,也容易展现在前台界面上.由于python的面向对象,使得编写html也能够代码复用. a.多个field 综合验证 ...
- 基于Web实现网络拓扑图
想想好像好久没用写博客了! 由于最近想跳槽了(ps:尽管公司挽留,提出一些异与往常的挽留“制度”,But确实已经死心了) ,发现前一段时间一些做Hadoop,和Spark同事时常来请教网络拓扑图的有关 ...
- JavaScript中的异步操作
什么是异步操作? 异步模式并不难理解,比如任务A.B.C,执行A之后执行B,但是B是一个耗时的工作,所以,把B放在任务队列中,去执行C,然后B的一些I/O等返回结果之后,再去执行B,这就是异步操作. ...
- ubuntu编译安装ruby1.9.3,从p551降级到p484
在升级redmine的时候遇到ruby版本适配的问题.找了些资料. ruby安装包除了官方网站,可以参考 http://ftp.ruby-lang.org/pub/ruby/1.9/ 需要从1.9.3 ...
- 【Ubuntu】使用记录
Vim 设置自动折行 :set wrap Maven 安装 去官网下载maven安装包 解压maven, 在主目录下的.bashrc中添加 export PATH="$PATH:{your_ ...
- sql子查询在insert、update、delete中的应用
子查询可以应用在INSERT.UPDATE以及DELETE等语句中,合理的使用子查询将能够简化功能的实现并且极大的提高SQL语句执行的效率 用到的表: CREATE TABLE `t_readerfa ...