版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u012278016/article/details/90958251
客户端:
ClientControl.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ExampleNetCilent
{
public class ClientControl
{
private Socket clientSocket;
public ClientControl()
{
clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//创建客户端socket
}
public void connect(string ip, int port)
{
clientSocket.Connect(ip, port);//连接服务器
Console.WriteLine("连接服务器成功");
Thread threadReceive = new Thread(receive); //创建新线程接收消息
threadReceive.IsBackground = true; //该线程后台运行
threadReceive.Start(); //启动线程
}
//接收服务器端发来的消息
private void receive()
{
while(true)
{
try
{
byte[] msg = new byte[1024];
int msgLen = clientSocket.Receive(msg); //接收消息 字节数组 返回值为接收的字节长度
Console.WriteLine("服务器说: " + Encoding.UTF8.GetString(msg, 0, msgLen)); //转换字节为字符串输出
}
catch
{
Console.WriteLine("服务器积极拒绝");
break;
}
}
}
public void send()
{
Thread threadSend = new Thread(readAndSend); //创建新线程 发送消息
//threadSend.IsBackground = true; //取消后台执行 为了避免主线程关闭 子线程也关闭
threadSend.Start();
}
//读取用户输入并发送
private void readAndSend()
{
Console.WriteLine("请输入要发送的内容,输入quit退出");
string msg = Console.ReadLine();
while (msg != "quit")
{
clientSocket.Send(Encoding.UTF8.GetBytes(msg)); //发消息 Send函数 接受字节数组 msg 转字节数组 进行发送
msg = Console.ReadLine();
}
}
}
}
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace ExampleNetCilent
{
class Program
{
static void Main(string[] args)
{
ClientControl client = new ClientControl();
client.connect("127.0.0.1", 12321);//链接服务器
client.send(); //发送消息
Console.ReadKey();
}
}
}
服务器端:
ServerControl.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ExampleNetServer
{
public class ServerControl
{
private Socket serverSocket;
private List<Socket> clientList;
public ServerControl()
{
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//创建服务器端socket ipv4, 流式传输, tcp协议
clientList = new List<Socket>();
}
public void start()
{
serverSocket.Bind(new IPEndPoint(IPAddress.Any, 12321)); //绑定IP 及 端口 IPAddress.Any 表示程序运行在的机器IP地址 也可以为IPAddress.Parse("192.168.0.3")
serverSocket.Listen(10);// 监听 端口上 客户端的连接
Console.WriteLine("服务器启动成功");
Thread threadAccept = new Thread(accept);//创建一个接受客户端连接的线程 该线程机制可以接受多个客户端连接
threadAccept.IsBackground = true;//后台执行
threadAccept.Start();//启动线程
}
private void accept()
{
while(true)
{
//接受客户端连接,并返回socket, 该方法会阻塞挂起当前线程
Socket client = serverSocket.Accept();
IPEndPoint point = client.RemoteEndPoint as IPEndPoint; //远程连接过来IP 指客户端IP
Console.WriteLine(point.Address + "[" + point.Port + "]" + "连接成功");
clientList.Add(client);
Thread thradReceive = new Thread(receive);//开启一个新线程用于接收数据
thradReceive.IsBackground = true;
thradReceive.Start(client);
}
}
private void receive(Object obj)
{
while (true)
{
Socket client = obj as Socket;
IPEndPoint point = client.RemoteEndPoint as IPEndPoint;
try
{
byte[] msg = new byte[1024];//申请一块字节数组用于存放接收的数据
int msgLen = client.Receive(msg);//接收字节数组 返回接收的长度 该函数会阻塞所在的线程 所以放到新线程中
string msgStr = point.Address + "[" + point.Port + "] : " + Encoding.UTF8.GetString(msg, 0, msgLen); //转换字节数组成字符串 并输出
Console.WriteLine(msgStr);
//client.Send(Encoding.UTF8.GetBytes(Encoding.UTF8.GetString(msg, 0, msgLen) + ", 楼上说得对"));
broadcast(client, msgStr);
}
catch
{
Console.WriteLine(point.Address + "[" + point.Port + "]" + "积极断开");
clientList.Remove(client);
break;
}
}
}
private void broadcast(Socket clientOther, string msg)
{
foreach(var client in clientList)
{
if (client == clientOther)
{
//当前消息是由client发来的, 不需要有任何响应
}
else
{
client.Send(Encoding.UTF8.GetBytes(msg));
}
}
}
}
}
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ExampleNetServer
{
class Program
{
static void Main(string[] args)
{
ServerControl server = new ServerControl();
server.start();
Console.ReadKey();
}
}
}