简单Tcp的winform窗体

  1. 云栖社区>
  2. 博客>
  3. 正文

简单Tcp的winform窗体

codingcoge 2017-10-21 16:25:47 浏览507
展开阅读全文

最近我们工作室的老师要过来检查了 算是正式大二了。这便是让我抛下医药项目,突击看了书本和网上的例子结合写的Tcp聊天工具。之前我对套接字还是很排斥的,看到就头疼 当初直接跳过 这次回过头来做这个项目也是对我自己的完善和检测。
先来看一下我的简单winform窗体的界面吧
这里写图片描述
* 注意:*
1首先注意的点就是 上面的Icon图标是可以改的,这样看起来好看点,这个也是我的队友告诉我的 我也是蠢的一比 啥也不知道
2还有标题 当初我本来是要用Paint绘制画板写的 ,后来发现可以用Label控件就ok
3.本文章的客户端是针对传送字符串操作的 和下面的服务器端有点冲突 因为 服务器端还可以传送文件等操作 所以 留意区别
TCP要用到的头文件
using System.IO;
using System.Net.Sockets;
using System.Net;
using System.Threading;
知识点
用到的知识点无非就是
1.Socket的套接字
2.线程(没有线程的话 当窗体在等待接收的时候 窗体是卡死的 不能进行其他操作 所以要对等待的事件进行后台线程操作)
3.skinEngine控件的皮肤控件 用来美化窗体(控件在其他文章里 自己找)
4键盘控制输入
5 首先要设置Socket GetSocket; 这个全局变量 不然容易忽视而造成无连接
6form窗体有个属性是AccepButton 绑定一个控件 比如button1 效果是如果按键盘的Enter相当于单击button1

7还有一个问题就是 当传输的内容过多 不进行操作的话 就会出现看不到消息 要手动拖动滑轮 解决方案如下:
单击richtextbox控件 进行操作

 private void richTextBox2_TextChanged(object sender, EventArgs e)
        {
            richTextBox2.SelectionStart = richTextBox2.Text.Length;
            richTextBox2.ScrollToCaret();//将控件内容滚到当前插入字符的位置
        }

对窗体进行初始化 窗体加载的时候要 加载皮肤 。其次还要对线程的检查设置为false 否则 线程无法建通。最后 要对窗体接受键盘按键的值设置为true。

 private void Form1_Load(object sender, EventArgs e)
        {
            this.skinEngine1.SkinFile = "Silver.ssk";
            Control.CheckForIllegalCrossThreadCalls = false;
            this.KeyPreview = true;
        }

单击连接按钮的代码 try{}catch{}是为了防止窗体因为服务端断来连接而造成的窗体卡死

 private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                Socket GetSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//创建了Socket连接
                IPAddress IP = IPAddress.Parse(textBox1.Text);//获取ip地址
                IPEndPoint point = new IPEndPoint(IP, Int32.Parse(label1.Text));  //是ip地址和端口号的集合
                GetSocket.Connect(point);//创建连接  GetSocket和服务器端建立连接
                Thread thread = new Thread(Recive);//创建线程将Recive函数作为传递给线程的委托
                thread.IsBackground = true; //设置线程为后台线程
                thread.Start(GetSocket);  
            }
            catch { }

        }

recive函数用来接受服务器端的消息

void Recive(object a)
        {
            GetSocket = a as Socket;
            try
            {
                while (true)
                {
                    byte[] buffer = new byte[1024 * 1024 * 2];//传输的时候都是用Byte字节来传输的   这是2MB
                    int number = GetSocket.Receive(buffer);//number是实际接受的长度  receive是接受服务器端传送的消息
                    if (number == 0)
                        break;  //这是防止意外的跳出
                    string ss = Encoding.UTF8.GetString(buffer, 0, number);  //这是byte转换成string类型 0表示从buffer下标为0开始 ,number表示转化的长度
                    ShowThing(ss);
                }
            }
            catch { }
        }

这是 文本框结尾追加 为了代码清晰所以分开写

  void ShowThing(string ss)
        {
            richTextBox2.AppendText(ss + "\n");
        }

这是客户端发送给服务器端的按钮控件

  private void button2_Click(object sender, EventArgs e)
        {
            try
            {
                byte[] buffer = new byte[1024 * 1024 * 2];
                string name = "李四--->" + richTextBox1.Text;
                buffer = Encoding.UTF8.GetBytes(name);
                GetSocket.Send(buffer);  //文本框转化byte的内容
                ShowThing(name);
                richTextBox1.Clear();//清空文本框
            }
            catch
            {

            }
        }

这是窗体接受键盘按钮值的操作 在这里 发送按钮不用Enter 因为 如果这样子虽然也可以达到发送效果 但是文件框会换行 如果 case Key.S的话 也可以达到对应的效果,但是文本框结束后会残留S值 意思就是 虽然按键实现了效果但是按键的 值也施加给了text文本

 private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.KeyCode)  //按下的值 
            { 
                case Keys.F1: button1_Click(sender, e); break;//当按下F1的时候 系统就默认单击button1
                case Keys.Escape: button3_Click(sender, e); break;
            }

        }

