分享
 
 
 

Multithreading in .NET Applications

王朝vc·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

Multithreading in .NET Applications

创建高水平的应用程序,多线程是一个很好的设计工具,特别是那些要求与与用户互操作的程序。使用Microsoft.NET能很方便的创建这样的多线程应用程序。Part1和Part2两不部分探索了NET 的框架。在第一篇中,我们讨论了线程的背景知识,线程的优点,并提供了例子。 在第二篇中,我们讨论了多线程的工作机制,以及线程同步机制。在这篇文章中(多线程的最后一篇)我们来分析和使用System.Threading,System.Net两个名字空间。

网络编程基础

要是编写一个程序能回答网络请求,我们首先要了解网络组成,以及相应的技术。我不将全面的解释网络和网络的工作机制,相反,我将提供这些题目的基础知识。一些定义如下:

TCP/IP -这是计算机用来通信的一套协议,是路由协议,这就意味着如果你的目的地主机,如果不依赖它所在地网络的话,这个路由将保证你的通信能够正常进行。

Port-每一个基于TCP/IP协议的应用程序,都有一个唯一确定的端口。这个端口是应用程序用来通信的逻辑通道。一些端口被保留给协议使用,例如:如果你连接Web服务器,那么你将使用80端口,这端口是HTTP保留的。

Socket-一个socket就是两个应用程序的网络连接的一端。这是一种用来在同一台机器,或者网络中不同机器通信的一种机制。一个socket往往绑定在一个具体的Port上。

Listener Application

Listener Application也就是服务器程序,它打开网络端口,同时等待客户机的连接。这样的程序包括web 服务器,数据库服务器,e-mail服务器,chat服务器等等。Listener Application

l 一般都遵循以下算法:

l 能打开可以使用的端口。

l 通过端口可以等待客户端Socket的连接。

l 客户端通过Socket连接,提出请求或者连接服务。

l 服务器启动一些进程发送回答。

l 关闭客户端Socket连接。

Sample Listener Code Listing

下面的例子遵循上面提到的基本算法。它包括一个控制台应用程序,这个程序用来打开port同时等待客户的socket连接。在这里我们只是编写很简单的连接程序。一旦客户端连接上了,服务器将每隔几秒发送当前时间的数据给客户端。然后,这个listener将关闭连接,重新等待其他客户端的连接。

using System;

using System.Net;

using System.Net.Sockets;

using System.Text;

using System.Threading;

namespace CodeGuru.MultithreadedPart3

{

/// <remarks>

/// Example console application demonstrating a listener/server

/// application.

/// Waits for connections to be made and responds with a message.

/// </remarks>

class HelloWorldServer

{

/// <summary>

/// The main entry point for the application.

/// </summary>

[STAThread]

static void Main(string[] args)

{

try

{

DateTime now;

String dateStr;

// Choose a port other than 8080 if you have difficulty

TcpListener listener = new TcpListener(IPAddress.Loopback,

8080);

listener.Start();

Console.WriteLine("Waiting for clients to connect");

Console.WriteLine("Press Ctrl+c to Quit...");

while(true)

{

// Accept blocks until a client connects

Socket clientSocket = listener.AcceptSocket();

for( int i = 0; i < 10; i++ )

{

// Get the current date and time then build a

// Byte Array to send

now = DateTime.Now;

dateStr = now.ToShortDateString() + " "

+ now.ToLongTimeString();

Byte[] byteDateLine = Encoding.ASCII.GetBytes(

dateStr.ToCharArray());

// Send the data

clientSocket.Send(byteDateLine, byteDateLine.Length, 0);

Thread.Sleep(1000);

Console.WriteLine("Sent {0}", dateStr);

}

clientSocket.Close();

}

}

catch( SocketException socketEx )

{

Console.WriteLine("Socket error: {0}", socketEx.Message);

}

}

}

}

Sample Client Code Listing

下面的代码将连接服务器,同时显示服务器发送过来的数据。

using System;

using System.IO;

using System.Net;

using System.Net.Sockets;

using System.Text;

namespace CodeGuru.MultithreadedPart3

{

/// <remarks>

/// Example console application demonstrating a client

/// application.

/// Makes a connection to the server and displays the response.

/// </remarks>

class HelloWorldClient

{

/// <summary>

/// The main entry point for the application.

/// </summary>

[STAThread]

static void Main(string[] args)

{

bool isDone = false;

Byte[] read = new Byte[32];

TcpClient client = new TcpClient("localhost", 8080);

// Get the stream to read the input

Stream s;

try

{

s = client.GetStream();

}

catch( InvalidOperationException )

{

Console.WriteLine("Cannot connect to localhost");

return;

}

// Read the stream and convert it to ASII

while( !isDone )

{

int numBytes = s.Read(read, 0, read.Length);

String data = Encoding.ASCII.GetString(read);

if( numBytes == 0 )

{

isDone = true;

}

else

{

Console.WriteLine("Received {0} bytes: {1}",

numBytes, data);

}

}

client.Close();

}

}

}

