C#网络程序设计(1)网络编程常识与C#常用特性
网络程序设计能够帮我们了解联网应用的底层通信原理!
一、网络编程常识:
1、什么是网络编程
只有主要实现进程(线程)相互通信和基本的网络应用原理性(协议)功能的程序,才能算是真正的网络编程。
2、网络编程的层次
现实中的互联网是按照"TCP/IP分层协议栈"的体系结构构建的,因此程序员必须搞清楚自己要做的是哪个层次上的编程工作,TCP/IP协议体系的实现情况:
其中,网络接口层已经被大多数计算机生产厂家集成在了主板上,也就是经常所说的网卡(NIC)。windows操作系统内核中就集成了TCP/IP协议的实现。TCP/IP协议的核心部分是传输层协议(TCP/UDP)、网际层协议(IP)。应用程序通过编程界面(即程序员界面)与内核打交道。
3、编程界面的两种形式
一种室内和直接提供的系统调用,在windows下表现为Windows API函数;另一种是以程序库的方式提供的各种函数和类。MFC就是微软用C++语言对windows API进行面向对象封装后形成的功能强大的类库。前者在核内实现,后者在核外实现。TCP/IP网络环境下的应用程序是通过网络应用编程界面(套接字Socket)实现的。用VC一般是使用MFC封装好的Socket类,而在C#和.NET中可以实现两种编程界面。
二、网络程序的工作机制:
网络程序与传统单机程序的区别在于它能够与网络上其他计算机(主机)中的程序互通信息。
1、Socket基本介绍:
网络上计算机之间的通信实际上是计算机上进程之间的通信。为了标志通信的进程,首先要标志进程所在的主机,其次要标志主机上不同的进程。 在互联网上使用IP地址来标识不同的主机,在网络协议中使用端口号来识别不同的进程。为了唯一地标志网络中的一个进程要使用如下的二元组:
(IP地址,端口号)
这个二元组可以看做是网络进程地址。它是编程界面呈现给骑上应用程序的"插口",可以看成是两个网络应用进程在通信时,各自通信连接中的一个端点。当进行进城之间的通信时,其中一个程序将要传输的一段信息写入它所在主机的Socket中,该Socket通过与网络接口卡(Network Interface Cards,NIC)相连的传输介质将这段信息发往另一台主机的Socket中。使这段信息能够被其他程序使用:
2、套接字的类型
为了满足不同程序对通信质量和性能的要求,一般的网络系统都提供了一下3种不同类型的套接字,以供用户在设计程序时根据不同需要:
流式套接字(SOCKET_STREAM):提供了一种可靠的,面向连接的双向数据传输服务。实现数据无差错、无重复的发送,内设流量控制,被控制的数据被看成无记录边界的字节流。在TCP/IP协议簇中,使用TCP实现字节流的传输,当用户要发送大量数据,或对数据传输的可靠性有较高要求时使用流式套接字。
数据包套接字(SOCKET_DGRAM):提供了一种无连接,不可靠的双向数据传输服务。数据以独立的包形式被发送,并且保留了记录边界,不提供可靠性保证。数据在传输过程中可能会被丢失或重复,并且不能保证在接收端数据按发送顺序接收。在TCP/IP协议簇中,使用UDP实现数据报套接字。
原始套接字(SOCKET_RAW):该套接字允许对较低底层协议(如IP/ICMP)进行直接访问。一般用于对TCP/IP核心协议的网络编程。
在windows系统下,套接字WinSock屏蔽了下面TCP/IP协议栈的复杂性,使得在网络编程者看来,两个程序之间的通信实质就是它们各自绑定的套接字之间的通信。
三、C#网络编程常用特性:
在C#诸多优秀的特性中,委托,多线程和跨线程回调在网络应用中用得最多。
1、委托
C#的委托相当于C/C++中的函数指针。函数指针用于获得一个函数的入口地址,实现对函数的操作。委托与C/C++中函数指针的不同之处是:委托是面向对象的,类型安全的和保险的,是引用类型,因此对委托的使用要"先定义,后声明,接着实例化,最后作为参数传递给方法,最后才能使用"。定义委托使用关键字delegate。
1.定义
delegate void MyDelegate(type1 para1,type2 para2 ......);
2.声明
MyDelegate mydelegate;
3.实例化
mydelegate=new MyDelegate(obj.InstanceMethod);
4.作为参数传递
SomeMethod(mydelegate);
方法InstanceMethod的定义
private void InstanceMethod(type1 para1,type2 para2......)
{
//方法体,操作参数
}
5.在代码中使用
private void SomeMethod(MyDelegate mydelgate)
{
mydelegate(arg1,arg2......);
}
注意:委托机制实际上是通过委托实现对方法的动态调用。
但调用还必须有一个前提条件:方法InstanceMethod有参数且和MyDelegate的参数一致,
并且返回类型相同。委托的实例化中的参数既可以是实例方法,也可以是静态方法。
若实例化委托的语句与作为参数的方法位于一个类中,则可以省略对象名引用,直接用方法名实例化委托。
为什么要使用委托:
在接下来的讨论中,均用文字抄写员程序讲解这三个特性:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace text01_Delegate
{
public partial class TraditionalForm : Form
{
public TraditionalForm()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
if (checkBox1.Checked == true)
{
Process1.Text = "运行中......";
Process1.Refresh();//强制该控件重绘自己及其子控件
textBox1.Clear();
textBox1.Refresh();
this.WriteTextToBox1();
Process1.Text = "任务1";
}
if (checkBox2.Checked == true)
{
Process2.Text = "运行中......";
Process2.Refresh();
textBox2.Clear();
textBox2.Refresh();
this.WriteTextToBox2();
Process2.Text = "任务2";
}
}
private void WriteTextToBox1()
{
string strData = textBox3.Text;
for (int i = 0; i < strData.Length;i++ )
{
textBox1.AppendText(strData[i]+"\r");
DateTime now = DateTime.Now;
while(now.AddSeconds(1)>DateTime.Now){}
}
}
private void WriteTextToBox2()
{
string strData = textBox3.Text;
for (int i = 0; i < strData.Length;i++ )
{
textBox2.AppendText(strData[i]+"\r");
DateTime now = DateTime.Now;
while (now.AddSeconds(1) > DateTime.Now) { }
}
}
}
}
这是一个用传统方法编写的程序,当勾选两个复选框时实现将文本框中的文字依次填到文本区1和文本区2。但此程序存在两个问题:无法实现两个文本区域内容的同时书写;由于书写到文本框1和2内的代码基本相同,从而导致代码冗余。这两个问题可以分别通过多线程和委托解决。
下一篇: 秋天来了,那西北立秋吃啥传统食物最好