目录
服务器端
可以连接多个客户端,接受客户端的文本信息,并对文本信息进行广播。
可以发送文本和文件给客户端,也是广播的新式发送,就是每个客户端都能收到就叫广播。
服务器中需要两个socket,一个是服务器,另一个是连接进来的客户端socket
因为要连接进来很多socket,所以把服务器中连接进来的客户端单独封装成一个类
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;
namespace TCP服务器端
{
class Client
{
private Socket clientSocket;
public Thread t;
private byte[] data = new byte[1024];//这个是一个数据容器
public string acceptmessage="";
public Client(Socket s)
{
clientSocket = s;
//启动一个线程 处理客户端的数据接收
t = new Thread(ReceiveMessage);
t.Start();
}
public void ReceiveMessage()
{
//一直接收客户端的数据
while (true)
{
try
{
//在接收数据之前 判断一下socket连接是否断开
int length = clientSocket.Receive(data);
if (length == 0)//客户端断开连接
{
break;
}
string message = Encoding.UTF8.GetString(data, 0, length);
message = clientSocket.RemoteEndPoint.ToString() + ":" + message ;
//接收到数据的时候 要把这个数据 分发到客户端
//广播这个消息
Form1.BroadcastMessage(message);
Form1.mainform.textBox3.AppendText(message + "\n");
}
catch { }
}
}
//服务器发送消息给客户端
public void SendMessage(string message)
{
byte[] data = Encoding.UTF8.GetBytes(message);
clientSocket.Send(data);
}
public bool Connected
{
get { return clientSocket.Connected; }
}
}
}
主窗口代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;
namespace TCP服务器端
{
public partial class Form1 : Form
{
static List<Client> clientList = new List<Client>(); //管理客户端套接字列表
Thread t;
Socket tcpServer;
public static Form1 mainform; //主窗口对象
public Form1()
{
//在窗口加载的时候取消线程的检查
Control.CheckForIllegalCrossThreadCalls = false;
InitializeComponent();
this.textBox1.Text = "192.168.6.21";
mainform = this;
}
//将收到的消息广播
public static void BroadcastMessage(string message)
{
var notConnectedList = new List<Client>();//存放断开的客户端
foreach (var client in clientList)
{
if (client.Connected)
client.SendMessage(message);//服务器向客户端发送消息
else//有断开的客户端就存放进列表
{
notConnectedList.Add(client);
}
}//将断开的客户端删掉
foreach (var temp in notConnectedList)
{
clientList.Remove(temp);
}
}
//打开服务器
private void button2_Click(object sender, EventArgs e)
{
tcpServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
tcpServer.Bind(new IPEndPoint(IPAddress.Parse(textBox1.Text), Convert.ToInt32(textBox2.Text)));
textBox3.AppendText("服务器打开成功\n");
tcpServer.Listen(100);
t = new Thread(checkconnect);//开启线程来监听客户端的连接
t.Start();
}
//发送消息按钮
private void button1_Click(object sender, EventArgs e)
{
BroadcastMessage("服务器:"+textBox4.Text);//将消息广播出去
if (clientList.Count == 0)
{
textBox3.AppendText("发送失败,无客户端连接");
}
else
{
textBox3.AppendText(textBox4.Text + "\n");
}
}
private void checkconnect()
{
try
{
while (true)
{
Socket clientSocket = tcpServer.Accept();
textBox3.AppendText("a client is connected !" + "\n");
Client client = new Client(clientSocket);//把与每个客户端通信的逻辑(收发消息)放到client类里面进行处理
clientList.Add(client);
}
}
catch
{ }
}
//关闭窗口,杀死所有线程
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
System.Diagnostics.Process.GetCurrentProcess().Kill();
}
//选择文件
private void button3_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.InitialDirectory = @"C:\Users\SpringRain\Desktop";
ofd.Title = "请选择要发送的文件";
ofd.Filter = "文本文件|*.txt|音乐文件|*.wav|图片文件|*.jpg|所有文件|*.*";
ofd.ShowDialog();
//获得选中文件的路径
string path = ofd.FileName;
textBox5.Text = path;
}
//发送文件按钮
private void button4_Click(object sender, EventArgs e)
{
using (FileStream fsRead = new FileStream(textBox5.Text, FileMode.Open, FileAccess.Read))
{
byte[] buffer = new byte[fsRead.Length];
//实际读取到的有效字节数
int r = fsRead.Read(buffer, 0, buffer.Length);
//在读取到的字节数组前加一个0作为发送的是文件的标志位
List<byte> list = new List<byte>();
list.Add(1);
list.AddRange(buffer);
byte[] newBuffer = list.ToArray();
//广播发送
//这里又转成了字符串,主要是因为广播函数的传入参数写死了
//建议单独写一个广播文件的函数,直接传入字节数组
string message = Encoding.UTF8.GetString(newBuffer, 0, r+1);
BroadcastMessage(message);
}
}
}
}
客户端
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;
namespace TCP客户端
{
public partial class Form1 : Form
{
public Socket tcpClient;
byte[] data = new byte[1024 * 1024 * 5];//5M大
public Form1()
{
//在窗口加载的时候取消线程的检查
Control.CheckForIllegalCrossThreadCalls = false;
InitializeComponent();
this.textBox1.Text = "192.168.6.21";
tcpClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
}
//连接
private void button1_Click(object sender, EventArgs e)
{
try
{
IPAddress ipaddress = IPAddress.Parse(textBox1.Text);//可以把一个字符串的ip地址转化成一个ipaddress的对象
EndPoint point = new IPEndPoint(ipaddress, Convert.ToInt32(textBox2.Text));
tcpClient.Connect(point);//通过ip:端口号 定位一个要连接到的服务器端
tcpClient.Send(Encoding.UTF8.GetBytes("客户端连接成功"));
textBox3.AppendText("连接成功");
Thread t = new Thread(ReceiveMessage);
t.Start();
}
catch
{}
}
//发送
private void button2_Click(object sender, EventArgs e)
{
//向服务器端发送消息
try
{
string message2 = textBox4.Text;
tcpClient.Send(Encoding.UTF8.GetBytes(message2));//把字符串转化成字节数组,然后发送到服务器端
}
catch
{}
}
private void ReceiveMessage()
{
try
{
//一直接收服务端的数据
while (true)
{
if (tcpClient.Connected == false)
{
break;
}
else
{
int length = tcpClient.Receive(data);
if (data[0] == 1)//接受文件
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.InitialDirectory = @"C:\Users\SpringRain\Desktop";
sfd.Filter = "文本文件|*.txt|音乐文件|*.wav|图片文件|*.jpg|所有文件|*.*";
sfd.Title = "请选择要保存的文件路径";
sfd.ShowDialog(this);
string path = sfd.FileName;
using (FileStream fsWrite = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write))
{
fsWrite.Write(data, 1, length - 1);
}
MessageBox.Show("保存成功");
}
else//接受文本
{
string message = Encoding.UTF8.GetString(data, 0, length);
string time = DateTime.Now.ToString();
textBox3.AppendText(time + "--" + message + "\n");
}
}
}
}
catch
{ }
}
//窗体关闭,杀死所有线程
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
System.Diagnostics.Process.GetCurrentProcess().Kill();
tcpClient.Close();
}
}
}
源代码下载
链接:https://pan.baidu.com/s/1i2sYJyKei-yYrcR2eIKUkQ
提取码:yqp7
如有帮助,请点赞。谢谢。