C#服务器客户端

本文详细介绍了一个基于TCP协议的服务器与客户端通信的实现过程,包括服务器端的监听、接收和发送消息,以及客户端的连接、接收和发送消息。通过多线程处理,实现了消息的实时收发和文件传输功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

服务器

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("保存文件成功");
        }
    }
}
 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值