版工目前有一个 ASP.NET 项目,server 上的数据库是用 Sybase ASE 12.5.1,需要用 PDA (操作系统为 Windows Mobile 6),透过网络联机至远程的 server,再将数据传送至 server 上的 Sybase。但 PDA 用的数据库是 SQL Server Compact,因此无法与 Sybase 直接联机,也就无法直接交换数据库中的数据。版工目前想到两种解决方案。
版工目前有一个 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# 范例。
server 端代码
Imports System.Text
Imports System.Net.Sockets
Imports System.Threading
Imports System.Net
Public Class FormNetServerClass FormNetServer
Dim intPort As Integer
Dim myTcpListener As TcpListener
Dim myNetworkStream As NetworkStream
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
Private Sub StartListen()Sub StartListen()
Label.CheckForIllegalCrossThreadCalls = False
TextBox.CheckForIllegalCrossThreadCalls = False
intPort = Integer.Parse(txtPort.Text)
myTcpListener = New TcpListener(IPAddress.Parse("192.168.0.1"), intPort)
Dim blnConection As Boolean = False
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
Catch ex As SocketException
MessageBox.Show _
(ex.Message, "開啟連接錯誤", MessageBoxButtons.OK, _
MessageBoxIcon.Warning)
End Try
End Sub
Private Sub btnClose_Click()Sub btnClose_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnClose.Click
myTcpListener.Stop()
End Sub
End Class
client 端 (PDA) 代码
using System.Data.SqlServerCe;
using System.IO;
//using System.Data.SqlClient;
//using Sybase.Data.AseClient;
using System.Net;
using System.Net.Sockets;
namespace DeviceApplication01
{
public partial class Form1 : Form
{
TcpClient myTcpClient = new TcpClient();
NetworkStream myNetworkStream;
public Form1()
{
InitializeComponent();
}
// 透過 .NET 的 Socket API,從 PDA 連線至遠端 PC (可正確執行)
private void button6_Click(object sender, EventArgs e)
{
string strHostName = txtHostName.Text;
int intPort = Int32.Parse(txtPort.Text);
try
{
myTcpClient.Connect(strHostName, intPort);
myNetworkStream = myTcpClient.GetStream();
lblMessage.Text = "ip:" + strHostName + ", port: " + intPort.ToString() + ", 連接成功";
}
catch (ArgumentOutOfRangeException ex)
{
MessageBox.Show("ArgumentOutOfRangeException 例外: " + ex.Message + ", 通訊埠號碼不正確");
}
catch (SocketException ex)
{
MessageBox.Show("SocketException 例外: " + ex.Message + ",連接錯誤");
}
catch (Exception ex)
{
MessageBox.Show("Exception 例外: " + ex.Message);
}
}
// 將 TextBox 中使用者輸入的內容,從 PDA 傳送到已連線的遠端 PC 上 (可正確執行)
private void btnTransString_Click(object sender, EventArgs e)
{
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)
{
myNetworkStream.Write(byteArray1, 0, byteArray1.Length);
//byte[] myWriteBuffer = Encoding.ASCII.GetBytes("Are you receiving this message?");
//myNetworkStream.Write(myWriteBuffer, 0, myWriteBuffer.Length);
}
else
{
lblMessage.Text = ("Sorry. You cannot write to this NetworkStream.");
}
}
} // end of class
} // end of namespace
上述源代码,可由此处下载:
https://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 所传来的文字内容。
图 1
图 2
图 3
图 4
测试环境,为一台个人 PC 当作 server,另一台 Notebook 上的 PDA 仿真器当作 client,双方透过一条网络线直接对连,模拟 LAN 环境。
上述 server 端的代码,会一直跑 loop,逐渐吃掉 server 上的系统资源,且代码中建立的网络通讯,似乎开启后也忘了 close。看来即使是书上的代码范例,也还有很大的改善空间。台湾的计算机书,好坏差别是相当大的,不能太指望书附光盘里的代码,其执行结果的正确性,有 bug 是很正常的。