C# Socket 线程
2023-09-14 09:02:11 时间
最初的版本是这样的:点击打开链接。但一直没有调好,所以就咨询了一下同事翔哥,最后初步搞定!
客户端代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
为什么kill进程后socket一直处于FIN_WAIT_1状态 本文介绍一个因为conntrack内核参数设置和iptables规则设置的原因导致TCP连接不能正常关闭(socket一直处于FIN_WAIT_1状态)的案例,并介绍conntrack相关代码在conntrack表项超时后对新报文的处理逻辑。
/* 实现功能:通过epoll, 处理多个socket * 监听一个端口,监听到有链接时,添加到epoll_event * xs #include #include #include #include
关于Socket 多线程 的一篇好文章 http://www.kegel.com/c10k.html#topIt s time for web servers to handle ten thousand clients simultaneously, don t you think? After all, the web is a big place now.
最初的版本是这样的:点击打开链接。但一直没有调好,所以就咨询了一下同事翔哥,最后初步搞定!
客户端代码:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Net.Sockets; using System.Threading; using System.Net; using System.Diagnostics; namespace SocketClient public partial class Client : Form Socket vsServerSocket; Thread vsClientThread; string strIP = "127.0.0.1"; public delegate void PassString(string strMsg); int nPort = 9001; public Client() InitializeComponent(); public void SetSendData(string strMsg) if (tBoxClientSend.InvokeRequired == true) PassString d = new PassString(SetSendData); this.Invoke(d, new object[] { strMsg }); else tBoxClientSend.Text = strMsg; public void SetRecvData(string strMsg) if (tBoxClientReceive.InvokeRequired == true) PassString d = new PassString(SetRecvData); this.Invoke(d, new object[] { strMsg }); else tBoxClientReceive.Text = strMsg; private void ClientHandle() string strRecv = string.Empty; //IPEndPoint其实就是一个IP地址和端口的绑定,可以代表一个服务,用来Socket通讯。 //IPAddress类中有一个 Parse()方法,可以把点分的十进制IP表示转化成IPAddress类 IPEndPoint ipep = new IPEndPoint(IPAddress.Parse(strIP), nPort); //创建套接字实例 //这里创建的时候用ProtocolType.Tcp,表示建立一个面向连接(TCP)的Socket vsServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //将所创建的套接字与IPEndPoint绑定 vsServerSocket.Bind(ipep); catch (SocketException ex) MessageBox.Show("Connect Error: " + ex.Message); return; Byte[] buffer = new Byte[1024]; //设置套接字为收听模式 vsServerSocket.Listen(10); //循环监听 while (true) //接收服务器信息 int bufLen = 0; Socket vsClientSocket = vsServerSocket.Accept(); bufLen=vsClientSocket.Receive(buffer); vsClientSocket.Send(Encoding.ASCII.GetBytes("aaaaa"), 5, SocketFlags.None); catch (Exception ex) MessageBox.Show("Receive Error:" + ex.Message); strRecv = Encoding.ASCII.GetString(buffer, 0, bufLen); SetRecvData(strRecv); //vsClientSocket.Shutdown(SocketShutdown.Both); //vsClientSocket.Close(); //发送数据 private void btnSend_Click(object sender, EventArgs e) byte[] data = new byte[1024]; string ss = tBoxClientSend.Text; Socket centerClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPEndPoint GsServer = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9002); centerClient.Connect(GsServer); centerClient.Send(Encoding.ASCII.GetBytes(ss)); centerClient.Close(); private void Client_Load(object sender, EventArgs e) //连接服务器 //通过ThreadStart委托告诉子线程讲执行什么方法 vsClientThread = new Thread(new ThreadStart(ClientHandle)); vsClientThread.Start(); //窗体关闭时杀死客户端进程 private void Client_FormClosing(object sender, FormClosingEventArgs e) KillProcess(); //杀死客户端进程 private void KillProcess() Process[] processes = Process.GetProcessesByName("SocketClient"); foreach (Process process in processes) process.Kill(); break; }服务端代码:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Threading; using System.Net.Sockets; using System.Net; using System.Diagnostics; namespace SocketServer public partial class Server : Form Thread vsServerThread; Socket vsServerSocket; string strIP = "127.0.0.1"; public delegate void PassString(string strMsg); int nPort = 9002; public Server() InitializeComponent(); private void SeverSendData(string strMsg) //Control.InvokeRequired 属性,命名空间: System.Windows.Forms //获取一个值,该值指示调用方在对控件进行方法调用时是否必须调用 Invoke 方法,因为调用方位于创建控件所在的线程以外的线程中。 if (tBoxServerSend.InvokeRequired == true) //Control.Invoke 方法 (Delegate) //在拥有此控件的基础窗口句柄的线程上执行指定的委托。 PassString d = new PassString(SeverSendData); this.Invoke(d, new object[] { strMsg }); else tBoxServerSend.Text = strMsg; private void SeverRecvData(string strMsg) if (tBoxServerReceive.InvokeRequired == true) PassString d = new PassString(SeverRecvData); this.Invoke(d, new object[] { strMsg }); else tBoxServerReceive.Text = strMsg; private void ServerStart() string strRecv = string.Empty; //创建IPEndPoint实例 IPEndPoint ipep = new IPEndPoint(IPAddress.Parse(strIP), nPort); //创建一个套接字 vsServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //将所创建的套接字与IPEndPoint绑定 vsServerSocket.Bind(ipep); catch (Exception ee) MessageBox.Show(ee.ToString()); return; //设置套接字为收听模式 vsServerSocket.Listen(10); int bufLen = 0; //循环监听 while (true) //在套接字上接收接入的连接 Socket vsClientSocket = vsServerSocket.Accept(); Byte[] buffer = new Byte[1024]; //在套接字上接收客户端发送的信息 bufLen = vsClientSocket.Receive(buffer); vsClientSocket.Send(Encoding.ASCII.GetBytes("aaaaa"), 5, SocketFlags.None); if (bufLen == 0) continue; //将指定字节数组中的一个字节序列解码为一个字符串。 strRecv = Encoding.ASCII.GetString(buffer, 0, bufLen); SeverRecvData(strRecv.ToString()); catch (Exception ex) MessageBox.Show("Listening Error: " + ex.Message); vsClientSocket.Close(); vsServerSocket.Close(); private void btnSend_Click(object sender, EventArgs e) byte[] data = new byte[1024]; string ss = tBoxServerSend.Text; Socket centerClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPEndPoint GsServer = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9001); centerClient.Connect(GsServer); centerClient.Send(Encoding.ASCII.GetBytes(ss)); centerClient.Send(Encoding.ASCII.GetBytes(ss)); //Thread.Sleep(100); //centerClient.Close(); private void Server_Load(object sender, EventArgs e) vsServerThread = new Thread(new ThreadStart(ServerStart)); vsServerThread.Start(); //窗体关闭时杀死客户端进程 private void Server_FormClosing(object sender, FormClosingEventArgs e) KillProcess(); //杀死客户端进程 private void KillProcess() Process[] processes = Process.GetProcessesByName("Server"); foreach (Process process in processes) process.Kill(); break; }
效果如下:
客户端可以发送消息给服务端,服务端也可以发送消息给客户端。
缺点:
现在服务端只能连接一个客户端
为什么kill进程后socket一直处于FIN_WAIT_1状态 本文介绍一个因为conntrack内核参数设置和iptables规则设置的原因导致TCP连接不能正常关闭(socket一直处于FIN_WAIT_1状态)的案例,并介绍conntrack相关代码在conntrack表项超时后对新报文的处理逻辑。
/* 实现功能:通过epoll, 处理多个socket * 监听一个端口,监听到有链接时,添加到epoll_event * xs #include #include #include #include
关于Socket 多线程 的一篇好文章 http://www.kegel.com/c10k.html#topIt s time for web servers to handle ten thousand clients simultaneously, don t you think? After all, the web is a big place now.
相关文章
- C#子线程中更新ui
- C#线程同步的几种方法
- C#中的线程(二) 线程同步基础
- Unity C#写的A*寻路
- C# winform 学习(三)
- C# Winform 学习(四)
- 重新整理数据结构与算法(c#)——算法套路迪杰斯特拉算法[三十一]
- c# semaphoreSlim限制线程数
- c# 线程的优先级
- 浅谈Attribute [C# | Attribute | DefaultValueAttribute]
- C#线程同步——lock,Monitor,Mutex(摘录)
- 重学c#系列——c# 托管和非托管资源与代码相关(四)
- c# Barrier 线程回调
- C# 获取xml数据,并转换为dataset
- 浅析C#深拷贝与浅拷贝
- C# - 多线程 之 进程与线程
- C#中Encoding.Unicode与Encoding.UTF8的区别
- C# Socket 线程
- 10年C#历程的MVP之路与MVP项目介绍
- Atitit.线程 死锁 跑飞 的检测与自动解除 与手动解除死锁 java c# .net php javascript.
- C# 线程同步
- C#使用线程池创建线程
- C# 线程安全的集合
- C#多线程实践-锁和线程安全
- C# 多线程与线程扫描器
- c# 并发与异步 二、变量 锁 前后台线程 优先级 信号