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利用 ...
随机推荐
- java 集合(Map2)
Map 接口的迭代方法: import java.util.*; public class ex12 { public static void main(String[] args) { Map< ...
- English word
第一部分 通过词缀认识单词 (常用前缀一) 1.a- ①加在单词(形容词)或词根前面,表示"不,无,非" acentric [ə'sentrik] a 无中心的(a+centr ...
- 微信JS SDK Demo 官方案例
微信JS-SDK是微信公众平台面向网页开发者提供的基于微信内的网页开发工具包. 通过使用微信JS-SDK,网页开发者可借助微信高效地使用拍照.选图.语音.位置等手机系统的能力,同时可以直接使用微信分享 ...
- [redis] 征服Redis系列
征服 Redis:简介+安装+调优+测试+主从+集群 征服 Redis + Jedis:简单Jedis+池化Jedis+集群Jedis 征服 Redis + Jedis + Spring (一)—— ...
- VMware Workstation 无法连接到虚拟机
"This PC(我的电脑)":右键"manage(管理)": "Service and Applications(服务和应用)":&quo ...
- SAP 预制发票时扣除已预制的数据
INCLUDE程序: LMR1MF6S 最后增强: ENHANCEMENT ZMIR7_01. "active version DATA:LS_YDRSEG LIKE LINE OF YDR ...
- go——搭建Win7下的Go开发环境
1.首先需要下载下载go平台安装包 安装程序 下载地址:https://golang.org/dl/ (墙内下载地址http://www.golangtc.com/download),如果是您的系统是 ...
- 解决apache AH01630: client denied by server configuration错误
昨天给公司配置了apache-2.4.9的版本,今天他们要求把虚拟主机配置起好放网站程序,在修改apache-2.4.9的配置文件中,我发现了2.4.x跟以前的2.2.x里面的很多配置都不一样了,比如 ...
- oracle之to_char,to_date用法
[转载自]http://www.jb51.net/article/45591.htm 这篇文章主要介绍了oracle中to_date详细用法示例,包括期和字符转换函数用法.字符串和时间互转.求某天是星 ...
- 简单模拟QQ界面框架。
package com.lixu.qqjiemian; import java.util.Timer; import java.util.TimerTask; import android.app.A ...