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利用 ...
随机推荐
- Windows 位图
目录 第1章简介 1 1.1 DFB 1 1.2 DDB 1 1.3 DIB 2 第2章相关API 3 2.1 创建 3 2.1.1 CreateCompatibl ...
- Unity5 新功能解析--物理渲染与standard shader
Unity5 新功能解析--物理渲染与standard shader http://blog.csdn.net/leonwei/article/details/48395061 物理渲染是UNITY5 ...
- ubuntu12.04 安装配置jdk1.7
第一步:下载jdk-7-linux-i586.tar.gz wget -c http://download.oracle.com/otn-pub/java/jdk/7/jdk-7-linux-i586 ...
- spring配置带参数的视图解析器:ParameterMethodNameResolver
1.配置处理器 <!-- 处理器 --> <bean id="myController" class="cn.cnsdhzzl.controller.M ...
- 课堂练习&课下作业
设计思路: 列举出买十本的所有情况:1.一本的时候不打折扣 2.两本的时候买两本价最低 3.三本的时候买三本价最低 4.四本的时候买四本价最低 5.五本的时候买五本价最低 6.六本的时候分一本和五本价 ...
- attachEvent ,addEventListener
if (window.attachEvent) { window.attachEvent("onload", remove); ...
- mybatis使用
mybatis网站:http://mybatis.github.io/spring/zh/ mybatis spring下载网址:https://github.com/mybatis/spring/r ...
- java面向对象编程——第六章 数组
1.数组概述 数组是存储在一个连续的内存块中的元素集合.数组中的每个元素必须是相同的数据类型,并且通过索引进行区分.数组中的第一个元素的索引为0. 在java中,创建数组有两个步骤: 声明一个对数组的 ...
- 如何在Quagga BGP路由器中设置IPv6的BGP对等体和过滤
在本教程中,我们会向你演示如何创建IPv6 BGP对等体并通过BGP通告IPv6前缀.同时我们也将演示如何使用前缀列表和路由映射特性来过滤通告的或者获取到的IPv6前缀. 拓扑 服务供应商A和B希望在 ...
- c++普通高精除单精
//没有在网上测试 //手测几组无误 //如有错误,还望指出,不胜感激. #include<cstdio>#include<cstring>int a1[600],a2,a4[ ...