Testing the Listener Using the Client

把服务器程序和客户端程序copy到不同的位置,独立编译。打开控制台来运行服务器程序,同时打开另外一个控制台来运行客户端程序,你将看到类似以下的结果。

图: 1—Listener

图 2—Client

我们再次执行一个客户端程序,打开第三个控制台,再次执行客户端程序,你将看到这两个客户端程序只有一个能从服务器上接受到数据。另外一个在等待服务器的应答。一旦第一个客户端程序完成,第二个将接到服务器的应答。

Multithreaded Listener Application

上面的例子的问题是服务器只能在一个时刻建立一个连接。这也许在我们这个date/time例子已经足够了,但是对于其他服务器程序例如Web服务器,这是远远不行的。由于服务器的程序是单线程的,因此,它只能应答一个客户端的响应。为了应答多个客户程序同时的请求。我们必须创建不同的多个线程来处理每个请求。

Sample Listener Code Listing

下面是代码修改类前面的服务器程序,这样,它可以同时应答多个请求。在这里,我们创建一个新的线程来应答新的客户端的请求。每个客户端socket将被分配给新的HelloWorldServer实例。这样,客户端请求将可以被新线程处理。

using System;

using System.Net;

using System.Net.Sockets;

using System.Text;

using System.Threading;

namespace CodeGuru.MultithreadedPart3

{

/// <remarks>

/// Example console application demonstrating a listener/server

/// application.

/// Waits for connections to be made and responds with a message.

/// </remarks>

class HelloWorldServer

{

// Socket to use to accept client connections

private Socket _socket;

/// <summary>

/// The main entry point for the application.

/// </summary>

[STAThread]

static void Main(string[] args)

{

try

{

TcpListener listener = new TcpListener(

IPAddress.Loopback, 8080);

listener.Start();

Console.WriteLine("Waiting for clients to connect");

Console.WriteLine("Press Ctrl+c to Quit...");

while(true)

{

// Accept blocks until a client connects

HelloWorldServer hwServer = new HelloWorldServer();

hwServer._socket = listener.AcceptSocket();

// Process the client connection on a new thread

Thread sampleThread = new Thread(new ThreadStart(

hwServer.Process));

sampleThread.Start();

}

}

catch( SocketException socketEx )

{

Console.WriteLine("Socket error: {0}", socketEx.Message);

}

}

/*

* Get the current date and time and send it to the client.

* Requires that a socket is created and connected to a client.

* Closes the socket when complete.

*/

private void Process()

{

DateTime now;

String dateStr;

for( int i = 0; i < 10; i++ )

{

// Get the current date and time then concatenate build

// a Byte Array to send

now = DateTime.Now;

dateStr = now.ToShortDateString() + " "

+ now.ToLongTimeString();

Byte[] byteDateLine = Encoding.ASCII.GetBytes(

dateStr.ToCharArray());

// Send the data

this._socket.Send(byteDateLine, byteDateLine.Length, 0);

Thread.Sleep(1000);

Console.WriteLine("Sent {0}", dateStr);

}

this._socket.Close();

}

}

}

Testing the Multithreaded Listener Using the Client拷贝更新了的服务器程序代码到适当的位置,并重编译。从控制台运行服务器程序。从多个不同的控制台运行多个客户端程序,你将注意到客户端程序都能接到服务器的响应。

Possible Enhancements

上面的例子包括一个简单的服务器程序和客户端程序,你可以使用他们来作为熟悉System.net名字空间的开始。此外,你可以做以下的扩展工作:

扩展客户端程序来发送具体工作的请求。更改服务器程序来应答不同的具体工作请求。例如:

l 客户端可以发送”DATATIME”的数据作为请求,同时服务器用date和time来应答。

l 不使用控制台作为服务器,而使用windows 服务器,这样,可以自动启动,和后台运行。

About the Author

Mark Strawmyer, MCSD, MCSE (NT4/W2K), MCDBA is a Senior Architect of .NET applications for large- and mid-size organizations. Mark is a technology leader with Crowe Chizek in Indianapolis, Indiana. He specializes in the architecture, design, and development of Microsoft-based solutions. You can reach Mark at mstrawmyer@crowechizek.com.

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有