TCP同步传送数据示例以及可能出现问题分析
TCP传送数据可以分为同步传送和异步传送,首先这里使用了TCP的同步传送方式,学习了TCP同步传送数据的原理。
同步工作方式是指利用TCP编写的程序执行到监听或者接受数据语句的时候,在未完成当前工作(侦听到连接请求或接收到对方发送来的数据)前不在继续往下执行,线程处于阻塞状态,直到该语句完成响应的工作以后才继续执行下一语句。
TCP协议只需要将数据以字节流的形式发送到缓存,在他自己看来就好像已经完成了此动作,然而此时的数据让可能还在缓冲区。至于对方是否真正的接收到数据,就不再负责了。这以后可以继续执行其他的操作,可以继续发送数据,不会阻塞,而真正的发送是由IP协议完成的。IP层为TCP协议提供了实际的传输服务,从而对上层屏蔽了主动操作时同步和异步的差异。
在同步方式中,比如服务器端有一条语句是接收客户端数据的工作,但是客户端一直没有发送数据,则一直处于等待状态。一下的例子就给出了这种实现功能。
但是,对于请求和发送语句,同步方式和异步方式没有差异,因为程序执行发送语句的时候是直接将数据发送出去而不管对方是否准备好,当客户端发起连接请求时,如果服务器没有打开,则会返回失败信息。此时,数据有可能仍然在本地缓冲区还没有发送出去,这样,TCP协议为我们隐藏了这一细节。
异步工作方式中,监听程序或者接受语句,不论当前工作是否完成,都会继续往下执行。
这里写的服务器和客户端的程序截图:
程序解释:1. 首先客户端连接到服务器。显示连接成功。
2. 给服务器发送了一个"test from client",然后在服务器端点击接收,可以收到客户端发来的数据。
3. 服务器端发送"test from server",因为在程序中写的是连续发送三次,所以这里服务器端发送了三次数据,在客户端点击三次接收,就可以收到三条服务器发来的信息。如果只是点击一次,只能收到服务器发来的一条信息。
4.然后又从客户端给服务器发送了两条消息,服务器接收两次也成功。
5. 如果你在客户端没有给服务器发送消息的时候点击接收消息,这个时候服务器的接收消息线程会阻塞在等待状态,直到客户端发送数据过去,服务器那里就可以显示接收到的数据了。这里就是同步方式的特点了,接收消息的语句会处于阻塞状态。
在本程序中,出错的情况是:在客户端没有传送数据的前提下,连续多次点击服务器的接收消息操作,因为程序中写的是每次接收开启一个线程,这样多次点击接收就会有多个线程同时读网络数据缓冲区,肯定会造成莫名其妙的错误。
程序下载地址:http://www.2cto.com/uploadfile/2012/0607/20120607105137520.rar
重点语句说明:
tcpClient = tcpListener.AcceptTcpClient();
这里的接收客户端连接请求时同步方式,如果没有客户端请求,则一直处于阻塞状态,所以一定要放在单独的线程中。
try
{
string message = br.ReadString();
ShowMsg(message);
}
这里的接收消息,也是同步操作,如果没有消息到来,则一直处于阻塞状态,所以也要放在单独的线程中。
[csharp] networkStream = tcpClient.GetStream();
// 通过BinaryWriter,BinaryReader操作网络流,测试是否可以方便的操作网络流
br = new BinaryReader(networkStream);
bw = new BinaryWriter(networkStream);
networkStream = tcpClient.GetStream();
// 通过BinaryWriter,BinaryReader操作网络流,测试是否可以方便的操作网络流
br = new BinaryReader(networkStream);
bw = new BinaryWriter(networkStream);
这几行代码把从网络连接获取的NetworkStream的操作封装到BinaryWriter,BinaryReader两个类中,通过这两个类可以方便操作网络流的发送和接收,都不用再认为的接收和发送消息,只需要用BinaryWriter,BinaryReader写消息和读消息就可以了,使用起来很方便,我也是第一次用。
本项目的主要代码.
服务器:
[csharp] using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.IO;
using System.Net;
using System.Threading;
namespace TCPServer
{
public partial class Form1 : Form
{
delegate void ShowInfo(string s);
IPAddress serverIP;
int port = 1234;
TcpListener tcpListener;
TcpClient tcpClient;
private NetworkStream networkStream;
BinaryWriter bw;
BinaryReader br;
int sendCount = 1;
int receiveCount = 1;
public Form1()
{
serverIP = IPAddress.Parse("10.108.13.27");
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
tcpListener = new TcpListener(serverIP, port);
tcpListener.Start();
ShowMsg("开始监听");
Thread listenThread = new Thread(new ThreadStart(acceptClientConn));
listenThread.IsBackground = true;
listenThread.Start();
}
private void acceptClientConn()
{
try
{
tcpClient = tcpListener.AcceptTcpClient();
if (tcpClient != null)
{
ShowMsg("接受一个连接请求!");
networkStream = tcpClient.GetStream();
// 通过BinaryWriter,BinaryReader操作NetworkStream
bw = new BinaryWriter(networkStream);
br = new BinaryReader(networkStream);
}
}
catch (System.Exception ex)
{
//
}
}
/// <summary>
/// 线程安全的现实信息
/// </summary>
/// <param name="info"></param>
public void ShowMsg(string info)
{
ShowInfo call = delegate(string s) { this.richTextBox1.Text += s + "\n"; };
this.richTextBox1.Invoke(call, info);
}
private void button2_Click(object sender, EventArgs e)
{
tcpListener.Stop();
}
private void button5_Click(object sender, EventArgs e)
{
if (br!=null)
{
br.Close();
}
if (bw!=null)
{
bw.Close();
}
if (tcpClient!=null)
{
tcpClient.Close();
}
}
private void button4_Click(object sender, EventArgs e)
{
Thread receiveThread = new Thread(new ThreadStart(receiveMeg));
receiveThread.IsBackground = true;
receiveThread.Start();
}
private void receiveMeg()
{
for (int i = 0; i < receiveCount;i++ )
{
try
{
string message = br.ReadString();
ShowMsg(message);
}
catch (System.Exception ex)
{
if (br != null)
{
br.Close();
}
if (bw != null)
{
bw.Close();
}
if (tcpClient != null)
{
tcpClient.Close();
}
DateTime now = DateTime.Now;
while (now.AddSeconds(3) > DateTime.Now) { }
// 重启线程接受连接请求
Thread threadAccept = new Thread(new ThreadStart(acceptClientConn));
threadAccept.IsBackground = true;
threadAccept.Start();
}
}
}
private void button3_Click(object sender, EventArgs e)
{
Thread sendThread = new Thread(new ParameterizedThreadStart(sendMessage));
sendThread.IsBackground = true;
string s = this.textBox1.Text;
sendThread.Start(s);
}
private void sendMessage(object msg)
{
for (int i = 0; i < sendCount;i++ )
{
try
{
bw.Write(msg.ToString());
DateTime now = DateTime.Now;
while (now.AddSeconds(1)>DateTime.Now)
{
//
}
bw.Flush();
ShowMsg("发送成功!");
}
catch (System.Exception ex)
{
if (br != null)
{
br.Close();
}
if (bw != null)
{
bw.Close();
}
if (tcpClient != null)
{
tcpClient.Close();
}
DateTime now = DateTime.Now;
while (now.AddSeconds(3) > DateTime.Now) { }
// 重启线程接受连接请求
Thread threadAccept = new Thread(new ThreadStart(acceptClientConn));
threadAccept.IsBackground = true;
threadAccept.Start();
}
}
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.IO;
using System.Net;
using System.Threading;
namespace TCPServer
{
public partial class Form1 : Form
{
delegate void ShowInfo(string s);
IPAddress serverIP;
int port = 1234;
TcpListener tcpListener;
TcpClient tcpClient;
private NetworkStream networkStream;
BinaryWriter bw;
BinaryReader br;
int sendCount = 1;
int receiveCount = 1;
public Form1()
{
serverIP = IPAddress.Parse("10.108.13.27");
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
tcpListener = new TcpListener(serverIP, port);
tcpListener.Start();
ShowMsg("开始监听");
Thread listenThread = new Thread(new ThreadStart(acceptClientConn));
listenThread.IsBackground = true;
listenThread.Start();
}
private void acceptClientConn()
{
try
{
tcpClient = tcpListener.AcceptTcpClient();
if (tcpClient != null)
{
ShowMsg("接受一个连接请求!");
networkStream = tcpClient.GetStream();
// 通过BinaryWriter,BinaryReader操作NetworkStream
bw = new BinaryWriter(networkStream);
br = new BinaryReader(networkStream);
}
}
catch (System.Exception ex)
{
//
}
}
/// <summary>
/// 线程安全的现实信息
/// </summary>
/// <param name="info"></param>
public void ShowMsg(string info)
{
ShowInfo call = delegate(string s) { this.richTextBox1.Text += s + "\n"; };
this.richTextBox1.Invoke(call, info);
}
private void button2_Click(object sender, EventArgs e)
{
tcpListener.Stop();
}
private void button5_Click(object sender, EventArgs e)
{
if (br!=null)
{
br.Close();
}
if (bw!=null)
{
bw.Close();
}
if (tcpClient!=null)
{
tcpClient.Close();
}
}
private void button4_Click(object sender, EventArgs e)
{
Thread receiveThread = new Thread(new ThreadStart(receiveMeg));
receiveThread.IsBackground = true;
receiveThread.Start();
}
private void receiveMeg()
{
for (int i = 0; i < receiveCount;i++ )
{
try
{
string message = br.ReadString();
ShowMsg(message);
}
catch (System.Exception ex)
{
if (br != null)
{
br.Close();
}
if (bw != null)
{
bw.Close();
}
if (tcpClient != null)
{
tcpClient.Close();
}
DateTime now = DateTime.Now;
while (now.AddSeconds(3) > DateTime.Now) { }
// 重启线程接受连接请求
Thread threadAccept = new Thread(new ThreadStart(acceptClientConn));
threadAccept.IsBackground = true;
threadAccept.Start();
}
}
}
private void button3_Click(object sender, EventArgs e)
{
Thread sendThread = new Thread(new ParameterizedThreadStart(sendMessage));
sendThread.IsBackground = true;
string s = this.textBox1.Text;
sendThread.Start(s);
}
private void sendMessage(object msg)
{
for (int i = 0; i < sendCount;i++ )
{
try
{
bw.Write(msg.ToString());
DateTime now = DateTime.Now;
while (now.AddSeconds(1)>DateTime.Now)
{
//
}
bw.Flush();
ShowMsg("发送成功!");
}
catch (System.Exception ex)
{
if (br != null)
{
br.Close();
}
if (bw != null)
{
bw.Close();
}
if (tcpClient != null)
{
tcpClient.Close();
}
DateTime now = DateTime.Now;
while (now.AddSeconds(3) > DateTime.Now) { }
// 重启线程接受连接请求
Thread threadAccept = new Thread(new ThreadStart(acceptClientConn));
threadAccept.IsBackground = true;
threadAccept.Start();
}
}
}
}
}
客户端:
[csharp] using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;
namespace TCPClient
{
public partial class Form1 : Form
{
delegate void ShowMeg(string s);
IPAddress serverIP;
int port = 1234;
NetworkStream networkStream;
BinaryWriter bw;
BinaryReader br;
TcpClient tcpClient;
int sendCount = 1;
int receiveCount = 1;
public Form1()
{
serverIP = IPAddress.Parse("10.108.13.27");
InitializeComponent();
}
private void bt_connect_Click(object sender, EventArgs e)
{
// 通过一个新的线程连接
Thread connectThread = new Thread(new ThreadStart(ConnectServer));
connectThread.IsBackground = true;
connectThread.Start();
}
/// <summary>
/// 连接服务器
/// </summary>
private void ConnectServer()
{
try
{
tcpClient = new TcpClient();
tcpClient.Connect(serverIP, port);
DateTime now = DateTime.Now;
while (now.AddSeconds(1) > DateTime.Now) { }
if (tcpClient!=null)
{
// 连接成功
ShowInfo("连接成功!");
networkStream = tcpClient.GetStream();
// 通过BinaryWriter,BinaryReader操作网络流,测试是否可以方便的操作网络流
br = new BinaryReader(networkStream);
bw = new BinaryWriter(networkStream);
}
}
catch
{
// 连接失败
ShowInfo("连接失败!");
}
}
private void ShowInfo(string info)
{
ShowMeg call = delegate(string s) { this.richTextBox1.Text += s + "\n"; };
this.richTextBox1.Invoke(call,info);
}
/// <summary>
/// 断开连接
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)
{
if (br!=null)
{
br.Close();
}
if (bw!=null)
{
bw.Close();
}
if (tcpClient!=null)
{
tcpClient.Close();
}
ShowInfo("成功断开连接!");
}
private void button2_Click(object sender, EventArgs e)
{
// 在新的线程中发送数据
Thread sendThread = new Thread(new ParameterizedThreadStart(SendMessage));
sendThread.IsBackground = true;
string message = this.textBox1.Text;
sendThread.Start(message);
}
private void SendMessage(object message)
{
int sendTimeDelay = 1;
for (int i = 0; i < sendCount;i++ )
{
try
{
bw.Write(message.ToString());
DateTime now = DateTime.Now;
while (now.AddSeconds(sendTimeDelay) > DateTime.Now) { }
bw.Flush();
ShowInfo("发送成功");
}
catch (System.Exception ex)
{
ShowInfo("发送失败");
if (br != null)
{
br.Close();
}
if (bw != null)
{
bw.Close();
}
if (tcpClient != null)
{
tcpClient.Close();
}
//ShowInfo("成功断开连接!");
}
}
}
private void button3_Click(object sender, EventArgs e)
{
//在新的线程中接收
Thread receiveThread = new Thread(new ThreadStart(ReceiveMeg));
receiveThread.IsBackground = true;
receiveThread.Start();
}
private void ReceiveMeg()
{
for (int i = 0; i < receiveCount; i++)
{
try
{
string message = br.ReadString();
if (message!=null)
{
ShowInfo(message);
}
}
catch (System.Exception ex)
{
ShowInfo("接收失败!");
}
}
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;
namespace TCPClient
{
public partial class Form1 : Form
{
delegate void ShowMeg(string s);
IPAddress serverIP;
int port = 1234;
NetworkStream networkStream;
BinaryWriter bw;
BinaryReader br;
TcpClient tcpClient;
int sendCount = 1;
int receiveCount = 1;
public Form1()
{
serverIP = IPAddress.Parse("10.108.13.27");
InitializeComponent();
}
private void bt_connect_Click(object sender, EventArgs e)
{
// 通过一个新的线程连接
Thread connectThread = new Thread(new ThreadStart(ConnectServer));
connectThread.IsBackground = true;
connectThread.Start();
}
/// <summary>
/// 连接服务器
/// </summary>
private void ConnectServer()
{
try
{
tcpClient = new TcpClient();
tcpClient.Connect(serverIP, port);
DateTime now = DateTime.Now;
while (now.AddSeconds(1) > DateTime.Now) { }
if (tcpClient!=null)
{
// 连接成功
ShowInfo("连接成功!");
networkStream = tcpClient.GetStream();
// 通过BinaryWriter,BinaryReader操作网络流,测试是否可以方便的操作网络流
br = new BinaryReader(networkStream);
bw = new BinaryWriter(networkStream);
}
}
catch
{
// 连接失败
ShowInfo("连接失败!");
}
}
private void ShowInfo(string info)
{
ShowMeg call = delegate(string s) { this.richTextBox1.Text += s + "\n"; };
this.richTextBox1.Invoke(call,info);
}
/// <summary>
/// 断开连接
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)
{
if (br!=null)
{
br.Close();
}
if (bw!=null)
{
bw.Close();
}
if (tcpClient!=null)
{
tcpClient.Close();
}
ShowInfo("成功断开连接!");
}
private void button2_Click(object sender, EventArgs e)
{
// 在新的线程中发送数据
Thread sendThread = new Thread(new ParameterizedThreadStart(SendMessage));
sendThread.IsBackground = true;
string message = this.textBox1.Text;
sendThread.Start(message);
}
private void SendMessage(object message)
{
int sendTimeDelay = 1;
for (int i = 0; i < sendCount;i++ )
{
try
{
bw.Write(message.ToString());
DateTime now = DateTime.Now;
while (now.AddSeconds(sendTimeDelay) > DateTime.Now) { }
bw.Flush();
ShowInfo("发送成功");
}
catch (System.Exception ex)
{
ShowInfo("发送失败");
if (br != null)
{
br.Close();
}
if (bw != null)
{
bw.Close();
}
if (tcpClient != null)
{
tcpClient.Close();
}
//ShowInfo("成功断开连接!");
}
}
}
private void button3_Click(object sender, EventArgs e)
{
//在新的线程中接收
Thread receiveThread = new Thread(new ThreadStart(ReceiveMeg));
receiveThread.IsBackground = true;
receiveThread.Start();
}
private void ReceiveMeg()
{
for (int i = 0; i < receiveCount; i++)
{
try
{
string message = br.ReadString();
if (message!=null)
{
ShowInfo(message);
}
}
catch (System.Exception ex)
{
ShowInfo("接收失败!");
}
}
}
}
}
文章转自:http://www.2cto.com/kf/201206/134840.html
TCP同步传送数据示例以及可能出现问题分析的更多相关文章
- TCP同步传送数据示例(简洁、清楚)
转自:http://www.2cto.com/kf/201206/134841.html 本例子写了个简单的TCP数据传送功能.没有使用BinaryWriter,BinaryReader,而是使用Ne ...
- 简单的C#TCP协议收发数据示例
参考:http://www.cnblogs.com/jzxx/p/5630516.html 一.原作者的这段话很好,先引用一下: Socket的Send方法,并非大家想象中的从一个端口发送消息到另一个 ...
- 以太网,IP,TCP,UDP数据包分析【转】
原文地址:http://www.cnblogs.com/feitian629/archive/2012/11/16/2774065.html 1.ISO开放系统有以下几层: 7 应用层 6 表示层 5 ...
- 以太网,IP,TCP,UDP数据包分析(此文言简意赅,一遍看不懂的话,耐心的看个10遍就懂了,感谢作者无私奉献)
1.ISO开放系统有以下几层: 7 应用层 6 表示层 5 会话层 4 传输层 3 网络层 2 数据链路层 1 物理层 2.TCP/IP 网络协议栈分为应用层(Application).传输层(Tra ...
- 1、如何抓取Modbus TCP/UDP 数据包实战
CEIWEI最近发布了Modbus RTU Over TCP/UDP 过滤监控的新工具,下面以Modbus RTU TCP为示例,讲解如何抓取Modbus通信数据包,因为CEIWEI ModbusMo ...
- TCP/IP数据包结构具体解释
[关键词] TCP IP 数据包 结构 具体解释 网络 协议 一般来说,网络编程我们仅仅须要调用一些封装好的函数或者组件就能完毕大部分的工作,可是一些特殊的情况下,就须要深入的理解 网络数据包的结构, ...
- TCP最大报文段MSS源码分析
概述 本文主要对MSS相关的几个字段结合源码流程进行分析: 字段含义 user_mss(tcp_options_received)–用户配置的mss,优先级最高: mss_clamp(tcp_opti ...
- C# 从Excel2003将数据导入到SQL2005,数据发生截断的问题分析
C# 从Excel2003将数据导入到SQL2005,数据发生截断的问题分析 问题描述:大家没有遇到过这种情况使用自己编写的工具读取Excel2003文件中的数据,然后执行插入语句将数据批量导入到SQ ...
- Node.js学习之TCP/IP数据通讯
Node.js学习之TCP/IP数据通讯 1.使用net模块实现基于TCP的数据通讯 提供了一个net模块,专用于实现TCP服务器与TCP客户端之间的通信 1.1创建TCP服务器 在Node.js利用 ...
随机推荐
- Unity视频播放的各种实现方式汇总
http://www.taidous.com/bbs/article-860-1.html Unity视频播放有很多种实现方式,可根据要求来选择适当的实现,这里总结一下: 1. MovieTextu ...
- IE6 IE7 hasLayout bug之li间的3px垂直间距
1. li中仅包含a,span等内联(行内)元素2.触发条件: li元素的layout被触发(通常为设置了宽或高,设置overflow:hidden在IE7下同样触发layout),且a或span元素 ...
- 20145218 《Java程序设计》第04次实验报告
北京电子科技学院(BESTI)实验报告 课程:Java程序设计 班级:1452 指导教师:娄嘉鹏 实验日期:2016.04.22 实验名称:Android开发基础 一.实验内容 1.基于Android ...
- 在ubuntu(linux)下安装vim,以及vim的常用命令
介绍vim: vim是一种编辑器,自我感觉这东西好用,就是现在有些不太习惯 如何安装: 如果是使用redhat ,系统自带着vi和vim 如果是使用ubuntu,建议使用apt-get命令, 可以尝试 ...
- IO流--字符流
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileReader; import java ...
- MySql与SqlServer的一些常用用法的差别
MySql与SqlServer的一些常用用法的差别 本文为转载 本文将主要列出MySql与SqlServer不同的地方,且以常用的存储过程的相关内容为主. 1. 标识符限定符 SqlServer [] ...
- groovy基础
字符串字面值 def age=25 log.info 'My age is ${age}' log.info "my age is \${age}" log.info " ...
- springMvc配置编码过滤器
在web.xml中配置 <!-- 编码过滤器 --> <filter> <filter-name>characterEncodingFilter</filte ...
- jQuery_pager.js分页
在做前端项目中,总是需要自己手写类似于这样的分页效果: 这就需要使用jQuery.pager.js文件,其使用方法为:在html中引入三个文件,分别为: <link rel="styl ...
- NetworkComms框架介绍 完美支持TCP/UDP协议
NetworkComms网络通信框架序言 英文文章地址 :http://www.networkcomms.net/tcp-udp-connections/ NetworkComs.Net无缝的支持TC ...