以上是客户端的操作 接下来是 服务器端的操作
这个是服务器端的界面 没有进行排版有点简陋
这里写图片描述

实现了 服务器端对多个不同的可以客户端进行收发的效果 还有传送文件的操作 而不是简单的
我就直接复制代码过来好了

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.Sockets;
using System.Net;
using System.Threading;
using System.IO;
namespace WindowsFormsApplication12
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Control.CheckForIllegalCrossThreadCalls = false;
        }
        private void ShowMsg(string str)
        {
            richTextBox1.AppendText(str + "\r\n");
        }

        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                Form2 xx =new Form2();
                xx.Show();
                Form2 xx1 = new Form2();
                xx1.Show();
                Form2 xx2 = new Form2();
                xx2.Show();
                Socket sockWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IPEndPoint point = new IPEndPoint(IPAddress.Any, int.Parse(textBox2.Text));
                sockWatch.Bind(point); //监听程序
                sockWatch.Listen(10);//等待加入的客户端 限制是10个以内
                Thread thread = new Thread(Listen);
                thread.IsBackground = true;
                thread.Start(sockWatch);
            }
            catch
            {

            }
        }
        Socket socketSend;
        Dictionary<string, Socket> SocketDic =new Dictionary<string, Socket>();//这个是为了 实现服务器端对多个客户端进行收发消息 名字对应连接
        void Recive(object o)//监听等待进入的客户端
        {
             socketSend = o as Socket;   //线程要用object  然后转换成需要的类型
            while (true)
            {
                byte[] buffer = new byte[1024 * 1024 * 2];
                int r=socketSend.Receive(buffer);
                if (r == 0)
                    break;
                string str = Encoding.UTF8.GetString(buffer, 0, r);
                ShowMsg(socketSend.RemoteEndPoint.ToString() + ":" + str);//RemoteEndPoint获取socketSend终端的ip地址和端口号信息

            }
        }
        void Listen(object o) //接受客户端传信息
        {
            try
            {
                Socket socketWatch = o as Socket;
                while (true)
                {
                    socketSend = socketWatch.Accept();
                    ShowMsg(socketSend.RemoteEndPoint.ToString() + ":" + "  ok");
                    string name = socketSend.RemoteEndPoint.ToString();
                    SocketDic.Add(name, socketSend);//键值对传值
                    comboBox1.Items.Add(name);
                    Thread thread = new Thread(Recive);
                    thread.IsBackground = true;
                    thread.Start(socketSend);
                }
            }
            catch
            {

            }
        }
        //发送字符串消息这个实现了  判断传入的消息是字符串类型
        private void button2_Click(object sender, EventArgs e)
        {
            byte[] buffer = Encoding.UTF8.GetBytes(richTextBox2.Text);
            List<byte> list = new List<byte>();  
            list.Add(1); 
            list.AddRange(buffer);  
            byte[] newbuffer = list.ToArray();

            string name=comboBox1.SelectedItem.ToString();
            SocketDic[name].Send(newbuffer);
           // MessageBox.Show(socketSend.RemoteEndPoint.ToString());
        }

        private void button3_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Title = "选择打开文件";
            ofd.Filter = "suoyouwenjian|*.*";
            ofd.ShowDialog();
            textBox3.Text = ofd.FileName;
        }

        private void button4_Click(object sender, EventArgs e)
        {
            string name = textBox3.Text;
            using (FileStream fs = new FileStream(name,FileMode.OpenOrCreate,FileAccess.ReadWrite))
            {
                byte[] buffer = new byte[1024 * 1024 * 3];
                int r= fs.Read(buffer,0,buffer.Length);
                List<byte> list = new List<byte>();
                list.Add(2);
                list.AddRange(buffer);
                byte[] newbuffer = list.ToArray();
                SocketDic[comboBox1.SelectedItem.ToString()].Send(newbuffer);
            }
        }
//震动按钮
        private void button5_Click(object sender, EventArgs e)
        {   
            byte[] buffer=new byte[1];
            buffer[0]=2;
            SocketDic[comboBox1.SelectedItem.ToString()].Send(buffer);
        }
    }
}
接收器主要代码
 void recive()
        {
            while (true)
            {
                byte[] buffer = new byte[1024*1024*2];
                int r = sockSend.Receive(buffer);


                if (r == 0)
                    break;
                else if (buffer[0] == 1)
                {
                    string ss = Encoding.UTF8.GetString(buffer,1,r-1); 
                    if(ss!="")
                        showMsg(sockSend.RemoteEndPoint.ToString() + ":" + ss);
                }
                else if (buffer[0] == 2)
                {
                    SaveFileDialog sdg = new SaveFileDialog();
                    sdg.Title = "请选择保存路径";
                    sdg.Filter="text|*.txt*";
                    sdg.InitialDirectory = @"C:\Users\蒋家聪\Desktop";
                    sdg.ShowDialog(this);//不加this会报错
                    using (FileStream write = new FileStream(sdg.FileName, FileMode.OpenOrCreate, FileAccess.ReadWrite))
                    {
                        write.Write(buffer, 1, r - 1);
                        MessageBox.Show("保存成功!");
                    }
                }
            }
        }

网友评论

登录后评论
0/500
评论
codingcoge
+ 关注