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利用 ...
随机推荐
- Peer Code Reviews Made Easy with Eclipse Plug-In
欢迎关注我的社交账号: 博客园地址: http://www.cnblogs.com/jiangxinnju/p/4781259.html GitHub地址: https://github.com/ji ...
- J2EE相关总结
Java Commons The Java™ Tutorials: http://docs.oracle.com/javase/tutorial/index.html Java Platform, E ...
- 使用Objective-C的文档生成工具
前言 做项目的人多了,就需要文档了.今天开始尝试写一些项目文档.但是就源代码来说,文档最好和源码在一起,这样更新起来更加方便和顺手.象Java语言本身就自带javadoc命令,可以从源码中抽取文档.今 ...
- robotframework笔记2
法文件和目录 层次结构安排测试用例构建如下: 在创建测试用例 测试用例文件 . 自动创建一个测试用例文件 测试套件 包含 测试用例文件. 一个目录包含测试用例文件形成一个更高级别的测试 套件. 这样一 ...
- [myeclipse] 官方中文网站
myeclipse官方中文网站:http://www.myeclipsecn.com/
- ERROR 1130: Host 'root@localhost' is not allowed to connect to MySQL server
连接mysql时遇到的错误. 原因:该用户没有权限连接访问mysql数据库 解决方法:网站上搜了好多,试了都没有用.最终在登陆的信息页面用root用户登陆时不输入root密码即可.
- Spring使用jdbcJdbcTemplate和三种方法配置数据源
三种方法配置数据源 1.需要引入jar包:spring-jdbc-4.3.2.RELEASE.jar <!-- spring内置,springJdbc,配置数据源 --> <bean ...
- MYSQL 日期函数【转】
MySQL日期时间函数大全 DAYOFWEEK(date) 返回日期date是星期几(=星期六,ODBC标准) mysql> select DAYOFWEEK('1998-02-03'); WE ...
- 学习记录012-NFS
1.Network file System 主要是通过网络让不同的主机进行通信,构建于ip协议之上的现代文件系统,用来存储共享视频,图片,文件等 2.并发大的时候会有点问题(维护不好会丢数据) 3.N ...
- System.Web.Optimization找不到引用
在程序包管理控制程序中录入:Install-Package Microsoft.AspNet.Web.Optimization,安装即可.