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#诸多优秀的特性中,委托,多线程和跨线程回调在网络应用中用得最多。
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内的代码基本相同,从而导致代码冗余。这两个问题可以分别通过多线程和委托解决。
当今程序语言普遍支持的方法(函数)调用机制是结构化编程时代的产物,而结构化是适应面向过程发展起来的编程方式,故程序中的方法(函数)体也是对操作过程的封装,但是如今的面向对象的程序设计方法要求我们设计一种不同于传统方法的全新的代码封装机制(将程序的方法作为一个函数传递)。
用委托实现文字抄写员程序:
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 DelegateForm : Form
{
private delegate void WriteTextBox(char ch);
private WriteTextBox writeTextBox;
public DelegateForm()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
if(checkBox1.Checked==true)
{
Process1.Text = "运行中";
Process1.Refresh();
textBox1.Clear();
textBox1.Refresh();
writeTextBox = new WriteTextBox(WriTextToBox1);
wriTextForBoxAndBox2(writeTextBox);
Process1.Text = "任务1";
}
if(checkBox2.Checked==true)
{
Process2.Text = "运行中";
Process2.Refresh();
textBox2.Clear();
textBox2.Refresh();
writeTextBox = new WriteTextBox(WriTextToBox2);
wriTextForBoxAndBox2(writeTextBox);
Process2.Text = "任务2";
}
}
private void wriTextForBoxAndBox2(WriteTextBox writeMethod)
{
string strData = textBox3.Text;
for (int i = 0; i < strData.Length;i++)
{
writeMethod(strData[i]);
DateTime now = DateTime.Now;
while(now.AddSeconds(1)>DateTime.Now){}
}
}
private void WriTextToBox1(char ch)
{
textBox1.AppendText(ch+"\r");
}
private void WriTextToBox2(char ch)
{
textBox2.AppendText(ch+"\r");
}
}
}
由于运行效果与不使用委托相同,只是减少了代码冗余,因此不再演示。
https://www.cnblogs.com/MenAngel/p/6740996.html