服务器
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;// Socket编程
using System.Net.Sockets;
using System.Threading;
using System.IO;// 文件IO
using System.Text.RegularExpressions;// 正则表达式
namespace MyAcsDemo
{
public partial class Server : Form
{
private delegate void SetTextValueCallBack(string str);// 跨线程访问问题
private delegate void ReceiveMessageCallBack(string str);// 接收客户端发送消息
private SetTextValueCallBack setTextValueCallBack;
private ReceiveMessageCallBack receivevMessageCallBack;
private delegate void SetComboxCallBack(int type, string str);// 控件控制元素
private SetComboxCallBack setComboxCallBack;
private delegate void SendFileCallBack(byte[] bytes);// 发送文件
private SendFileCallBack sendFileCallBack;
//private delegate void ChangeButtonEnableCallBack();// button的激活
//private ChangeButtonEnableCallBack changeButtonEnableCallBack;
Socket csock;// 通信
Socket lsock;// 监听
Dictionary<string, Socket> socketDictionary = new Dictionary<string, Socket>();// 字典集合,存储ip地址和socket
Thread acceptSocketThread;
Thread receiveMessageThread;
//DateTime dateTime = DateTime.Now;// 获取当前的日期和时间
public Server()
{
InitializeComponent();
buttonStartListen.Enabled = true;
buttonStopListen.Enabled = false;
buttonChoose.Enabled = false;
buttonSendFile.Enabled = false;
buttonSendMessage.Enabled = false;
}
// 开始监听
private void buttonStartListen_Click(object sender, EventArgs e)
{
if (!check())
{
return;
}
lsock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ip = IPAddress.Parse(textBoxIP.Text.Trim());
IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(textBoxPort.Text.Trim()));
lsock.Bind(point);
textBoxLog.AppendText(DateTime.Now + "正在监听中......" + "\n");
buttonStartListen.Enabled = false;// 通常每个套接字地址(协议/网络地址/端口)只允许使用一次
lsock.Listen(10);
setTextValueCallBack = new SetTextValueCallBack(SetTextValue);
receivevMessageCallBack = new ReceiveMessageCallBack(ReceiveMessage);
setComboxCallBack = new SetComboxCallBack(AddComboxItem);
sendFileCallBack = new SendFileCallBack(SendFile);
//changeButtonEnableCallBack = new ChangeButtonEnableCallBack(ChangeButtonEnable);
acceptSocketThread = new Thread(new ParameterizedThreadStart(StartListen));
acceptSocketThread.IsBackground = true;
acceptSocketThread.Start(lsock);
}
private void ChangeButtonEnable()
{
buttonChoose.Enabled = true;
buttonSendMessage.Enabled = true;
buttonSendFile.Enabled = true;
}
// 等待客户端的连接,创建Socket
private void StartListen(object obj)
{
Socket lsock = obj as Socket;
while (true)
{
csock = lsock.Accept();
string strIp = csock.RemoteEndPoint.ToString();
socketDictionary.Add(strIp, csock);
comboBoxSocket.Invoke(setComboxCallBack, 1, strIp);
string strMsg = "远程主机:[" + csock.RemoteEndPoint + "]连接成功";
textBoxLog.Invoke(setTextValueCallBack, strMsg);
receiveMessageThread = new Thread(new ParameterizedThreadStart(Receive));
receiveMessageThread.IsBackground = true;
receiveMessageThread.Start(csock);
//groupBoxServer.Invoke(changeButtonEnableCallBack);
}
}
private void Receive(object obj)
{
Socket csock = obj as Socket;
while (true)
{
byte[] bytes = new byte[2048];
int count = csock.Receive(bytes);
if (count == 0)
{
break;
}
else
{
if (bytes[0] == 1)// 消息
{
string str = Encoding.Default.GetString(bytes, 1, count - 1);
string strRecv = "收到[" + csock.RemoteEndPoint + "]的消息:" + str;
textBoxLog.Invoke(receivevMessageCallBack, strRecv);
}
else if (bytes[0] == 2)// 断开连接
{
string str = csock.RemoteEndPoint.ToString();
textBoxLog.Invoke(setTextValueCallBack, str + "断开连接");
comboBoxSocket.Invoke(setComboxCallBack, 2, str);
csock.Close();
return;
}
}
}
}
private void SetTextValue(string str)
{
textBoxLog.AppendText(DateTime.Now + str + "\r\n");
}
private void ReceiveMessage(string str)
{
textBoxLog.AppendText(DateTime.Now + str + "\r\n");
}
private void AddComboxItem(int type, string str)
{
switch (type)
{
case 1:// 增加
comboBoxSocket.Items.Add(str);
comboBoxSocket.Text = str;
break;
case 2:// 删除
comboBoxSocket.Items.Remove(str);
socketDictionary.Remove(str);// 从集合中删除
break;
default:
break;
}
}
// 发送消息
private void buttonSendMessage_Click(object sender, EventArgs e)
{
try
{
string str = textBoxMessage.Text.Trim();
byte[] bytes = Encoding.Default.GetBytes(str);
List<byte> list = new List<byte>();
list.Add(1);
list.AddRange(bytes);
byte[] newBytes = list.ToArray();// 泛型集合转数组
socketDictionary[comboBoxSocket.SelectedItem.ToString()].Send(newBytes);
textBoxLog.Invoke(setTextValueCallBack, "发送的消息:" + str);
textBoxMessage.Clear();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString(), "发送消息失败");
}
}
// 发送文件
private void buttonSendFile_Click(object sender, EventArgs e)
{
List<byte> list = new List<byte>();
string path = textBoxFilePath.Text.Trim();
using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))
{
byte[] bytes = new byte[1 * 1024 * 1024];// 1M 注意:分配内存大小导致文件传输损坏
int count = fs.Read(bytes, 0, bytes.Length);
list.Add(2);
list.AddRange(bytes);
byte[] newBytes = list.ToArray();
buttonSendFile.Invoke(sendFileCallBack, newBytes);
buttonSendFile.Enabled = false;
textBoxFilePath.Clear();
}
}
// 选择文件
private void buttonChoose_Click(object sender, EventArgs e)
{
// 打开文件
OpenFileDialog ofd = new OpenFileDialog();
ofd.InitialDirectory = "";
ofd.Title = "请选择要发送的文件";
ofd.Filter = "所有文件|*.*";
ofd.ShowDialog();
textBoxFilePath.Text = ofd.FileName;
buttonSendFile.Enabled = true;
}
// 发送文件
private void SendFile(byte[] bytes)
{
try
{
socketDictionary[comboBoxSocket.SelectedItem.ToString()].Send(bytes);
}
catch (Exception ex)
{
MessageBox.Show("发送文件失败:" + ex.Message);
}
}
// 关闭监听
private void buttonStopListen_Click(object sender, EventArgs e)
{
buttonStartListen.Enabled = true;
buttonStopListen.Enabled = false;
buttonChoose.Enabled = false;
buttonSendFile.Enabled = false;
buttonSendMessage.Enabled = false;
lsock.Close();
if (csock != null)
{
csock.Close();
}
acceptSocketThread.Abort();
if (receiveMessageThread != null)
{
receiveMessageThread.Abort();
}
textBoxLog.AppendText(DateTime.Now + "监听关闭" + "\n");
}
private bool check()
{
// 正则表达式
Regex regex = new Regex(@"^(\d){1,3}.(\d){1,3}.(\d){1,3}.(\d){1,3}$");
if (!regex.IsMatch(textBoxIP.Text))
{
MessageBox.Show("IP错误,请输入正确的IP");
return false;
}
int port;
int.TryParse(textBoxPort.Text, out port);
if (textBoxPort.Text.Length >= 5 || port <= 0)
{
MessageBox.Show("端口号错误,请输入正确的端口号");
return false;
}
buttonStopListen.Enabled = true;
return true;
}
private void comboBoxSocket_SelectedIndexChanged(object sender, EventArgs e)
{
if (comboBoxSocket.Text != null)
{
buttonChoose.Enabled = true;
//buttonSendFile.Enabled = true;
buttonSendMessage.Enabled = true;
}
else
{
buttonChoose.Enabled = false;
//buttonSendFile.Enabled = false;
buttonSendMessage.Enabled = false;
}
}
}
}
客户端
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;
namespace MyAcsDemo
{
public partial class Client : Form
{
private delegate void SetTextCallBack(string str);// 后台线程改变文本
private delegate void ReceiveMessageCallBack(string str);// 接收消息
private delegate void SaveFileCallBack(byte[] bytes, int count);// 保存文件
private SetTextCallBack setTextCallBack;
private ReceiveMessageCallBack receiveMessageCallBack;
private SaveFileCallBack saveFileCallBack;
Socket csock;
Thread receiveThread;
public Client()
{
InitializeComponent();
buttonConnect.Enabled = true;
buttonDisConnect.Enabled = false;
buttonSend.Enabled = false;
}
// 建立连接
private void buttonConnect_Click(object sender, EventArgs e)
{
try
{
csock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ip = IPAddress.Parse(textBoxIP.Text.Trim());
csock.Connect(ip, Convert.ToInt32(textBoxPort.Text.Trim()));
setTextCallBack = new SetTextCallBack(SetValue);
receiveMessageCallBack = new ReceiveMessageCallBack(SetValue);
saveFileCallBack = new SaveFileCallBack(SaveFile);
textBoxLog.AppendText(DateTime.Now + "连接服务器成功" + "\n");
receiveThread = new Thread(new ThreadStart(Receive));
receiveThread.IsBackground = true;
receiveThread.Start();
buttonConnect.Enabled = false;
buttonDisConnect.Enabled = true;
buttonSend.Enabled = true;
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString(), "连接服务器失败");
}
}
// 断开连接
private void buttonDisConnect_Click(object sender, EventArgs e)
{
List<byte> list = new List<byte>();
list.Add(2);
byte[] bytes = list.ToArray();
csock.Send(bytes);
csock.Close();
receiveThread.Abort();
textBoxLog.AppendText(DateTime.Now + "已断开与服务器连接" + "\r\n");
buttonDisConnect.Enabled = false;
buttonConnect.Enabled = true;
buttonSend.Enabled = false;
}
// 发送消息
private void buttonSend_Click(object sender, EventArgs e)
{
try
{
string str = textBoxMessage.Text.Trim();
byte[] bytes = new byte[2048];
bytes = Encoding.Default.GetBytes(str);
List<byte> list = new List<byte>();
list.Add(1);
list.AddRange(bytes);
byte[] newBytes = list.ToArray();
csock.Send(newBytes);
textBoxLog.Invoke(setTextCallBack, "发送的消息:" + str);
textBoxMessage.Clear();
}
catch (Exception ex)
{
MessageBox.Show("发送消息失败" + ex.ToString());
}
}
private void SetValue(string str)
{
textBoxLog.AppendText(DateTime.Now + str + "\r\n");
}
// 接收消息
private void Receive()
{
while (true)
{
byte[] bytes = new byte[1 * 1024 * 1024];// 1M
int count = csock.Receive(bytes);
if (count == 0)
{
break;
}
else
{
if (bytes[0] == 1)// 消息
{
string str = Encoding.Default.GetString(bytes, 1, count - 1);
textBoxLog.Invoke(receiveMessageCallBack, "收到的消息:" + str);
}
else if (bytes[0] == 2)// 文件
{
// 保存文件
groupBoxClient.Invoke(saveFileCallBack, bytes, count);
}
}
}
}
private void SaveFile(byte[] bytes, int count)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.InitialDirectory = "";
sfd.Title = "请选择要保存的文件";
sfd.Filter = "所有文件|*.*";
sfd.ShowDialog();
string path = sfd.FileName;
using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write))
{
fs.Write(bytes, 1, count - 1);
}
SetValue("保存文件成功");
}
}
}