让知识更加联贯让技术走进生活
我的博客
我的程序我的网络
------郑紫至
E-mail:zhengzizhi@yahoo.com.cn
智能通道系统
本系统全面地展示了Socket与多线程,数据库,工业上采用的CRC查表校验信息码
等综合技术的完整代码,从代码的角度展示了工控通讯的完整过程,本系统可以改装成
地铁、火车站、海关、商场、旅游景点,智能小区、大型集团公司,大型停车场,
等等需要刷卡通行智能验证平台,本系统使用了软终端从理论的角度模拟出单片机终
端设备的通讯过程。
开发工具:Visual Studio 2008.NET(C#) + Microsoft SQL Server 2005
智能通道系统之(1)Server
1.设计模式下的界面截图
2.MainForm.cs:
//******************************************************************************************
// 作者 :郑紫至
// 创建日期:2008-03-14
// 邮件地址:zhengzizhi@mail.china.com
// 博客地址:http://hi.youkuaiyun.com/zhengzizhi
// 备注说明:欢迎大家转载我的博客内容,代码版权归本人所有,请保留此信息。
//******************************************************************************************
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.Threading;
using System.Data.SqlClient;
using System.Configuration;
namespace Server
{
public
partial class
MainForm : Form
{
public
static ListBox TopListBox;
public
static ListBox MiddleListBox;
public
static ListBox BottomListBox;
///<summary>
/// IsServerSocketRunning默认为执行状态
///</summary>
bool IsServerSocketRunning =
true;
public
static PictureBox[] PictureBoxArray;
public
static Label[] LabelArray;
public
static PictureBox ConnectedPictureBox;
public
static PictureBox DisconnectedPictureBox;
int ServerPromgramRunningSeconds = 0;
int MachineCount = 0;
Thread ThreadOfStartServerSocketListening;
Socket ServerSocket;
private
Socket SocketOfNewlyConnection;
public MainForm()
{
InitializeComponent();
InitStaticListBoxes();
}
private
void InitStaticListBoxes()
{
TopListBox =
new ListBox();
MiddleListBox =
new ListBox();
BottomListBox =
new ListBox();
//
// TopListBox
//
TopListBox.BackColor = System.Drawing.Color.Black;
TopListBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
TopListBox.Dock = System.Windows.Forms.DockStyle.Top;
TopListBox.Font =
new System.Drawing.Font("PMingLiU", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(136)));
TopListBox.ForeColor = System.Drawing.Color.Lime;
TopListBox.FormattingEnabled =
true;
TopListBox.HorizontalScrollbar =
true;
TopListBox.ItemHeight = 12;
TopListBox.Location =
new System.Drawing.Point(3, 3);
TopListBox.Name =
"TopListBox";
TopListBox.ScrollAlwaysVisible =
true;
TopListBox.Size =
new System.Drawing.Size(748, 170);
TopListBox.TabIndex = 4;
//
// MiddleListBox
//
MiddleListBox.BackColor = System.Drawing.Color.Black;
MiddleListBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
MiddleListBox.Dock = System.Windows.Forms.DockStyle.Top;
MiddleListBox.Font =
new System.Drawing.Font("PMingLiU", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(136)));
MiddleListBox.ForeColor = System.Drawing.Color.Lime;
MiddleListBox.FormattingEnabled =
true;
MiddleListBox.HorizontalScrollbar =
true;
MiddleListBox.ItemHeight = 12;
MiddleListBox.Location =
new System.Drawing.Point(4, 173);
MiddleListBox.Name =
"MiddleListBox";
MiddleListBox.ScrollAlwaysVisible =
true;
MiddleListBox.Size =
new System.Drawing.Size(747, 170);
MiddleListBox.TabIndex = 5;
//
// BottomListBox
//
BottomListBox.BackColor = System.Drawing.Color.Black;
BottomListBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
BottomListBox.Dock = System.Windows.Forms.DockStyle.Fill;
BottomListBox.Font =
new System.Drawing.Font("PMingLiU", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(136)));
BottomListBox.ForeColor = System.Drawing.Color.Lime;
BottomListBox.FormattingEnabled =
true;
BottomListBox.HorizontalScrollbar =
true;
BottomListBox.ItemHeight = 12;
BottomListBox.Location =
new System.Drawing.Point(5, 343);
BottomListBox.Name =
"BottomListBox";
BottomListBox.ScrollAlwaysVisible =
true;
BottomListBox.Size =
new System.Drawing.Size(746, 182);
BottomListBox.TabIndex = 7;
TopListBox.Parent =
this.tabPage2;
MiddleListBox.Parent =
this.tabPage2;
BottomListBox.Parent =
this.tabPage2;
this.tabPage2.Parent =
this.tabControl1;
}
#region CRC16 Table Polynomial = 0xA001
byte[] CrcTableH8bit = {0x00,0xC0,0xC1,0x01,0xC3,0x03,0x02,0xC2,
0xC6,0x06,0x07,0xC7,0x05,0xC5,0xC4,0x04,
0xCC,0x0C,0x0D,0xCD,0x0F,0xCF,0xCE,0x0E,
0x0A,0xCA,0xCB,0x0B,0xC9,0x09,0x08,0xC8,
0xD8,0x18,0x19,0xD9,0x1B,0xDB,0xDA,0x1A,
0x1E,0xDE,0xDF,0x1F,0xDD,0x1D,0x1C,0xDC,
0x14,0xD4,0xD5,0x15,0xD7,0x17,0x16,0xD6,
0xD2,0x12,0x13,0xD3,0x11,0xD1,0xD0,0x10,
0xF0,0x30,0x31,0xF1,0x33,0xF3,0xF2,0x32,
0x36,0xF6,0xF7,0x37,0xF5,0x35,0x34,0xF4,
0x3C,0xFC,0xFD,0x3D,0xFF,0x3F,0x3E,0xFE,
0xFA,0x3A,0x3B,0xFB,0x39,0xF9,0xF8,0x38,
0x28,0xE8,0xE9,0x29,0xEB,0x2B,0x2A,0xEA,
0xEE,0x2E,0x2F,0xEF,0x2D,0xED,0xEC,0x2C,
0xE4,0x24,0x25,0xE5,0x27,0xE7,0xE6,0x26,
0x22,0xE2,0xE3,0x23,0xE1,0x21,0x20,0xE0,
0xA0,0x60,0x61,0xA1,0x63,0xA3,0xA2,0x62,
0x66,0xA6,0xA7,0x67,0xA5,0x65,0x64,0xA4,
0x6C,0xAC,0xAD,0x6D,0xAF,0x6F,0x6E,0xAE,
0xAA,0x6A,0x6B,0xAB,0x69,0xA9,0xA8,0x68,
0x78,0xB8,0xB9,0x79,0xBB,0x7B,0x7A,0xBA,
0xBE,0x7E,0x7F,0xBF,0x7D,0xBD,0xBC,0x7C,
0xB4,0x74,0x75,0xB5,0x77,0xB7,0xB6,0x76,
0x72,0xB2,0xB3,0x73,0xB1,0x71,0x70,0xB0,
0x50,0x90,0x91,0x51,0x93,0x53,0x52,0x92,
0x96,0x56,0x57,0x97,0x55,0x95,0x94,0x54,
0x9C,0x5C,0x5D,0x9D,0x5F,0x9F,0x9E,0x5E,
0x5A,0x9A,0x9B,0x5B,0x99,0x59,0x58,0x98,
0x88,0x48,0x49,0x89,0x4B,0x8B,0x8A,0x4A,
0x4E,0x8E,0x8F,0x4F,0x8D,0x4D,0x4C,0x8C,
0x44,0x84,0x85,0x45,0x87,0x47,0x46,0x86,
0x82,0x42,0x43,0x83,0x41,0x81,0x80,0x40};
byte[] CrcTableL8bit = {0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40};
#endregion
///<summary>
///根据卡机数目初始化客户端卡机处于“断开状态”图片和卡机编号
///</summary>
///<param name="MachineCount">卡机数目</param>
public
void InitMachineImage(int MachineCount)
{
PictureBoxArray =
new PictureBox[MachineCount + 1];
LabelArray =
new Label[MachineCount + 1];
for (
int i = 1; i <= MachineCount; i++)
{
PictureBoxArray[i] =
new PictureBox();
PictureBoxArray[i].Parent =
this.ListViewImageConnectingStatus;
//获得客户端卡机断开与服务连接的“断开状态”图片
PictureBoxArray[i].Image =
this.imageList1.Images[0];
PictureBoxArray[i].Left = 2 + 50 * (i - 1);
PictureBoxArray[i].Top = 3;
PictureBoxArray[i].SizeMode =
PictureBoxSizeMode.AutoSize;
PictureBoxArray[i].Visible =
true;
LabelArray[i] =
new Label();
LabelArray[i].Parent =
this.ListViewImageConnectingStatus;
LabelArray[i].Text = (i).ToString() +
" 号";
LabelArray[i].ForeColor =
Color.Blue;
LabelArray[i].Left = 2 + (i - 1) * 50;
LabelArray[i].Top = 36;
LabelArray[i].Visible =
true;
LabelArray[i].AutoSize =
true;
}
}
///<summary>
///以查表法获得需要校验字节信息的16进制CRC码
///表格数据的生成多项式CRC-16 Polynomial = 0xA001
///</summary>
///<param name="RequestToCheckBytes">需要校验的字节数组</param>
///<param name="RequestToCheckLengthOfBytes">实际传入的字节数长度</param>
///<returns>返回一个高两位在前,低两位在后的16进制CRC码</returns>
public
string HexCrcCode(byte[] RequestToCheckBytes,
int RequestToCheckLengthOfBytes)
{
int CrcTableIndex = 0;
byte CrcH8bit = 0x00, CrcL8bit = 0x00;
for (int i = 0; i < RequestToCheckLengthOfBytes; i++)
{
if (RequestToCheckBytes[i] >= 0 && RequestToCheckBytes[i] < 255)
{
CrcTableIndex = RequestToCheckBytes[i] ^ CrcL8bit;
CrcL8bit = (byte)(CrcTableL8bit[CrcTableIndex] ^ CrcH8bit);
CrcH8bit = CrcTableH8bit[CrcTableIndex];
}
}
return CrcH8bit.ToString("x2").ToUpper() + CrcL8bit.ToString("x2").ToUpper();
}
public
static IPAddress GetServerIP()
{
IPHostEntry ieh =
Dns.GetHostEntry(Dns.GetHostName());// Dns.GetHostByName(Dns.GetHostName();
return ieh.AddressList[0];
}
public
CardMachineCollection CardMachineList = new
CardMachineCollection();
///<summary>
///当服务器Socket实例_ServerSocket[它是SocketOfNewlyConnection赋给的值]收到的字节长度大于42个字节
///并且OnReceiveData事件非null值时,触发事件要执行的方法CardMachine_OnReceiveData()
///</summary>
///<param name="sender">当前类的实例</param>
///<param name="ReceiveString">服务器接收到的字符串(由服务器接收到的字节转变而来)</param>
///<param name="ReceiveStringLength">服务器接收到的字符串长度</param>
///<param name="ReceiveBytes">服务器接收到的字节</param>
private
void CardMachine_OnReceiveData(object sender,
string ServerReceivedString,
int ServerReceivedStringLength, byte[] ServerReceivedBytes)
{
try
{
string CardNo =
string.Empty;
string MachineNo =
string.Empty;
string ReadHeadNo =
string.Empty;
string SendToClientString =
string.Empty;
string EmpNo =
string.Empty;
string EmpName =
string.Empty;
string CardPassingState =
string.Empty;
string PassingTime =
string.Empty;
string PassingStateInfo =
string.Empty;
if (ServerReceivedString.IndexOf("<EOF>") > -1)
{
(sender
as CardMachine).Close();
}
if (ServerReceivedBytes[0] == 0x03 && (ServerReceivedStringLength == 43))
{
//从第0位到第42位(长度为43)这段字符串中截取第19位20位21位22位23位24位25位和第26位表示卡号的字串
CardNo =
Convert.ToInt32(ServerReceivedString.Substring(19, 8), 16).ToString();
//卡号不足10位左边补0,直到满足10位退出循环
while (CardNo.Length < 10)
{
CardNo =
"0" + CardNo;
}
//从第0位到第42位(长度为43)这段字符串中截取第1位和第2位表示卡机编号的字串
MachineNo = ServerReceivedString.Substring(1, 2);
//从第0位到第42位(长度为43)这段字符串中截取第5位和第6位表示卡机读头编号的字串
ReadHeadNo = ServerReceivedString.Substring(5, 2);
}
if ( !string.IsNullOrEmpty(CardNo))
{
if ((sender
as CardMachine).SqlConn.State !=
ConnectionState.Open)
{
(sender
as CardMachine).SqlConn.Open();
}
(sender
as CardMachine).SqlComm.Parameters["@CardNo"].Value = CardNo;
(sender
as CardMachine).SqlComm.Parameters["@MachineNo"].Value = MachineNo;
(sender
as CardMachine).SqlComm.Parameters["@ReadHeadNo"].Value =
Convert.ToInt32(ReadHeadNo);
(sender
as CardMachine).SqlComm.ExecuteNonQuery();
EmpNo = (sender
as CardMachine).SqlComm.Parameters["@EmpNo"].Value.ToString();
EmpName = (sender
as CardMachine).SqlComm.Parameters["@EmpName"].Value.ToString();
CardPassingState = (sender
as CardMachine).SqlComm.Parameters["@CardPassingState"].Value.ToString();
PassingTime =
DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss");
switch (CardPassingState)
{
case "0": PassingStateInfo =
"正常通行";
break;
case "1": PassingStateInfo =
"无效卡号";
break;
case "2": PassingStateInfo =
"未到或已过就餐时间";
break;
case "3": PassingStateInfo =
"无设置就餐时段";
break;
}
//非正常通行时
if (CardPassingState !=
"0")
{
//发送到客户端卡机的字符串(卡机读头编号固定为04)
SendToClientString =
Convert.ToChar(0x01) + MachineNo + "JA" +
"04" + Convert.ToChar(0x02);
//将字符串转换成字节数组,以获得16进制CRC校验码
byte[] SendToClientBytes = System.Text.Encoding.Default.GetBytes(SendToClientString);
//信息码+16进制CRC校验码+换行符
SendToClientString = SendToClientString + HexCrcCode(SendToClientBytes, 8) +
Convert.ToChar(0x0D);
//将字符串转换成字节数组
byte[] SendingToClientBytes = System.Text.Encoding.Default.GetBytes(SendToClientString);
//将字节数组发送到客户端的卡机
(sender
as CardMachine).SavedSocketOfNewlyConnected.Send(SendingToClientBytes);
}
else
{
//发送到客户端卡机的字符串(读头编号是客户端卡机发送过来的43位字符串中包含的)
SendToClientString =
Convert.ToChar(0x01) + MachineNo + "JA" + ReadHeadNo +
Convert.ToChar(0x02);
//将字符串转换成字节数组,以获得16进制CRC校验码
byte[] SendToClientBytes = System.Text.Encoding.Default.GetBytes(SendToClientString);
//信息码+16进制CRC校验码+换行符
SendToClientString = SendToClientString + HexCrcCode(SendToClientBytes, 8) +
Convert.ToChar(0x0D);
//将字符串转换成字节数组
byte[] SendingToClientBytes = System.Text.Encoding.Default.GetBytes(SendToClientString);
//将字节数组发送到客户端的卡机
(sender
as CardMachine).SavedSocketOfNewlyConnected.Send(SendingToClientBytes);
}
ListViewItem listViewItem = this.PassedRecordlistView.Items.Insert(0, EmpNo);
listViewItem.SubItems.AddRange(new
string[] { EmpName, PassingTime, CardNo, PassingStateInfo, MachineNo, ReadHeadNo });
}
}
catch (System.Exception ex)
{
//MiddleListBox中显示CardMachine_OnReceiveData方法出现错误的时间
MiddleListBox.Items.Add(DateTime.Now.ToString() +
" : CardMachine_OnReceiveData方法中的错误 " + ex.ToString());
//MiddleListBox中显示的数据超过2000条,就删除索引为 1 的那条记录
if (MiddleListBox.Items.Count > 2000) { MiddleListBox.Items.RemoveAt(1); }
}
// PassedRecordlistView中显示的数据超过500条,就删除索引为 1 的那条记录
if (this.PassedRecordlistView.Items.Count >= 500)
PassedRecordlistView.Items.RemoveAt(1);
}
///<summary>
///通过MainForm_Load事件中创建的线程启动服务器端Socket监听
///</summary>
private
void BeginServerSocketListening()
{
byte[] bytes =
new byte[1024];
int i;
string ClientMachineIP;
try
{
//读取服务器IP地址
IPAddress ServerIp = GetServerIP();
//指定双方在8000端口上通讯,也可以把8000写到配置文件中
IPEndPoint iep =
new IPEndPoint(ServerIp, 8000);
ServerSocket =
new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
byte[] byteMessage =
new byte[100];
ServerSocket.Bind(iep);
ServerSocket.Listen(0);
//“永真循环”,在FormClosing事件中重新设置IsServerSocketRunning
//
为False,以退出这个“死循环”,退出服务器Socket处于等待连接的状态
while (IsServerSocketRunning)
{
this.Text =
"卡机服务器IP[ " + iep.ToString() +
" ]正在监听客户端卡机的连线请求 ‥‥‥";
// Accept()方法执行完毕,目的是等待客户端Socket对象的连接请求
//
当客户端Socket执行Send(byte[])方法时,该行代码才继续顺序向
//
下执行,否则就一直处于等待被连接的状态,代码执行暂停在该行;
//
返回值是为新建连接创建新的 Socket对象,它包含了本地终结点和
//
远程终结点,还包含了Connected属性是否已连接到远程主机(客户
//
端卡机)和Available 属性(已经从网络接收且可供读取的数据量)等等
//
方法和属性信息。
SocketOfNewlyConnection = ServerSocket.Accept();
//新建一个卡机对象实例,将已创建的新 Socket 对象包装进来
CardMachine cardMachine =
new CardMachine(SocketOfNewlyConnection);
//实例化委托类型的事件OnReceiveData,当服务器Socket实例_ServerSocket[它是SocketOfNewlyConnection赋给的值]收到的字节
//长度大于42个字节并且OnReceiveData事件非null值时,触发事件要执行的方法CardMachine_OnReceiveData()
cardMachine.OnReceiveData +=
new CardMachine.DegReceiveData(CardMachine_OnReceiveData);
//获取远程终结点(客户端卡机的IP和端口)中的IP地址
ClientMachineIP = ((IPEndPoint)(SocketOfNewlyConnection.RemoteEndPoint)).Address.ToString();
//遍历配置文件(app.config)中用户输入的卡机数目
for (i = 0; i < CardMachineList.Count; i++)
{
//如果保存在卡机集合列表中存在与从远程终结点中获得的IP地址
if (CardMachineList[i].ClientMachineIpAddress == ClientMachineIP)
{
//那么就用最新的卡机对象取代过去的卡机对象;
CardMachineList[i] = cardMachine;
//并将连接状态的图片设置为“已连接上”的图片;
PictureBoxArray[i + 1].Image = ConnectedPictureBox.Image;
//设置客户端卡机的编号
cardMachine.ClientMachineNo = i + 1;
}
}
//MiddleListBox中显示一空行
MiddleListBox.Items.Add("");
//MiddleListBox中显示的数据超过2000条,就删除索引为 1 的那条记录
if (MiddleListBox.Items.Count > 2000) { MiddleListBox.Items.RemoveAt(1); }
//MiddleListBox中显示数据来自那台卡机(IP地址和端口)的数据
MiddleListBox.Items.Add(DateTime.Now.ToString() +
" : 服务器已收到来自客户端[ " + SocketOfNewlyConnection.RemoteEndPoint.ToString() +
" ]发过来的数据");
//MiddleListBox中显示的数据超过2000条,就删除索引为 1 的那条记录
if (MiddleListBox.Items.Count > 2000) { MiddleListBox.Items.RemoveAt(1); }
}
}
catch (System.Exception ex)
{
//MiddleListBox中显示BeginServerSocketListening方法中出现错误的时间
MiddleListBox.Items.Add(DateTime.Now.ToString() +
" : BeginServerSocketListening方法中的错误 " + ex.ToString());
//MiddleListBox中显示的数据超过2000条,就删除索引为 1 的那条记录
if (MiddleListBox.Items.Count > 2000) { MiddleListBox.Items.RemoveAt(1); }
}
}
private
void MainForm_Load(object sender,
EventArgs e)
{
int i, j;
//MiddleListBox中显示服务器启动时间
MiddleListBox.Items.Add(DateTime.Now.ToString() +
" : 服务器已经启动 ");
//获得客户端卡机连接到服务状态下的“连接状态”图片
ConnectedPictureBox =
new PictureBox();
ConnectedPictureBox.Image =
this.imageList1.Images[1];
//获得客户端卡机断开与服务连接的“断开状态”图片
DisconnectedPictureBox =
new PictureBox();
DisconnectedPictureBox.Image =
this.imageList1.Images[0];
//读取配置文件(app.config)中用户输入的卡机数目
MachineCount =
Convert.ToInt32(ConfigurationManager.AppSettings["MachineCount"]);
for (i = 0; i < MachineCount; i++)
{
//新建一个卡机对象实例
CardMachine cardMachine =
new CardMachine(null);
//
加 1 是因为卡机编号从1开始编号
j = i + 1;
//卡机对象实例保存到卡机集合列表中
CardMachineList.Add(cardMachine);
//读取配置文件(app.config)中用户输入的卡机编号对应的IP地址保存到卡机集合列表中
CardMachineList[i].ClientMachineIpAddress = ConfigurationManager.AppSettings["MachineNo" + j.ToString()];
//读取配置文件(app.config)中用户输入的卡机编号保存到卡机集合列表中
CardMachineList[i].ClientMachineNo = j;
}
//
根据卡机数目初始化客户端卡机处于“断开状态”图片和卡机编号
InitMachineImage(MachineCount);
try
{
//创建一个线程用来准备启动服务端的Socket监听
ThreadOfStartServerSocketListening =
new Thread(new
ThreadStart(BeginServerSocketListening));
//正式启动服务端的Socket监听
ThreadOfStartServerSocketListening.Start();
}
catch (Exception ex)
{
//MiddleListBox中显示MainForm_Load事件中的错误
MiddleListBox.Items.Add(DateTime.Now.ToString() +
" : MainForm_Load事件中的错误 " + ex.ToString());
//MiddleListBox中显示的数据超过2000条,就删除索引为 1 的那条记录
if (MiddleListBox.Items.Count > 2000) { MiddleListBox.Items.RemoveAt(1); }
}
}
private
void MainForm_FormClosing(object sender,
FormClosingEventArgs e)
{
//结束“永真循环”退出服务器Socket处于等待连接的状态
IsServerSocketRunning =
false;
for (int i = 0; i <
this.CardMachineList.Count; i++)
{
this.CardMachineList[i].Close();
}
}
private
void timer1_Tick(object sender, System.EventArgs e)
{
try
{
ServerPromgramRunningSeconds++;
//每隔60秒报告一次每台卡机的连接状态
if (ServerPromgramRunningSeconds % 60 == 0)
{
//重新记时,避免数据过大占用内存
ServerPromgramRunningSeconds = 0;
//TopListBox中显示一空行
TopListBox.Items.Add("");
//TopListBox中显示的数据超过2000条,就删除索引为 1 的那条记录
if (TopListBox.Items.Count > 2000) { TopListBox.Items.RemoveAt(1); }
for (int i = 0; i < CardMachineList.Count; i++)
{
//TopListBox中显示卡机IP和连接状态
TopListBox.Items.Add(DateTime.Now.ToString() +
" : [ " + CardMachineList[i].ClientMachineNo.ToString() +
" ]号机IP[ " + CardMachineList[i].ClientMachineIpAddress +
" ]连接状态[ " + CardMachineList[i].ClientIsConnected.ToString() +
" ]");
//TopListBox中显示的数据超过2000条,就删除索引为 1 的那条记录
if (TopListBox.Items.Count > 2000) { TopListBox.Items.RemoveAt(1); }
}
//MiddleListBox中显示一空行
MiddleListBox.Items.Add("");
//MiddleListBox中显示的数据超过2000条,就删除索引为 1 的那条记录
if (MiddleListBox.Items.Count > 2000) { MiddleListBox.Items.RemoveAt(1); }
//BottomListBox中显示一空行
BottomListBox.Items.Add("");
//BottomListBox中显示的数据超过2000条,就删除索引为 1 的那条记录
if (BottomListBox.Items.Count > 2000) { BottomListBox.Items.RemoveAt(1); }
}
for (int i = 0; i < CardMachineList.Count; i++)
{
//
每台卡机每隔1秒钟ClientConnectedLifeTime会自动加上1秒(Timer事件每隔1秒触发一次)
CardMachineList[i].ClientConnectedLifeTime += 1;
//
如果某一台卡机连接时间超过70秒时
if (CardMachineList[i].ClientConnectedLifeTime > 70)
{
//(1)将该台卡机连接时间清0
CardMachineList[i].ClientConnectedLifeTime = 0;
//(2)如果该台卡机还处在“已连接上”上的状态
if (CardMachineList[i].ClientIsConnected == true)
{
//(a)将该卡机已连接状态的图片设置为断开状态的图片
PictureBoxArray[CardMachineList[i].ClientMachineNo].Image = DisconnectedPictureBox.Image;
//(b)如果该卡机已与服务器通讯了
if (CardMachineList[i].SavedSocketOfNewlyConnected !=
null)
{
//(i) 设置ServerSocketIsActive为非活动状态;
//(ii) 禁用SavedSocketOfNewlyConnected上的发送和接收并释放所有关联的资源;
//(iii) 结束ThreadOfServerIsWaitingForClientData线程的执行。
CardMachineList[i].Close();
}
//(c)将该卡机的连接属性设置为断开连接
CardMachineList[i].ClientIsConnected =
false;
//(d)将该卡机设置为非活动状态.
CardMachineList[i].ServerSocketIsActive =
false;
}
//BottomListBox中显示一空行
BottomListBox.Items.Add("");
//BottomListBox中显示的数据超过2000条,就删除索引为 1 的那条记录
if (BottomListBox.Items.Count > 2000) { BottomListBox.Items.RemoveAt(1); }
for (int j = 0; j < CardMachineList.Count; j++)
{
//(4)报告每台卡机的连接状态
BottomListBox.Items.Add(DateTime.Now.ToString() +
" : [ " + CardMachineList[j].ClientMachineNo.ToString() +
" ]号机IP[ " + CardMachineList[j].ClientMachineIpAddress +
" ]连接状态[ " + CardMachineList[j].ClientIsConnected.ToString()+"
]");
//BottomListBox中显示的数据超过2000条,就删除索引为 1 的那条记录
if (BottomListBox.Items.Count > 2000) { BottomListBox.Items.RemoveAt(1); }
}
}
}
}
catch (System.Exception ex)
{
//MiddleListBox中显示timer1_Tick 事件中出现错误的时间
MiddleListBox.Items.Add(DateTime.Now.ToString() +
" : timer1_Tick 事件中的错误 " + ex.ToString());
//MiddleListBox中显示的数据超过2000条,就删除索引为 1 的那条记录
if (MiddleListBox.Items.Count > 2000) { MiddleListBox.Items.RemoveAt(1); }
}
}
}
}
2.MainForm.Designer.cs:
namespace Server
{
partial
class MainForm
{
///<summary>
/// Required designer variable.
///</summary>
private System.ComponentModel.IContainer components =
null;
///<summary>
/// Clean up any resources being used.
///</summary>
///<param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected
override void Dispose(bool disposing)
{
try
{
ServerSocket.Shutdown(System.Net.Sockets.SocketShutdown.Both);
ServerSocket.Close();
ThreadOfStartServerSocketListening.Abort();
}
catch { }
if (disposing && (components !=
null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
///<summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
///</summary>
private
void InitializeComponent()
{
this.components =
new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources =
new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
this.tabControl1 =
new System.Windows.Forms.TabControl();
this.tabPage1 =
new System.Windows.Forms.TabPage();
this.PassedRecordlistView =
new System.Windows.Forms.ListView();
this.columnHeader1 =
new System.Windows.Forms.ColumnHeader();
this.columnHeader2 =
new System.Windows.Forms.ColumnHeader();
this.columnHeader3 =
new System.Windows.Forms.ColumnHeader();
this.columnHeader4 =
new System.Windows.Forms.ColumnHeader();
this.columnHeader5 =
new System.Windows.Forms.ColumnHeader();
this.columnHeader6 =
new System.Windows.Forms.ColumnHeader();
this.columnHeader7 =
new System.Windows.Forms.ColumnHeader();
this.tabPage2 =
new System.Windows.Forms.TabPage();
this.ListViewImageConnectingStatus =
new System.Windows.Forms.ListView();
this.timer1 =
new System.Windows.Forms.Timer(this.components);
this.imageList1 =
new System.Windows.Forms.ImageList(this.components);
this.tabControl1.SuspendLayout();
this.tabPage1.SuspendLayout();
this.SuspendLayout();
//
// tabControl1
//
this.tabControl1.Controls.Add(this.tabPage1);
this.tabControl1.Controls.Add(this.tabPage2);
this.tabControl1.Dock = System.Windows.Forms.DockStyle.Fill;
this.tabControl1.Location =
new System.Drawing.Point(0, 55);
this.tabControl1.Name =
"tabControl1";
this.tabControl1.SelectedIndex = 0;
this.tabControl1.Size =
new System.Drawing.Size(762, 530);
this.tabControl1.TabIndex = 0;
//
// tabPage1
//
this.tabPage1.Controls.Add(this.PassedRecordlistView);
this.tabPage1.Location =
new System.Drawing.Point(4, 21);
this.tabPage1.Name =
"tabPage1";
this.tabPage1.Padding =
new System.Windows.Forms.Padding(3);
this.tabPage1.Size =
new System.Drawing.Size(754, 505);
this.tabPage1.TabIndex = 0;
this.tabPage1.Text =
"通行记录";
this.tabPage1.UseVisualStyleBackColor =
true;
//
// PassedRecordlistView
//
this.PassedRecordlistView.AllowColumnReorder =
true;
this.PassedRecordlistView.BackColor = System.Drawing.Color.Black;
this.PassedRecordlistView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.columnHeader1,
this.columnHeader2,
this.columnHeader3,
this.columnHeader4,
this.columnHeader5,
this.columnHeader6,
this.columnHeader7});
this.PassedRecordlistView.Dock = System.Windows.Forms.DockStyle.Fill;
this.PassedRecordlistView.Font =
new System.Drawing.Font("PMingLiU", 9F);
this.PassedRecordlistView.ForeColor = System.Drawing.Color.Lime;
this.PassedRecordlistView.FullRowSelect =
true;
this.PassedRecordlistView.Location =
new System.Drawing.Point(3, 3);
this.PassedRecordlistView.Name =
"PassedRecordlistView";
this.PassedRecordlistView.Size =
new System.Drawing.Size(748, 499);
this.PassedRecordlistView.TabIndex = 0;
this.PassedRecordlistView.UseCompatibleStateImageBehavior =
false;
this.PassedRecordlistView.View = System.Windows.Forms.View.Details;
//
// columnHeader1
//
this.columnHeader1.Text =
"工号";
this.columnHeader1.Width = 80;
//
// columnHeader2
//
this.columnHeader2.Text =
"姓名";
this.columnHeader2.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
this.columnHeader2.Width = 80;
//
// columnHeader3
//
this.columnHeader3.Text =
"时间";
this.columnHeader3.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
this.columnHeader3.Width = 133;
//
// columnHeader4
//
this.columnHeader4.Text =
"卡号";
this.columnHeader4.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
this.columnHeader4.Width = 91;
//
// columnHeader5
//
this.columnHeader5.Text =
"状态";
this.columnHeader5.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
this.columnHeader5.Width = 127;
//
// columnHeader6
//
this.columnHeader6.Text =
"机器号";
this.columnHeader6.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
//
// columnHeader7
//
this.columnHeader7.Text =
"进出";
this.columnHeader7.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
//
// tabPage2
//
this.tabPage2.Location =
new System.Drawing.Point(4, 21);
this.tabPage2.Name =
"tabPage2";
this.tabPage2.Padding =
new System.Windows.Forms.Padding(3);
this.tabPage2.Size =
new System.Drawing.Size(754, 505);
this.tabPage2.TabIndex = 1;
this.tabPage2.Text =
"终端设备运行信息";
this.tabPage2.UseVisualStyleBackColor =
true;
//
// ListViewImageConnectingStatus
//
this.ListViewImageConnectingStatus.BackColor = System.Drawing.SystemColors.Control;
this.ListViewImageConnectingStatus.Dock = System.Windows.Forms.DockStyle.Top;
this.ListViewImageConnectingStatus.Location =
new System.Drawing.Point(0, 0);
this.ListViewImageConnectingStatus.Name =
"ListViewImageConnectingStatus";
this.ListViewImageConnectingStatus.Size =
new System.Drawing.Size(762, 55);
this.ListViewImageConnectingStatus.TabIndex = 1;
this.ListViewImageConnectingStatus.UseCompatibleStateImageBehavior =
false;
//
// timer1
//
this.timer1.Enabled =
true;
this.timer1.Interval = 1000;
this.timer1.Tick +=
new System.EventHandler(this.timer1_Tick);
//
// imageList1
//
this.imageList1.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imageList1.ImageStream")));
this.imageList1.TransparentColor = System.Drawing.Color.Transparent;
this.imageList1.Images.SetKeyName(0,
"");
this.imageList1.Images.SetKeyName(1,
"");
//
// MainForm
//
this.AutoScaleDimensions =
new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize =
new System.Drawing.Size(762, 585);
this.Controls.Add(this.tabControl1);
this.Controls.Add(this.ListViewImageConnectingStatus);
this.Name =
"MainForm";
this.Text =
"智能通道系统";
this.Load +=
new System.EventHandler(this.MainForm_Load);
this.FormClosing +=
new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing);
this.tabControl1.ResumeLayout(false);
this.tabPage1.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.TabControl tabControl1;
private System.Windows.Forms.TabPage tabPage1;
private System.Windows.Forms.ListView PassedRecordlistView;
private System.Windows.Forms.TabPage tabPage2;
private System.Windows.Forms.ListView ListViewImageConnectingStatus;
private System.Windows.Forms.Timer timer1;
private System.Windows.Forms.ImageList imageList1;
private System.Windows.Forms.ColumnHeader columnHeader1;
private System.Windows.Forms.ColumnHeader columnHeader2;
private System.Windows.Forms.ColumnHeader columnHeader3;
private System.Windows.Forms.ColumnHeader columnHeader4;
private System.Windows.Forms.ColumnHeader columnHeader5;
private System.Windows.Forms.ColumnHeader columnHeader6;
private System.Windows.Forms.ColumnHeader columnHeader7;
}
}
3.CardMachineCollection.cs:
//***********************************************************************************************
// 作者 :郑紫至
// 创建日期:2008-03-14
// 邮件地址:zhengzizhi@mail.china.com
// 博客地址:http://hi.youkuaiyun.com/zhengzizhi
// 备注说明:欢迎大家转载我的博客内容,代码版权归本人所有,请保留此信息。
//***********************************************************************************************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
namespace Server
{
public
class CardMachineCollection :
CollectionBase
{
public
CardMachine this[int index]
{
get {
return ((CardMachine)List[index]); }
set { List[index] =
value; }
}
public
int Add(CardMachine value)
{
return (List.Add(value));
}
public
void Remove(CardMachine value)
{
List.Remove(value);
}
}
}
4.CardMachine.cs:
//******************************************************************************************
// 作者 :郑紫至
// 创建日期:2008-03-14
// 邮件地址:zhengzizhi@mail.china.com
// 博客地址:http://hi.youkuaiyun.com/zhengzizhi
// 备注说明:欢迎大家转载我的博客内容,代码版权归本人所有,请保留此信息。
//******************************************************************************************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Data.SqlClient;
using System.Threading;
using System.Configuration;
using System.Data;
namespace Server
{
public
class CardMachine
{
///<summary>
///保存由服务器Accecpt方法返回的一个新创建的Socket对象
///</summary>
public
Socket SavedSocketOfNewlyConnected=null;
public
Thread ThreadOfServerIsWaitingForClientData;
public
SqlConnection SqlConn=null;
public
SqlCommand SqlComm=null;
///<summary>
/// ServerSocketIsActive默认为活动状态
///</summary>
public
bool ServerSocketIsActive = true;
///<summary>
///委托类型的事件
///</summary>
public
event DegReceiveData OnReceiveData;
public
delegate void
DegReceiveData(object sender,
string ReceiveString, int ReceiveStringLength,
byte[] ReceiveBytes);
private
int _ClientConnectedLifeTime = 0;
///<summary>
///卡机连接服务器的秒数( 默认为0 )
///</summary>
public
int ClientConnectedLifeTime
{
get {
return _ClientConnectedLifeTime; }
set { _ClientConnectedLifeTime =
value; }
}
private
int _ClientMachineNo = 0;
///<summary>
///卡机编号( 默认为0 )
///</summary>
public
int ClientMachineNo
{
get {
return _ClientMachineNo; }
set { _ClientMachineNo =
value; }
}
private
bool _ClientIsConnected = false;
///<summary>
///卡机连接状态( 默认为断开 )
///</summary>
public
bool ClientIsConnected
{
get {
return _ClientIsConnected; }
set { _ClientIsConnected =
value; }
}
private
string _ClientMachineIpAddress = string.Empty;
///<summary>
///卡机IP地址
///</summary>
public
string ClientMachineIpAddress
{
get {
return _ClientMachineIpAddress; }
set { _ClientMachineIpAddress =
value; }
}
///<summary>
///在已连接数据库的状态下,建立一个操作数据库存储过程的SqlCommand对象实例SqlComm,并定义存储过程中
///要使用的参数类型和长度,最后线程启动ServerIsWaitingForClientData()方法接收来自客户端发过来的字节数据
///</summary>
///<param name="SocketOfNewlyConnected">服务器Accecpt方法返回的新建Socket对象</param>
public CardMachine(Socket SocketOfNewlyConnected)
{
if (SocketOfNewlyConnected !=
null)//在执行窗体Load事件的时候会传null值过来,其它情况都是非null值
{
SqlConn =
new SqlConnection(ConfigurationManager.AppSettings["ConnectionString"]);
SqlConn.Open();
SqlComm =
new SqlCommand("dbo.[CheckDiningEmpInfoByCardNo]", SqlConn);
SqlComm.CommandType = System.Data.CommandType.StoredProcedure;
SqlComm.Connection = SqlConn;
SqlComm.Parameters.Add(new
SqlParameter("@RETURN_VALUE",
SqlDbType.Int, 4,
ParameterDirection.ReturnValue, false, (System.Byte)(0),
(System.Byte)(0),
"",DataRowVersion.Current,
null));
SqlComm.Parameters.Add(new
SqlParameter("@CardNo",
SqlDbType.VarChar, 10));
SqlComm.Parameters.Add(new
SqlParameter("@MachineNo",
SqlDbType.VarChar, 5));
SqlComm.Parameters.Add(new
SqlParameter("@ReadHeadNo",
SqlDbType.Int, 4));
SqlComm.Parameters.Add(new
SqlParameter("@EmpNo",
SqlDbType.VarChar, 8,
ParameterDirection.Output, false, (System.Byte)(0),
(System.Byte)(0),"",
DataRowVersion.Current,
null));
SqlComm.Parameters.Add(new
SqlParameter("@EmpName",
SqlDbType.NVarChar, 20,
ParameterDirection.Output, false, (System.Byte)(0),
(System.Byte)(0),"",
DataRowVersion.Current,
null));
SqlComm.Parameters.Add(new
SqlParameter("@CardPassingState",
SqlDbType.Int, 4,
ParameterDirection.Output, false, (System.Byte)(0),
(System.Byte)(0),"",
DataRowVersion.Current,
null));
//设置卡机连接服务器的状态为“已连接上”.
ClientIsConnected =
true;
//获取远程终结点(客户端卡机的IP和端口)中的IP地址
ClientMachineIpAddress =((IPEndPoint)(SocketOfNewlyConnected.RemoteEndPoint)).Address.ToString();
//保存服务器Accecpt方法返回的新建Socket对象到SavedSocketOfNewlyConnected变量中
SavedSocketOfNewlyConnected = SocketOfNewlyConnected;
//创建一个新线程准备执行ServerIsWaitingForClientData()方法
ThreadOfServerIsWaitingForClientData =
new Thread(new
ThreadStart(ServerIsWaitingForClientData));
//启动线程,开始执行ServerIsWaitingForClientData()方法
ThreadOfServerIsWaitingForClientData.Start();
}
}
///<summary>
///
///</summary>
public
void ServerIsWaitingForClientData()
{
//保存客户端发到服务器的字节数组
byte[] BytesOfClientToServer =
new byte[1024];
int MachineNo, ServerReceivedFromClientLengthOfBytes = 0;
try
{
// SavedSocketOfNewlyConnected会在MainForm的timer1_Tick事件中每隔70秒释放一次
while (ServerSocketIsActive && SavedSocketOfNewlyConnected !=
null)
{
//
使用SavedSocketOfNewlyConnected对象接收来自客户端Socket对象发过来的字节数据并
//
且将接收方法返回的字节长度数据保存到ServerReceivedFromClientLengthOfBytes变量中
ServerReceivedFromClientLengthOfBytes = SavedSocketOfNewlyConnected.Receive(BytesOfClientToServer);
//
定义一个将接收到的字节转换成字符串的变量
string ServerReceivedFromClientString =
string.Empty ;
//
将字节转换成字符串
ServerReceivedFromClientString +=
Encoding.ASCII.GetString(
BytesOfClientToServer, 0, ServerReceivedFromClientLengthOfBytes);
//
if (ServerReceivedFromClientString.Length == 11)
{
// 从第0位到第10位(长度为11)这段字符串中截取第1位和第2位表示卡机编号的字串
MachineNo =
Convert.ToInt32(ServerReceivedFromClientString.Substring(1, 2));
// MiddleListBox中显示一空行
MainForm.MiddleListBox.Items.Add("");
// MiddleListBox中显示的数据超过2000条,就删除索引为 1 的那条记录
if (MainForm.MiddleListBox.Items.Count > 2000) {
MainForm.MiddleListBox.Items.RemoveAt(1); };
// MiddleListBox中显示当前卡机完成一次完整的通讯结束信号
MainForm.MiddleListBox.Items.Add(DateTime.Now.ToString() +
" : 服务器已收到[ " +
MachineNo.ToString() +
" ]号卡机传回本次完整通讯结束的<EOF>信号");
// MiddleListBox中显示的数据超过2000条,就删除索引为 1 的那条记录
if (MainForm.MiddleListBox.Items.Count > 2000) {
MainForm.MiddleListBox.Items.RemoveAt(1); };
// 将当前卡机编号的连接状态图片设置为“已连接上”的图片;
MainForm.PictureBoxArray[MachineNo].Image = MainForm.ConnectedPictureBox.Image;
ClientConnectedLifeTime = 0;
}
if (ServerReceivedFromClientString.IndexOf("<EOF>") > -1)
{
break;//如果接收的字符串包含了“<EOF>”标记,退出以结束本次通讯
}
//接收字节长度大于 42 表示一次完整通讯客户端发过来真正有用的数据
if ((ServerReceivedFromClientLengthOfBytes > 42) && (OnReceiveData !=
null))
//
{ OnReceiveData(this, ServerReceivedFromClientString, ServerReceivedFromClientLengthOfBytes, BytesOfClientToServer); }
}
}
catch (Exception ex)
{
// MiddleListBox中显示ServerIsWaitingForClientData方法出现错误的时间
MainForm.MiddleListBox.Items.Add(DateTime.Now.ToString() +
" : ServerIsWaitingForClientData方法中的错误 " + ex.ToString());
// MiddleListBox中显示的数据超过2000条,就删除索引为 1 的那条记录
if (MainForm.MiddleListBox.Items.Count > 2000) {
MainForm.MiddleListBox.Items.RemoveAt(1); };
}
}
///<summary>
///设置ServerSocketIsActive为非活动状态;
///禁用SavedSocketOfNewlyConnected上的发送和接收并释放所有关联的资源;
///结束ThreadOfServerIsWaitingForClientData线程的执行。
///</summary>
public
void Close()
{
ServerSocketIsActive =
false;
try
{
if (SavedSocketOfNewlyConnected !=
null)
{
//(i)禁用SavedSocketOfNewlyConnected上的发送和接收
SavedSocketOfNewlyConnected.Shutdown(SocketShutdown.Both);
//(ii)关闭 SavedSocketOfNewlyConnected连接并释放所有关联的资源
SavedSocketOfNewlyConnected.Close();
//(iii)结束用来启动ServerIsWaitingForClientData()方法的线程
ThreadOfServerIsWaitingForClientData.Abort();
}
}
catch
{ }
}
}
}
5. app.config:
<?xmlversion="1.0"encoding="utf-8"
?>
<configuration>
<configSections>
</configSections>
<connectionStrings>
<addname="Server.Properties.Settings.IRSConnectionString"
connectionString=""
providerName="System.Data.SqlClient"
/>
</connectionStrings>
<appSettings>
<addkey="ConnectionString"value="Data
Source=VSNET2008/SQLEXPRESS;Initial Catalog=IRS;Integrated Security=True"/>
<addkey ="MachineCount"value="9"/>
<addkey ="MachineNo1"value="192.168.1.91"/>
<addkey ="MachineNo2"value="192.168.1.92"/>
<addkey ="MachineNo3"value="192.168.1.93"/>
<addkey ="MachineNo4"value="192.168.1.94"/>
<addkey ="MachineNo5"value="192.168.1.95"/>
<addkey ="MachineNo6"value="192.168.1.96"/>
<addkey ="MachineNo7"value="192.168.1.97"/>
<addkey ="MachineNo8"value="192.168.1.98"/>
<addkey ="MachineNo9"value="192.168.1.99"/>
</appSettings>
</configuration>
6. Program:
//***********************************************************************************************
// 作者 :郑紫至
// 创建日期:2008-03-14
// 邮件地址:zhengzizhi@mail.china.com
// 博客地址:http://hi.youkuaiyun.com/zhengzizhi
// 备注说明:欢迎大家转载我的博客内容,代码版权归本人所有,请保留此信息。
//***********************************************************************************************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace Server
{
static
class Program
{
///<summary>
/// The main entry point for the application.
///</summary>
[STAThread]
static
void Main()
{
Control.CheckForIllegalCrossThreadCalls =
false;
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new
MainForm());
}
}
}
Server项目所有代码全部发布完毕(包括自动生成的代码)
在整个方案中的结构如下图所显: