C#网络编程初探.docx
《C#网络编程初探.docx》由会员分享,可在线阅读,更多相关《C#网络编程初探.docx(13页珍藏版)》请在冰豆网上搜索。
C#网络编程初探
C#网络编程初探1
作者:
马金虎·yesky
2002-6-2021:
20:
39
[被查看:
3093次] (推荐作品)
我们知道C#和C++的差异之一,就是他本身没有类库,所使用的类库是.Net框架中的类库--.NetFrameWorkSDK。
在.NetFrameWorkSDK中为网络编程提供了二个名称空间:
"System.Net"和"System.Net.Sockets"。
C#就是通过这二个名称空间中封装的类和方法实现网络通讯的。
首先我们解释一下在网络编程时候,经常遇到的几个概念:
同步(synchronous)、异步(asynchronous)、阻塞(Block)和非阻塞(Unblock):
所谓同步方式,就是发送方发送数据包以后,不等接受方响应,就接着发送下一个数据包。
异步方式就是当发送方发送一个数据包以后,一直等到接受方响应后,才接着发送下一个数据包。
而阻塞套接字是指执行此套接字的网络调用时,直到调用成功才返回,否则此套节字就一直阻塞在网络调用上,比如调用StreamReader类的Readlin()方法读取网络缓冲区中的数据,如果调用的时候没有数据到达,那么此Readlin()方法将一直挂在调用上,直到读到一些数据,此函数调用才返回;而非阻塞套接字是指在执行此套接字的网络调用时,不管是否执行成功,都立即返回。
同样调用StreamReader类的Readlin()方法读取网络缓冲区中数据,不管是否读到数据都立即返回,而不会一直挂在此函数调用上。
在Windows网络通信软件开发中,最为常用的方法就是异步非阻塞套接字。
平常所说的C/S(客户端/服务器)结构的软件采用的方式就是异步非阻塞模式的。
其实在用C#进行网络编程中,我们并不需要了解什么同步、异步、阻塞和非阻塞的原理和工作机制,因为在.NetFrameWrokSDK中已经已经把这些机制给封装好了。
下面我们就用C#开一个具体的网络程序来说明一下问题。
一.本文中介绍的程序设计及运行环境
(1).微软视窗2000服务器版
(2)..NetFrameworkSDKBeta2以上版本
二.服务器端程序设计的关键步骤以及解决办法:
在下面接受的程序中,我们采用的是异步阻塞的方式。
(1).首先要要在给定的端口上面创建一个"tcpListener"对象侦听网络上面的请求。
当接收到连结请求后通过调用"tcpListener"对象的"AcceptSocket"方法产生一个用于处理接入连接请求的Socket的实例。
下面是具体实现代码:
//创建一个tcpListener对象,此对象主要是对给定端口进行侦听
tcpListener=newTcpListener(1234);
//开始侦听
tcpListener.Start();
//返回可以用以处理连接的Socket实例
socketForClient=tcpListener.AcceptSocket();
(2).接受和发送客户端数据:
此时Socket实例已经产生,如果网络上有请求,在请求通过以后,Socket实例构造一个"NetworkStream"对象,"NetworkStream"对象为网络访问提供了基础数据流。
我们通过名称空间"System.IO"中封装的二个类"StreamReader"和"StreamWriter"来实现对"NetworkStream"对象的访问。
其中"StreamReader"类中的ReadLine()方法就是从"NetworkStream"对象中读取一行字符;"StreamWriter"类中的WriteLine()方法就是对"NetworkStream"对象中写入一行字符串。
从而实现在网络上面传输字符串,下面是具体的实现代码:
try
{
//如果返回值是"true",则产生的套节字已经接受来自远方的连接请求
if(socketForClient.Connected)
{
ListBox1.Items.Add("已经和客户端成功连接!
");
while(true)
{
//创建networkStream对象通过网络套节字来接受和发送数据
networkStream=newNetworkStream(socketForClient);
//从当前数据流中读取一行字符,返回值是字符串
streamReader=newStreamReader(networkStream);
stringmsg=streamReader.ReadLine();
ListBox1.Items.Add("收到客户端信息:
"+msg);
streamWriter=newStreamWriter(networkStream);
if(textBox1.Text!
="")
{
ListBox1.Items.Add("往客户端反馈信息:
"+textBox1.Text);
//往当前的数据流中写入一行字符串
streamWriter.WriteLine(textBox1.Text);
//刷新当前数据流中的数据
streamWriter.Flush();
}
}
}
}
catch(Exceptioney)
{
MessageBox.Show(ey.ToString());
}
(3).最后别忘了要关闭所以流,停止侦听网络,关闭套节字,具体如下:
//关闭线程和流
networkStream.Close();
streamReader.Close();
streamWriter.Close();
_thread1.Abort();
tcpListener.Stop();
socketForClient.Shutdown(SocketShutdown.Both);
socketForClient.Close();
本帖子版权属于原作者所有,转载请与原作者联系并注明出处-DotNET中文技术网
C#网络编程初探2
作者:
马金虎·yesky
2002-6-2021:
21:
05
[被查看:
1632次] (推荐作品)
三.C#网络编程服务器端程序的部分源代码(server.cs):
由于在此次程序中我们采用的结构是异步阻塞方式,所以在实际的程序中,为了不影响服务器端程序的运行速度,我们在程序中设计了一个线程,使得对网络请求侦听,接受和发送数据都在线程中处理,请在下面的代码中注意这一点,下面是server.cs的完整代码:
usingSystem;
usingSystem.Drawing;
usingSystem.Collections;
usingSystem.ComponentModel;
usingSystem.Windows.Forms;
usingSystem.Data;
usingSystem.Net.Sockets;
usingSystem.IO;
usingSystem.Threading;
usingSystem.Net;
//导入程序中使用到的名字空间
publicclassForm1:
Form
{
privateListBoxListBox1;
privateButtonbutton2;
privateLabellabel1;
privateTextBoxtextBox1;
privateButtonbutton1;
privateSocketsocketForClient;
privateNetworkStreamnetworkStream;
privateTcpListenertcpListener;
privateStreamWriterstreamWriter;
privateStreamReaderstreamReader;
privateThread_thread1;
privateSystem.ComponentModel.Containercomponents=null;
publicForm1()
{
InitializeComponent();
}
//清除程序中使用的各种资源
protectedoverridevoidDispose(booldisposing)
{
if(disposing)
{
if(components!
=null)
{
components.Dispose();
}
}
base.Dispose(disposing);
}
privatevoidInitializeComponent()
{
label1=newLabel();
button2=newButton();
button1=newButton();
ListBox1=newListBox();
textBox1=newTextBox();
SuspendLayout();
label1.Location=newPoint(8,168);
label1.Name="label1";
label1.Size=newSize(120,23);
label1.TabIndex=3;
label1.Text="往客户端反馈信息:
";
//同样的方式设置其他控件,这里略去
this.Controls.Add(button1);
this.Controls.Add(textBox1);
this.Controls.Add(label1);
this.Controls.Add(button2);
this.Controls.Add(ListBox1);
this.MaximizeBox=false;
this.MinimizeBox=false;
this.Name="Form1";
this.Text="C#的网络编程服务器端!
";
this.Closed+=newSystem.EventHandler(this.Form1_Closed);
this.ResumeLayout(false);
}
privatevoidListen()
{
//创建一个tcpListener对象,此对象主要是对给定端口进行侦听
tcpListener=newTcpListener(1234);
//开始侦听
tcpListener.Start();
//返回可以用以处理连接的Socket实例
socketForClient=tcpListener.AcceptSocket();
try
{
//如果返回值是"true",则产生的套节字已经接受来自远方的连接请求
if(socketForClient.Connected)
{
ListBox1.Items.Add("已经和客户端成功连接!
");
while(true)
{
//创建networkStream对象通过网络套节字来接受和发送数据
networkStream=newNetworkStream(socketForClient);
//从当前数据流中读取一行字符,返回值是字符串
streamReader=newStreamReader(networkStream);
stringmsg=streamReader.ReadLine();
ListBox1.Items.Add("收到客户端信息:
"+msg);
streamWriter=newStreamWriter(networkStream);
if(textBox1.Text!
="")
{
ListBox1.Items.Add("往客户端反馈信息:
"+textBox1.Text);
//往当前的数据流中写入一行字符串
streamWriter.WriteLine(textBox1.Text);
//刷新当前数据流中的数据
streamWriter.Flush();
}
}
}
}
catch(Exceptioney)
{
MessageBox.Show(ey.ToString());
}
}
staticvoidMain()
{
Application.Run(newForm1());
}
privatevoidbutton1_Click(objectsender,System.EventArgse)
{
ListBox1.Items.Add("服务已经启动!
");
_thread1=newThread(newThreadStart(Listen));
_thread1.Start();
}
privatevoidbutton2_Click(objectsender,System.EventArgse)
{
//关闭线程和流
networkStream.Close();
streamReader.Close();
streamWriter.Close();
_thread1.Abort();
tcpListener.Stop();
socketForClient.Shutdown(SocketShutdown.Both);
socketForClient.Close();
}
privatevoidForm1_Closed(objectsender,System.EventArgse)
{
//关闭线程和流
networkStream.Close();
streamReader.Close();
streamWriter.Close();
_thread1.Abort();
tcpListener.Stop();
socketForClient.Shutdown(SocketShutdown.Both);
socketForClient.Close();
}
}
本帖子版权属于原作者所有,转载请与原作者联系并注明出处-DotNET中文技术网
C#网络编程初探3
作者:
马金虎·yesky
2002-6-2021:
21:
37
[被查看:
1397次] (推荐作品)
四.客户端程序设计的关键步骤以及解决办法:
(1).连接到服务器端的指定端口:
我们采用的本地机既做服务器也做客户机,你可以通过修改IP地址来确定自己想要连接的服务器。
我们在连接的时候采用了"TcpClient"类,此类是在较高的抽象级别(高于Socket类)上面提供TCP服务。
下面代码就是连接到本地机(端口为1234),并获取响应流:
//连接到服务器端口,在这里是选用本地机器作为服务器,你可以通过修改IP地址来改变服务器
try
{
myclient=newTcpClient("localhost",1234);
}
catch
{
MessageBox.Show("没有连接到服务器!
");
return;
}
//创建networkStream对象通过网络套节字来接受和发送数据
networkStream=myclient.GetStream();
streamReader=newStreamReader(networkStream);
streamWriter=newStreamWriter(networkStream);
(2).实现接受和发送数据:
在接受和发送数据上面,我们依然采用了"NetworkStream"类,因为对他进行操作比较简单,具体实现发送和接受还是通过命名空间"System.IO"中"StreamReader"类ReadLine()方法和"StreamWriter"类的WriteLine()方法。
具体的实现方法如下:
if(textBox1.Text=="")
{
MessageBox.Show("请确定文本框为非空!
");
textBox1.Focus();
return;
}
try
{
strings;
//往当前的数据流中写入一行字符串
streamWriter.WriteLine(textBox1.Text);
//刷新当前数据流中的数据
streamWriter.Flush();
//从当前数据流中读取一行字符,返回值是字符串
s=streamReader.ReadLine();
ListBox1.Items.Add("读取服务器端发送内容:
"+s);
}
catch(Exceptionee)
{
MessageBox.Show("从服务器端读取数据出现错误,类型为:
"+ee.ToString());
}
(3).最后一步和服务器端是一样的,就是要关闭程序中创建的流,具体如下:
streamReader.Close();
streamWriter.Close();
networkStream.Close();
本帖子版权属于原作者所有,转载请与原作者联系并注明出处-DotNET中文技术网
C#网络编程初探4
作者:
马金虎·yesky
2002-6-2021:
21:
46
[被查看:
1539次] (推荐作品)
五.客户端的部分代码:
由于在客户端不需要侦听网络,所以在调用上面没有程序阻塞情况,所以在下面的代码中,我们没有使用到线程,这是和服务器端程序的一个区别的地方。
总结上面的这些关键步骤,可以得到一个用C#网络编程完整的客户端程序(client.cs),具体如下:
usingSystem;
usingSystem.Drawing;
usingSystem.Collections;
usingSystem.ComponentModel;
usingSystem.Windows.Forms;
usingSystem.Data;
usingSystem.Net.Sockets;
usingSystem.IO;
usingSystem.Threading;
//导入程序中使用到的名字空间
publicclassForm1:
Form
{
privateListBoxListBox1;
privateLabellabel1;
privateTextBoxtextBox1;
privateButtonbutton3;
privateNetworkStreamnetworkStream;
privateStreamReaderstreamReader;
privateStreamWriterstreamWriter;
TcpClientmyclient;
privateLabellabel2;
privateSystem.ComponentModel.Containercomponents=null;
publicForm1()
{
InitializeComponent();
}
//清除程序中使用的各种资源
protectedoverridevoidDispose(booldisposing)
{
if(disposing)
{
if(components!
=null)
{
components.Dispose();
}
}
base.Dispose(disposing);
}
privatevoidInitializeComponent()
{
label1=newLabel();
button3=newButton();
ListBox1=newListBox();
textBox1=newTextBox();
label2=newLabel();
SuspendLayout();
label1.Location=newPoint(8,168);
label1.Name="label1";
label1.Size=newSize(56,23);
label1.TabIndex=3;
label1.Text="信息:
";
//同样方法设置其他控件
AutoScaleBaseSize=newSize(6,14);
ClientSize=newSize(424,205);
this.Controls.Add(button3);
this.Controls.Add(textBox1);
this.Controls.Add(label1);
this.Controls.Add(label2);
this.Controls.Add(ListBox1);
this.MaximizeBox=false;
this.MinimizeBox=false;
this.Name="Form1";
this.Text="C#的网络编程客户器端!
";
this.Closed+=newSystem.EventHandler(this.Form1_Closed);
this.ResumeLayout(false);
//连接到服务器端口,在这里是选用本地机器作为服务器,你可以通过修改IP地址来改变服务器
try
{
myclient=newTcpClient("localhost",1234);
}
catch
{
MessageBox.Show("没有连接到服务器!
");
return;
}
//创建networkStream对象通过网络套节字来接受和发送数据
networkStream=myclient.G