版工目前有一个 ASP.NET 项目,server 上的数据库是用 Sybase ASE 12.5.1,将来会需要用 PDA (操作系统为 Windows Mobile 6),透过网络联机至远程的 server,再将数据传送至 server 上的 Sybase。但 PDA 用的数据库是 SQL Server Compact,因此无法与 Sybase 直接联机,也就无法直接交换数据库中的数据。
要交换两边不同厂商数据库的数据,版工目前想到两种解决方案:
1. 使用者在 PDA 输入的数据,直接存到 .txt 纯文字文件中,等 PDA 和 server 联机后,再将该个 .txt 档上载至 server 中。但这样一来 PDA 中的 SQL Server Compact 数据库,即无用武之地。虽然它是 Windows Mobile 6 免费内建在 ROM 中的,但不好好利用有点可惜。
2. 用 .NET 的网络和 Socket 函式库,自己写网络程序,先从 PDA 建立联机至远程 server,再将 PDA 中的文字数据上传至 server 上。
以下两段代码,为上述第 2 点的源代码。透过 System.Net.Sockets namespace 的 NetworkStream class,达成我们想要的,跨越网络的数据交换作业。第一段的 server 端代码,是在书上找到的 VB.NET Windows Form 范例;第二段的 client 端 (PDA) 代码,为版工我随手写的 C# 范例。
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
server 端代码
Imports System.Text
Imports System.Net.Sockets
Imports System.Threading
Imports System.Net
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
Public Class FormNetServerClass FormNetServer
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Dim intPort As Integer
Dim myTcpListener As TcpListener
Dim myNetworkStream As NetworkStream
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Private Sub btnListener_Click()Sub btnListener_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnListener.Click
Dim myThread As New Thread(New ThreadStart(AddressOf StartListen))
myThread.Start()
End Sub
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Private Sub StartListen()Sub StartListen()
Label.CheckForIllegalCrossThreadCalls = False
TextBox.CheckForIllegalCrossThreadCalls = False
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
intPort = Integer.Parse(txtPort.Text)
myTcpListener = New TcpListener(IPAddress.Parse("192.168.0.1"), intPort)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Dim blnConection As Boolean = False
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Try
myTcpListener.Start()
lblMessage.Text = "等待連線中 ……"
Dim mySocket As Socket = myTcpListener.AcceptSocket()
Do
If mySocket.Connected = True Then
lblMessage.Text = "通訊埠 " + txtPort.Text + " 連線成功"
myNetworkStream = New NetworkStream(mySocket)
Do
Dim strContent As String
Dim myByte(1024) As Byte
Dim lngRead As Integer = myNetworkStream.Read(myByte, 0, 1024)
If lngRead < 0 Then Exit Do
strContent = Encoding.UTF8.GetString(myByte)
txtContent.Text += strContent
Loop
End If
Loop
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Catch ex As SocketException
MessageBox.Show _
(ex.Message, "開啟連接錯誤", MessageBoxButtons.OK, _
MessageBoxIcon.Warning)
End Try
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
End Sub
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Private Sub btnClose_Click()Sub btnClose_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnClose.Click
myTcpListener.Stop()
End Sub
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
End Class
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
client 端 (PDA) 代码
using System.Data.SqlServerCe;
using System.IO;
//using System.Data.SqlClient;
//using Sybase.Data.AseClient;
using System.Net;
using System.Net.Sockets;
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
namespace DeviceApplication01
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
public partial class Form1 : Form
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
TcpClient myTcpClient = new TcpClient();
NetworkStream myNetworkStream;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public Form1()
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
InitializeComponent();
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
// 透過 .NET 的 Socket API,從 PDA 連線至遠端 PC (可正確執行)
private void button6_Click(object sender, EventArgs e)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
string strHostName = txtHostName.Text;
int intPort = Int32.Parse(txtPort.Text);
try
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
myTcpClient.Connect(strHostName, intPort);
myNetworkStream = myTcpClient.GetStream();
lblMessage.Text = "ip:" + strHostName + ", port: " + intPort.ToString() + ", 連接成功";
}
catch (ArgumentOutOfRangeException ex)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
MessageBox.Show("ArgumentOutOfRangeException 例外: " + ex.Message + ", 通訊埠號碼不正確");
}
catch (SocketException ex)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
MessageBox.Show("SocketException 例外: " + ex.Message + ",連接錯誤");
}
catch (Exception ex)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
MessageBox.Show("Exception 例外: " + ex.Message);
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
// 將 TextBox 中使用者輸入的內容,從 PDA 傳送到已連線的遠端 PC 上 (可正確執行)
private void btnTransString_Click(object sender, EventArgs e)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
string strTransString = tbTransString.Text;
byte[] byteArray1 = Encoding.UTF8.GetBytes(strTransString);
lblMessage.Text = ("已經建立網路串流,將字串寫入串流!");
myNetworkStream = myTcpClient.GetStream();
// Check to see if this NetworkStream is writable.
if (myNetworkStream.CanWrite)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
myNetworkStream.Write(byteArray1, 0, byteArray1.Length);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
//byte[] myWriteBuffer = Encoding.ASCII.GetBytes("Are you receiving this message?");
//myNetworkStream.Write(myWriteBuffer, 0, myWriteBuffer.Length);
}
else
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
lblMessage.Text = ("Sorry. You cannot write to this NetworkStream.");
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
} // end of class
} // end of namespace
上述源代码,可由此处下载:
http://files.cnblogs.com/WizardWu/080706.zip
(此代码是在繁体中文版的 Windows、VS 2005 上开发,尚未在简体中文的环境里编译、执行、测试过)
执行画面如下方四张图。
图 1 中,我们先在 server 中 (IP 为 192.168.0.1),开启 8020 port 并等待 client-side 联机。
图 2 中,我们在 PDA 中的两个 TextBox 先输入要联机的 server IP 和 port,并按下「socket 连接远程 PC」Button,先和 server 建立网络联机。
图 3 中,继续在 PDA 中,按下「传下列 TextBox 字符串到远程 PC」Button,就会将该 Button 下方 TextBox 里,使用者输入的文字内容,传送至 server 上。
图 4 中,server 接收到 PDA 所传来的文字内容。
![](https://i-blog.csdnimg.cn/blog_migrate/323a8099019605ba98a94996037c4b85.jpeg)
图 1
![figure2](https://i-blog.csdnimg.cn/blog_migrate/1738eca47632ae6162445774bb6f6873.jpeg)
图 2
![figure3](https://i-blog.csdnimg.cn/blog_migrate/0554a4849adb9efa6b1a374c24046340.jpeg)
图 3
![figure4](https://i-blog.csdnimg.cn/blog_migrate/fad9bb79fb000fd0e02c799b51cf3bda.jpeg)
图 4
测试环境,为一台个人 PC 当作 server,另一台 Notebook 上的 PDA 仿真器当作 client,双方透过一条网络线直接对连,模拟 LAN 环境。
上述 server 端的代码,会一直跑 loop,逐渐吃掉 server 上的系统资源,且代码中建立的网络通讯,似乎开启后也忘了 close。看来即使是书上的代码范例,也还有很大的改善空间。台湾的计算机书,好坏差别是相当大的,不能太指望书附光盘里的代码,其执行结果的正确性,有 bug 是很正常的。