zoukankan      html  css  js  c++  java
  • C# Tcp协议收发数据

    运行这个程序前需要先关闭Windows防火墙,Win7系统关闭防火墙的方法是在控制面板的“控制面板系统和安全Windows 防火墙自定义设置”路径中,将“家庭或工作(专用)网络位置设置”和“公用网络位置设置”下面的选项都选到“关闭Windows防火墙(不推荐)”。

    1.界面设计

    左侧为发送数据的输入框,单击“发送数据”把数据发送到指定IP地址的指定端口号。(本例中,IP地址和端口号都被写死到代码中)

    2.程序代码

    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.IO;
    using System.Threading;
    
    namespace TcpClientTest
    {
        public partial class FormMain : Form
        {
            public FormMain()
            {
                InitializeComponent();
            }
    
            private void FormMain_Load(object sender, EventArgs e)
            {
                //初始化控件
                txtSendMssg.Text = "测试数据";
    
                //打开Listener开始监听
                Thread thrListener = new Thread(new ThreadStart(Listen));
                thrListener.Start();
            }
    
            private void FormMain_FormClosing(object sender, FormClosingEventArgs e)
            {
                //强制关闭程序(强行终止Listener)
                Environment.Exit(0);
            }
    
            //发送数据
            private void btnSend_Click(object sender, EventArgs e)
            {
                TcpClient tcpClient = new TcpClient();
                //tcpClient.Connect(IPAddress.Parse("170.0.0.78"), 2014);
                tcpClient.Connect(IPAddress.Parse("127.0.0.1"), 2014);
    
                NetworkStream ntwStream = tcpClient.GetStream();
                if (ntwStream.CanWrite)
                {
                    Byte[] bytSend = Encoding.UTF8.GetBytes(txtSendMssg.Text);
                    ntwStream.Write(bytSend, 0, bytSend.Length);
                }
                else
                {
                    MessageBox.Show("无法写入数据流");
    
                    ntwStream.Close();
                    tcpClient.Close();
    
                    return;
                }
    
                ntwStream.Close();
                tcpClient.Close();
            }
    
            //监听数据
            private void Listen()
            {
                Socket listener = new Socket(AddressFamily.InterNetwork, 
                    SocketType.Stream, ProtocolType.Tcp);
                listener.Bind(new IPEndPoint(IPAddress.Any, 2014));
    
                //不断监听端口
                while (true)
                {
                    listener.Listen(0);
                    Socket socket = listener.Accept();
                    NetworkStream ntwStream = new NetworkStream(socket);
                    StreamReader strmReader = new StreamReader(ntwStream);
                    Invoke(new PrintRecvMssgDelegate(PrintRecvMssg), 
                        new object[] { strmReader.ReadToEnd() });
                    socket.Close();
                }
    
                //程序的listener一直不关闭
                //listener.Close();
            }
    
            //线程内向文本框txtRecvMssg中添加字符串及委托
            private delegate void PrintRecvMssgDelegate(string s);
            private void PrintRecvMssg(string info)
            {
                txtRecvMssg.Text += string.Format("[{0}]:{1}
    ", 
                    DateTime.Now.ToLongTimeString(), info);
            }
        }
    }

    3.运行效果

    在发送数据的文本框中分别输入“千山鸟飞绝”、“万径人踪灭”、“孤舟蓑笠翁”、“独钓寒江雪”四句话,输完一句话,单击一次“发送数据”按钮,就可以在接收数据里看到这四句话了。上面代码中,信息的发送时通过TcpClient连接到127.0.0.1的2014端口,信息的接收是通过Listen函数不断监听本机的2014端口实现的。从自己创建的线程中修改控件信息,用到了委托。

    END

    Socket的Send方法,并非大家想象中的从一个端口发送消息到另一个端口,它仅仅是拷贝数据到基础系统的发送缓冲区,然后由基础系统将发送缓冲区的数据到连接的另一端口。值得一说的是,这里的拷贝数据与异步发送消息的拷贝是不一样的,同步发送的拷贝,是直接拷贝数据到基础系统缓冲区,拷贝完成后返回,在拷贝的过程中,执行线程会IO等待, 此种拷贝与Socket自带的Buffer空间无关,但异步发送消息的拷贝,是将Socket自带的Buffer空间内的所有数据,拷贝到基础系统发送缓冲区,并立即返回,执行线程无需IO等待,所以异步发送在发送前必须执行SetBuffer方法,拷贝完成后,会触发你自定义回调函数ProcessSend,在ProcessSend方法中,调用SetBuffer方法,重新初始化Buffer空间。

  • 相关阅读:
    golang 数据结构 优先队列(堆)
    leetcode刷题笔记5210题 球会落何处
    leetcode刷题笔记5638题 吃苹果的最大数目
    leetcode刷题笔记5637题 判断字符串的两半是否相似
    剑指 Offer 28. 对称的二叉树
    剑指 Offer 27. 二叉树的镜像
    剑指 Offer 26. 树的子结构
    剑指 Offer 25. 合并两个排序的链表
    剑指 Offer 24. 反转链表
    剑指 Offer 22. 链表中倒数第k个节点
  • 原文地址:https://www.cnblogs.com/jzxx/p/5630516.html
Copyright © 2011-2022 走看看