博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
简单的C#TCP协议收发数据示例
阅读量:5306 次
发布时间:2019-06-14

本文共 5411 字,大约阅读时间需要 18 分钟。

参考:http://www.cnblogs.com/jzxx/p/5630516.html

一、原作者的这段话很好,先引用一下:

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

二、代码如下:

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}\r\n",                 DateTime.Now.ToLongTimeString(), info);        }    }}

需要在项目上加两个TextBox名字分别为 txtSendMssg、txtRecvMssg和一个Button(名字为 btnSend

三、运行效果(效果图片见原作者文章)

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

四、补充

1、运行时提示:由于目标计算机积极拒绝,无法连接。 127.0.0.1:2014

用 System.Net.Dns.GetHostAddresses("localhost")[1].ToString(); 取得的也是127.0.0.1

参考:https://blog.csdn.net/u010784236/article/details/51820284 也与我的情况不一样。

想想我是在局域网中,用ipconfig /all 找到自己的ip  192.168.3.5 替换  127.0.0.1 添加防火墙规则,仍不行。关闭防火墙,还不行。

(如何获得IP,还可参考:https://blog.csdn.net/fwj380891124/article/details/18214145)

正准备放弃时,看到 https://blog.csdn.net/fengzheng22/article/details/17266105 其中有一句:

需要你用tcpclient访问的IP的端口正在被监听,否则就会显示积极拒绝,不是看他是否被占用,要看他是否在监听

想想我是直接整体复制的代码,不是双击窗体后单独写的formMain_load代码。而服务端应该是在formMain_load时开始监听。

于是重新修改代码,使得formMain_load时先运行服务端监听的代码。重新生成并运行,正常。这个错误太低级。

如果在局域网两台电脑上分别运行客户端和服务端,要确保能ping通,检查防火墙规则。参考这里:https://jingyan.baidu.com/article/a65957f4f557cb24e67f9ba6.html

2、另外,这里还有个例子:https://www.jb51.net/article/130148.htm

3、参考:https://www.cnblogs.com/straight/articles/7660889.html

socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,都可以用“打开open –> 读写write/read –> 关闭close”模式来操作。我的理解就是Socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭)。 

如果作为一个服务器,在调用socket()、bind()之后就会调用listen()来监听这个socket,如果客户端这时调用connect()发出连接请求,服务器端就会接收到这个请求。

 isten函数的第一个参数即为要监听的socket描述字,第二个参数为相应socket可以排队的最大连接个数。socket()函数创建的socket默认是一个主动类型的,listen函数将socket变为被动类型的,等待客户的连接请求。

TCP服务器端依次调用socket()、bind()、listen()之后,就会监听指定的socket地址了。TCP客户端依次调用socket()、connect()之后就向TCP服务器发送了一个连接请求。TCP服务器监听到这个请求之后,就会调用accept()函数取接收请求,这样连接就建立好了。之后就可以开始网络I/O操作了,即类同于普通文件的读写I/O操作。

 4、TCP协议三次握手过程分析 参考:http://www.cnblogs.com/rootq/articles/1377355.html

5、C# TCP多线程服务器示例 参考:https://www.cnblogs.com/zhangxiaoyong/p/6486311.html

6. C# socket端口复用-多主机头绑定 参考:https://www.cnblogs.com/viewcozy/p/4666137.html

7、定时执行、一对多  参考:  http://www.cnblogs.com/chenxizhang/archive/2011/09/10/2172994.html

8、在同步模式中,在服务器上使用Accept方法接入连接请求,而在客户端则使用Connect方法来连接服务器。相对地,在异步模式下,服务器可以使用BeginAccept方法和EndAccept方法来完成连接到客户端的任务,在客户端则通过BeginConnect方法和EndConnect方法来实现与服务器的连接。  参考:http://www.cnblogs.com/sunev/archive/2012/08/07/2625688.html

9、C#的IPAddress IPEndPoint  参考 https://www.cnblogs.com/2Yous/p/5797592.html

转载于:https://www.cnblogs.com/pu369/p/9987027.html

你可能感兴趣的文章
写一个根据现有窗体生成自绘窗体代码
查看>>
禁止密码显示框
查看>>
想做自媒体,做什么样的内容呢,怎么做呢--第006期博文
查看>>
深入基础(三)回调函数,文件处理
查看>>
Java发邮件基础篇
查看>>
.net core编写转发服务(三) 接入Polly
查看>>
找到一篇关于2.4/5G信道的新介绍
查看>>
substring()方法
查看>>
css3阴影效果
查看>>
C# 获取某月的第一天和最后一天
查看>>
FileReader上传文件
查看>>
MySQL 系统架构 说明
查看>>
win7下sublime text3 安装Emmet的pyv8
查看>>
Session失效的处理办法
查看>>
tomcat配置jdbc
查看>>
禅道——Linux服务器部署禅道
查看>>
VUE前端无法启动
查看>>
Nuxt.js知识点
查看>>
Java 日期类 Calendar SimpleDateFormat
查看>>
[2018.4.2集训]b-容斥-计数
查看>>