C# Sockets实现服务器与多个客户端进行通讯
程序员文章站
2022-05-19 14:09:19
...
学习一个新的东西,首先要知道其原理,对于Sockets的学习,可先看一下文档:
http://blog.csdn.net/hulihui/article/details/3230503#st 点击打开链接 PS: /*附有源码*/
刚开始是写代码实现了一个客户端和服务器的通讯,后来完善代码,实现了多个客户端与服务器端的通讯,由于原理是差不多的,这里就直接介绍多个客户端与服务器进行通讯。
第一部分 窗体设计
1.服务器端
2.客户端
第二部分 代码
1.服务器端:
– 申请一个socket (socketWatch)用来监听的
– 绑定到一个IP地址和一个端口上
– 开启侦听,等待接授客户端的连接
– 当有连接时创建一个用于和连接进来的客户端进行通信的socket(socketConnection)
– 即续监听,等侍下一个客户的连接
//服务器端
using System.IO;
using System.Net;
using System.Threading;
using System.Net.Sockets;
namespace SocketsServer
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Socket socketWatch = null;
Thread threadWatch = null;
private void startconn_Click(object sender, EventArgs e)
{
socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ipaddress = IPAddress.Parse(localip.Text.Trim());
IPEndPoint endpoint = new IPEndPoint(ipaddress, int.Parse(porttext.Text.Trim()));
socketWatch.Bind(endpoint);
socketWatch.Listen(10);
threadWatch = new Thread(WatchingConn);
threadWatch.IsBackground = true;
threadWatch.Start();
this.Invoke(new Action(() =>
{
recmsg.AppendText("开始对客户端进行监听!" + "\r\n");
}
));
}
//保存了服务器端所有负责和客户端通信发套接字
Dictionary<string, Socket> dictSocket = new Dictionary<string, Socket>();
//保存了服务器端所有负责调用通信套接字.Receive方法的线程
Dictionary<string, Thread> dictThread = new Dictionary<string, Thread>();
//Socket socConn = null;
private void WatchingConn(object obj)
{
while (true)
{
Socket socConn = socketWatch.Accept();
this.Invoke(new Action(() => {
//向下拉项中添加一个客户端的ip端口字符串,作为客户端的唯一标识
iptext.Items.Add(socConn.RemoteEndPoint.ToString());
}));
////将与客户端通信的套接字对象sokConn添加到键值对集合中,并以客户端IP端口作为键
dictSocket.Add(socConn.RemoteEndPoint.ToString(), socConn);
ParameterizedThreadStart pts = new ParameterizedThreadStart(RecMsg);
Thread trd = new Thread(pts);
trd.IsBackground = true;
trd.Start(socConn);
dictThread.Add(socConn.RemoteEndPoint.ToString(), trd);
this.Invoke(new Action(()=>
{
recmsg.AppendText("客户端连接成功!" + "\r\n");
}
));
}
}
private void RecMsg(object socketClientPara)
{
Socket socketRec = socketClientPara as Socket;
while (true)
{
byte[] arrRecMsg = new byte[1024 * 1024];
//int length = socketClient.Receive(arrRecMsg);//......wrong......
int length = -1;
try
{
length = socketRec.Receive(arrRecMsg);
}
catch (SocketException ex)
{
MessageBox.Show("异常:" + ex.Message);
//从通信套接字集合中删除被中断连接的通信套接字对象
dictSocket.Remove(socketRec.RemoteEndPoint.ToString());
//从通信线程结合中删除被终端连接的通信线程对象
dictThread.Remove(socketRec.RemoteEndPoint.ToString());
//从列表中移除被中断的连接 ip:Port
iptext.Items.Remove(socketRec.RemoteEndPoint.ToString());
break;
}
catch (Exception ex)
{
MessageBox.Show("异常:" + ex.Message);
break;
}
string str = Encoding.UTF8.GetString(arrRecMsg, 0, length);
this.Invoke(new Action(() => {
recmsg.AppendText(iptext.Text + ":\r\n" + GetTime() + "\r\n" + str + "\r\n");
}));
Thread.Sleep(10);
}
}
private DateTime GetTime()
{
DateTime getTime = new DateTime();
getTime = DateTime.Now;
return getTime;
}
private void SendMsg(string sendMsg)
{
if (string.IsNullOrEmpty(iptext.Text))
{
MessageBox.Show("请选择通信IP!");
}
else
{
byte[] strSendMsg = Encoding.UTF8.GetBytes(sendMsg);
string strClientKey = iptext.Text;//通过Key匹配对应ip地址的客户端
dictSocket[strClientKey].Send(strSendMsg);
this.Invoke(new Action(() =>
{
recmsg.AppendText("服务器:" + "\r\n" + GetTime() + "\r\n" + sendMsg + "\r\n");
}));
sendmsg.Text = null;
}
}
private void sendok_Click(object sender, EventArgs e)
{
SendMsg(sendmsg.Text.Trim());
}
}
}
2.客户端:
– 申请一个socket
– 连接服务器(指明IP地址和端口号)
//客户端
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace SocketsClient
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Socket socketWatch = null;
Thread threadWatch = null;
private void startconn_Click(object sender, EventArgs e)
{
socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress address = IPAddress.Parse(iptext.Text.Trim());
IPEndPoint endpoint = new IPEndPoint(address, int.Parse(porttext.Text.Trim()));
socketWatch.Connect(endpoint);
// socketWatch.Bind(endpoint);//...报错(服务器是Bind,客户端是Connect)...
threadWatch = new Thread(RecMsg);
threadWatch.IsBackground = true;
threadWatch.Start();
}
private void RecMsg(object obj)
{
while (true)
{
byte[] arrRecMsg = new byte[1024 * 1024];
int length = socketWatch.Receive(arrRecMsg);
string str = Encoding.UTF8.GetString(arrRecMsg, 0, length);
this.Invoke(new Action(() => {
recmsg.AppendText("服务器:" + "\r\n" + GetTime() + "\r\n" + str + "\r\n");
}));
}
}
private DateTime GetTime()
{
DateTime getTime = new DateTime();
getTime = DateTime.Now;
return getTime;
}
private void SendMsg(string sendMsg)
{
byte[] strSenMsg = Encoding.UTF8.GetBytes(sendMsg);
socketWatch.Send(strSenMsg);
this.Invoke(new Action(() =>
{
recmsg.AppendText("客户端:" + "\r\n" + GetTime() + "\r\n" + sendMsg + "\r\n");
}));
sendmsg.Text = null;
}
private void sendok_Click(object sender, EventArgs e)
{
SendMsg(sendmsg.Text.Trim());
}
}
}
下载路径:下载链接
————————————————
版权声明:本文为CSDN博主「勤劳的小码农」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u011602967/article/details/50728443
https://blog.csdn.net/u011602967/article/details/50728443
推荐阅读
-
C#使用Socket实现服务器与多个客户端通信(简单的聊天系统)
-
Java开发之使用websocket实现web客户端与服务器之间的实时通讯
-
C# ModBus Tcp读写数据 与服务器进行通讯
-
Android BLE与终端通信(四)——实现服务器与客户端即时通讯功能
-
C#使用Socket实现服务器与多个客户端通信(简单的聊天系统)
-
linux c IO多路复用之select函数模型,构建C/S来实现服务器与客户端之间进行通信
-
Java Socket 使用多线程实现服务器与多个客户端通信
-
C# Sockets实现服务器与多个客户端进行通讯
-
Java开发之使用websocket实现web客户端与服务器之间的实时通讯
-
Java多线程与线程池实现Socket多个客户端连接服务器同时通信代码