ASP.NET相关

1、委托:把一个方法当作参数传到另一个方法中

扩展方法:1、静态类 2、静态方法 3、this关键字

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 委托
{
    //扩展方法的三大步
    //1、静态类 2、静态方法 3、this 关键字
    public static class MyListExit
    {
        //this List<string> list 表示需要扩展方法的类型,即:给list<string>类型扩展一个MyWhere方法
        //Func<string,bool> funcWhere 传入的参数是一个泛型方法
        public static List<string> MyWhere(this List<string> list, Func<string, bool> funcWhere)
        {
            List<string> result = new List<string>();
            //遍历集合list,返回的也是一个集合
            foreach (var item in list)
            {
                if (funcWhere(item))
                {
                    result.Add(item);
                }
            }
            return result;
        }
    }
}

2、父窗体与子窗体间传值

1)、(委托方式)

i、在父窗体内定义一个无返回值且有一个字符串类型参数的委托

//定义发布消息委托
public Action<string> AfterMsgSend { get;set;}

ii、在子窗体内写一个传入参数为字符串类型的方法SetText作用是设置子窗体文本框的Text属性

public void SetText(string str)
        {
            tbMsg.Text = str;
        }

iii、在父窗体的Load事件中,创建子窗体对象,然后将子窗体的SetText方法追加到委托AfterMsgSend里面,然后调用子窗体Show方法,打开子窗体

private void ParentFrm_Load(object sender, EventArgs e)
        {
            ChildFrm frm = new ChildFrm();
            AfterMsgSend += frm.SetText;
            frm.Show();
        }

iiii、在父窗体的按钮单击事件中,先判断委托AfterMsgSend是否为空,如果为空则直接return,否则就调用委托函数

 

 private void btSendMsg_Click(object sender, EventArgs e)
        {
            //委托传值
            if (AfterMsgSend == null)
            {
                return;
            }
            AfterMsgSend(this.tbMsg.Text);
        }

 

2)、(事件方式)

 i、在父窗体内定义一个发布消息的事件AfterMsgChangedEvent

//定义一个发布消息事件
public event EventHandler AfterMsgChangedEvent;

ii、在父窗体的按钮点击事件中触发事件

 //触发事件
AfterMsgChangedEvent(this,new EventArgs());

iii、EventArgs不能传递参数,而我们需要给子窗体传递参数,所以我们需要自己写一个继承自EventArgs的子类TextBoxMsgChangeEventArg

public class TextBoxMsgChangeEventArg:EventArgs
    {
        public string Text { get; set; }
    }

iiii、父窗体的触发事件就应该变成

//触发事件
AfterMsgChangedEvent(this, new TextBoxMsgChangeEventArg() { Text = this.tbMsg.Text });

iiiii、在子窗体创建一个满足AfterMsgChangedEvent事件类型的方法

public  void AfterFrmMsgChange(object sender, EventArgs e)
        {
            TextBoxMsgChangeEventArg arg = e as TextBoxMsgChangeEventArg;
            SetText(arg.Text);
        }

iiiiii、在父窗体中创建子窗体的对象,在打开之前将子窗体的AfterFrmMsgChange方法绑定到父窗体的AfterMsgChangedEvent事件上

private void ParentFrm_Load(object sender, EventArgs e)
        {
            ChildFrm frm = new ChildFrm();
            AfterMsgChangedEvent += frm.AfterFrmMsgChange;
            frm.Show();
        }

3、发布订阅模式和观察者模式

i、写一个用来传递参数的接口Ifrmable

public interface Ifrmable
    {
        void SetText(string str);
    }

ii、父窗体中创建一个Ifrmable类型的集合

public List<Ifrmable> list { get; set; }

iii、父窗体按钮单击事件中给子窗体的接口方法传值

private void btSend_Click(object sender, EventArgs e)
        {
            if (list == null)
            {
                return;
            }
            foreach (var item in list)
            {
                item.SetText(this.tbSend.Text);

            }
        }

iiii、子窗体中实现接口方法

public partial class FrmChild : Form,Ifrmable
    {
        public FrmChild()
        {
            InitializeComponent();
        }
        public void SetText(string str)
        {
            this.tbSend.Text = str;
        }
    }

iiiii、父窗体load事件中初始化子窗体对象

private void FrmFather_Load(object sender, EventArgs e)
        {
            FrmFather ff = new FrmFather();
            FrmChild fc = new FrmChild();
            ff.list = new List<Ifrmable>();
            ff.list.Add(fc);
            ff.Show();
            fc.Show();
        }

 5、多线程

进程:操作系统分配资源的最小单位,可以理解为一个小模块小程序

线程:一个线程就是一个进程里面的代码的执行流。每个线程都要指向一个方法体,方法执行完之后,线程就释放

线程默认是前台线程,一个进程结束的标志是所有前台线程都结束之后。

static void Main(string[] args)
        {
            //创建一个线程
            Thread th = new Thread(delegate()
            {
                while (true)
                {
                    Console.WriteLine(DateTime.Now);
                    Thread.Sleep(1000);
                }
            });

            th.IsBackground = true;//线程默认是前台线程,一个进程结束的标志是所有前台线程都结束之后。

            th.Priority = ThreadPriority.Normal;//后台线程不会组塞 进程的退出

            th.Start();//告诉操作系统线程准备就绪

            th.Join(100000);//等待th执行完成

            th.Abort();//不得已才能使用,直接终止线程

        }

避免非子线程调用主线程创建的控件的时候报错的办法就是不检查是否存在跨线程调用

public Form1()
        {
            InitializeComponent();
            Control.CheckForIllegalCrossThreadCalls = false;  //这种方式不用在正式的项目中
        }

在正式的项目中解决跨线程报错的问题应该像下面这样写

Thread th = new Thread(delegate() {
                if (btSendMsg.InvokeRequired)//InvokeRequired:如果是别的线程创建的此控件
                {
                    btSendMsg.Invoke(new Action<string>(s =>
                    {
                        this.tbMsg.Text = s;
                    }), DateTime.Now.ToString());
                }
                else
                {
                    tbMsg.Text = DateTime.Now.ToString();
                }
            });

 双色球案例

public partial class WinFrmDoubleColorBall : Form
    {
        private List<Label> lbList = new List<Label>();
        private bool isRunning = false;
        public WinFrmDoubleColorBall()
        {
            InitializeComponent();
            //Control.CheckForIllegalCrossThreadCalls = false;
        }

        private void WinFrmDoubleColorBall_Load(object sender, EventArgs e)
        {
            for (int i = 0; i < 6; i++)
            {
                Label lb = new Label();
                lb.Text = "0";
                lb.AutoSize = true;

                lb.Location = new Point(50 * i + 50, 100);
                this.Controls.Add(lb);
                lbList.Add(lb);
            }
        }
        
        private void btStart_Click(object sender, EventArgs e)
        {
            isRunning = true;
            Thread th = new Thread(delegate()
            {
                Random r = new Random();
                while (isRunning)
                {
                    foreach (var item in lbList)
                    {
                        string str=r.Next(0, 10).ToString();
                        if (item.InvokeRequired)
                        {
                            item.Invoke(new Action<string>(delegate(string s) { item.Text = s; }), str);
                            //item.Invoke(new Action<string>(s => { item.Text = s; }

                            //    ),str);
                        }
                        else
                        {
                            item.Text = str;
                        }

                    }
                    Thread.Sleep(200);
                }
            });
            th.IsBackground = true;
            th.Start();
        }


        private void btStop_Click(object sender, EventArgs e)
        {
            isRunning = false;
        }
    }

6、对象池技术

为什么有链接池?1)、链接对象创建非常消耗资源 2)、考虑到对象的重用

避免死锁:1)、sql操作表的顺序尽量一致 2)把查询sql中加with(nolock) 3)、因为链接非常多引起的死锁,可以用临时表来解决 4)、分库:水平分库,垂直分库 5)、数据库集群,读写分离

class Program
    {
        static void Main(string[] args)
        {
            //创建一个池子
            MyConnection[] connectArry=new MyConnection[100];

            //索引
            int index = -1;

            //创建10个消费者
            for (int i = 0; i < 10; i++)
            {
                Thread th = new Thread(() => {
                    while (true)
                    {
                        lock(connectArry) //lock后面要跟一个引用类型的实例,锁住同一个对象(引用的地址)就互斥
                        {
                        if (index > 0)
                        {
                            connectArry[index+1] = null;
                            Console.WriteLine("消费了一个产品:"+index);
                            index--;
                        }
                        }
                        Thread.Sleep(500);
                    }
                });
                th.IsBackground = true;
                th.Start();
            }

            //创建5个生产者
            for (int i = 0; i <5; i++)
            {
                Thread th = new Thread(() =>
                {
                    while (true)
                    {
                        lock(connectArry)
                        {
                        if (index < 99)
                        {
                            connectArry[index+1] = new MyConnection();
                            Console.WriteLine("生产了一个产品:" + (index+1));
                            index++;
                        }
                        }
                        Thread.Sleep(1000);
                    }
                });
                th.IsBackground = true;
                th.Start();
            }
            Console.ReadKey();
        }
    }
    public class MyConnection
    {

    }

线程池的线程本身都是后台线程,优势在于线程可以进行重用,缺点在于不灵活(不能手动停止)

ThreadPool.QueueUserWorkItem((s) =>
            {
                    Console.WriteLine(s);
            });

上面的线程池过程和下面的队列操作是一样的原理,区别就是下面这个是先进先出的

 Queue<WaitCallback> queue = new Queue<WaitCallback>(); //创建一个队列
            queue.Enqueue((s) =>           //进队列
            {
                Console.WriteLine(s);
            });

什么时候用线程池?什么时候用手动创建线程?

1)、能用线程池就用线程池,处理的顺序不确定。

2)、想手动关闭线程就必须手动创建线程(Abort(),Join())

3)、需要对线程的优先级做设置必须手动创建线程

4)、如果执行的线程时间特别长,线程池适合用于做大量的小运算。

获取系统最大可设置线程数与实际设置最大线程数

//获取线程池最大线程数据
            int numMax = 0;
            int runNumMax = 0;
            ThreadPool.GetMaxThreads(out numMax, out runNumMax);
            Console.WriteLine(numMax + "   " + runNumMax);

7、异步调用委托:与手动创建线程比较的优势在于可以拿到线程执行的结果1)、无回调函数的异步委托

static void Main(string[] args)
        {
            //创建一个委托
            Func<int, int, string> func = delegate(int a, int b) { return (a + b).ToString(); };
            //异步调用委托
            IAsyncResult result = func.BeginInvoke(3, 4, null, null);
            //异步获取委托返回的结果,EndInvoke方法会阻塞当前线程,直到异步委托指向的方法执行完毕才会继续往下执行
            string str = func.EndInvoke(result);
            Console.WriteLine(str);
            Console.ReadKey();
        }

2)、有回调函数的异步委托

static void Main(string[] args)
        {
            //创建一个委托
            Func<int, int, string> func = delegate(int a, int b) { return (a + b).ToString(); };
            //异步调用委托
            func.BeginInvoke(3, 4, MyAsyncCallback, "123");
            Console.ReadKey();
        }
        public static void MyAsyncCallback(IAsyncResult ar)
        {
            //1、拿到异步委托执行的结果
            AsyncResult result = (AsyncResult)ar;    //强转成AsyncResult类型
            var del = (Func<int, int, string>)result.AsyncDelegate;   //强转成Func<int, int, string>类型
            string str = del.EndInvoke(result);
            Console.WriteLine("异步回调函数的返回结果是:"+str);  //7
            //2、拿到回掉函数参数
            Console.WriteLine("回调函数拿到的参数是:" + result.AsyncState); //123
        }
static void Main(string[] args)
        {
            //创建一个委托
            Func<int, int, string> func = delegate(int a, int b) { return (a + b).ToString(); };
            //异步调用委托
            func.BeginInvoke(3, 4, MyAsyncCallback, func);  //最后直接把委托func当成参数传给回调函数
            Console.ReadKey();
        }
        public static void MyAsyncCallback(IAsyncResult ar)
        {
            var del = (Func<int, int, string>)ar.AsyncState;   //直接将传进来的参数强转成Func<int, int, string>类型,
            string str = del.EndInvoke(ar);                    
            Console.WriteLine("异步回调函数的返回结果是:"+str);  //7
        }
static void Main(string[] args)
        {
            //创建一个委托
            Func<string, string, bool> func = delegate(string stra, string strb) { return stra == strb; };
            func.BeginInvoke("0123", "123", MyCallback, func);
            Console.ReadKey();
        }

        private static void MyCallback(IAsyncResult ar)
        {
            Func<string, string, bool> del = (Func<string, string, bool>)ar.AsyncState;
            bool b = del.EndInvoke(ar);
            if (b)
            {
                Console.WriteLine("相等");
            }
            else
            {
                Console.WriteLine("不等");
            }
        }

7、Socket编程

服务端:

  1 using System;
  2 using System.Collections.Generic;
  3 using System.ComponentModel;
  4 using System.Data;
  5 using System.Drawing;
  6 using System.IO;
  7 using System.Linq;
  8 using System.Net;
  9 using System.Net.Sockets;
 10 using System.Text;
 11 using System.Text.RegularExpressions;
 12 using System.Threading;
 13 using System.Threading.Tasks;
 14 using System.Windows.Forms;
 15 
 16 namespace Socket编程窗体服务端与客户端
 17 {
 18     public partial class ServerFrm : Form
 19     {
 20         List<Socket> proxSocketList = new List<Socket>();
 21         public ServerFrm()
 22         {
 23             InitializeComponent();
 24         }
 25 
 26         private void btStart_Click(object sender, EventArgs e)
 27         {
 28             btStart.Enabled=false;
 29             //1、获取本机IP
 30             //IPAddress[] ipAddress = Dns.GetHostAddresses(Dns.GetHostName());
 31             IPAddress iP = IPAddress.Parse(tbIp.Text);
 32             //2、创建一个用于监听的Socket
 33             Socket serverSocket = new Socket(
 34                 AddressFamily.InterNetwork, 
 35                 SocketType.Stream, 
 36                 ProtocolType.Tcp
 37             );
 38             //3、绑定IP
 39             IPEndPoint ipEndPoint=new IPEndPoint(iP,Convert.ToInt32(tbPort.Text));
 40             serverSocket.Bind(ipEndPoint);
 41 
 42             ReceiveText("服务端开始监听");
 43             //4、建立监听队列,默认为10
 44             serverSocket.Listen(10);
 45 
 46             //5、主线程一直负责监听,线程池的线程来接受客户端连接请求
 47             ThreadPool.QueueUserWorkItem((s) => 
 48             {
 49                 while (true)
 50                 {
 51                     Socket proxSocket = serverSocket.Accept();
 52                     ReceiveText("客户端:" + proxSocket.RemoteEndPoint + "链接成功");
 53                     proxSocketList.Add(proxSocket);
 54                     if (cbClientSocket.InvokeRequired)
 55                     {
 56                         cbClientSocket.Invoke(new Action<IPEndPoint>((a) => { cbClientSocket.Items.Add(a); }), proxSocket.RemoteEndPoint);
 57                     }
 58                     else
 59                     {
 60                         cbClientSocket.Items.Add(proxSocket.RemoteEndPoint);
 61                     }
 62                     ThreadPool.QueueUserWorkItem(new WaitCallback( ReceiveCallback), proxSocket);
 63                 }
 64             },serverSocket);
 65         }
 66 
 67         private void ReceiveCallback(object ar)
 68         {
 69             Socket proxSocket = (Socket)ar;
 70             byte[] buffer = new byte[1024 * 1024];
 71             while (true)
 72             {
 73                 int iReceive=0;
 74                 try
 75                 {
 76                     iReceive = proxSocket.Receive(buffer, 0, buffer.Length, SocketFlags.None);
 77                 }
 78                 catch
 79                 {
 80 
 81                 }
 82                 if (iReceive <= 0)
 83                 {
 84                     ReceiveText("客户端:" + proxSocket.RemoteEndPoint + "断开链接");
 85                     proxSocketList.Remove(proxSocket);
 86                     if (cbClientSocket.InvokeRequired)
 87                     {
 88                         cbClientSocket.Invoke(new Action<Socket>((s) => { cbClientSocket.Items.Remove(s.RemoteEndPoint); }), proxSocket);
 89                     }
 90                     else
 91                     {
 92                         cbClientSocket.Items.Remove(proxSocket.RemoteEndPoint);
 93                     }
 94                     return;
 95                 }
 96                 if (buffer[0] == 1)
 97                {
 98                    ReceiveText("收到来自:" + proxSocket.RemoteEndPoint + "的消息:" + Encoding.Default.GetString(buffer, 1, iReceive-1));                  
 99                }
100                 else if (buffer[0] == 2)
101                 {
102                     Thread th = new Thread(new ThreadStart(() =>
103                     {
104                         using (SaveFileDialog sfd = new SaveFileDialog())
105                         {
106                             if (sfd.ShowDialog() != DialogResult.OK)
107                             {
108                                 return;
109                             }
110                             byte[] fileData = new byte[buffer.Length - 1];
111                             Buffer.BlockCopy(buffer, 1, fileData, 0, buffer.Length - 1);
112                             using (FileStream fs = new FileStream(sfd.FileName, FileMode.Create, FileAccess.Write))
113                             {
114                                 using (StreamWriter sw = new StreamWriter(fs, Encoding.Default))
115                                 {
116                                     sw.Write(Encoding.Default.GetString(fileData, 0, fileData.Length));
117                                 }
118                             }
119                         }
120                     }));
121                     th.SetApartmentState(ApartmentState.STA);
122                     th.Start();
123                 }
124             }
125         }
126         private void ReceiveText(string str)
127         {
128             if (rtbReceive.InvokeRequired)
129             {
130                 rtbReceive.Invoke(new Action<string>((s) => 
131                 {
132                     rtbReceive.Text = string.Format("{0}\r\n{1}", str, rtbReceive.Text);
133                 }),str);
134             }
135             else
136             {
137                 rtbReceive.Text = string.Format("{0}\r\n{1}", str, rtbReceive.Text);
138             }
139         }
140 
141         private void btSend_Click(object sender, EventArgs e)
142         {
143             foreach (var item in proxSocketList)
144             {
145                 if (cbClientSocket.SelectedItem == null)
146                 {
147                     byte[] data = Encoding.Default.GetBytes(tbSend.Text);
148                     byte[] buffer = new byte[data.Length + 1];
149                     buffer[0] = 1;
150                     Buffer.BlockCopy(data, 0, buffer, 1, data.Length);
151                     item.Send(buffer, 0, buffer.Length, SocketFlags.None);
152                 }
153                 else
154                 {
155                     if (item.RemoteEndPoint == cbClientSocket.SelectedItem)
156                     {
157                         byte[] data = Encoding.Default.GetBytes(tbSend.Text);
158                         byte[] buffer = new byte[data.Length + 1];
159                         buffer[0] = 1;
160                         Buffer.BlockCopy(data, 0, buffer, 1, data.Length);
161                         item.Send(buffer, 0, buffer.Length, SocketFlags.None);
162                     }
163                 }
164             }
165         }
166 
167         private void btSendFile_Click(object sender, EventArgs e)
168         {
169             string str = "";
170             Thread th = new Thread(new ThreadStart(() =>
171             {
172                 using (OpenFileDialog ofd = new OpenFileDialog())
173                 {
174                     if (ofd.ShowDialog() != DialogResult.OK)
175                     {
176                         return;
177                     }
178                     if (tbFileName.InvokeRequired)
179                     {
180                         tbFileName.Invoke(new Action<string>(delegate(string s) { this.tbFileName.Text = s; }), ofd.FileName);
181                     }
182                     else
183                     {
184                         this.tbFileName.Text = ofd.FileName;
185                     }
186 
187                     using (FileStream fs = new FileStream(ofd.FileName, FileMode.Open, FileAccess.Read))
188                     {
189                         using (StreamReader sr = new StreamReader(fs, Encoding.Default))
190                         {
191                             if (!sr.EndOfStream)
192                             {
193                                 str = str + sr.ReadToEnd();
194                             }
195                         }
196                     }
197                 }
198                 foreach (var item in proxSocketList)
199                 {
200                     if (cbClientSocket.InvokeRequired)
201                     {
202                         cbClientSocket.Invoke(new Action<Socket>((s) =>
203                         {
204                             if (s.RemoteEndPoint == cbClientSocket.SelectedItem)
205                             {
206                                 byte[] data = Encoding.Default.GetBytes(str);
207                                 byte[] buffer = new byte[data.Length + 1];
208                                 buffer[0] = 2;
209                                 Buffer.BlockCopy(data, 0, buffer, 1, data.Length);
210                                 s.Send(buffer, 0, buffer.Length, SocketFlags.None);
211                                 ReceiveText("发送文件到:" + s.RemoteEndPoint + "成功");
212                             }
213                             else if (cbClientSocket.SelectedItem == null)
214                             {
215                                 byte[] data = Encoding.Default.GetBytes(str);
216                                 byte[] buffer = new byte[data.Length + 1];
217                                 buffer[0] = 2;
218                                 Buffer.BlockCopy(data, 0, buffer, 1, data.Length);
219                                 s.Send(buffer, 0, buffer.Length, SocketFlags.None);
220                                 ReceiveText("发送文件到:" + s.RemoteEndPoint + "成功");
221                             }
222                         }),item);
223                     }
224                     else
225                     {
226                         if (item.RemoteEndPoint == cbClientSocket.SelectedItem)
227                         {
228                             byte[] data = Encoding.Default.GetBytes(str);
229                             byte[] buffer = new byte[data.Length + 1];
230                             buffer[0] = 2;
231                             Buffer.BlockCopy(data, 0, buffer, 1, data.Length);
232                             item.Send(buffer, 0, buffer.Length, SocketFlags.None);
233                             ReceiveText("发送文件到:" + item.RemoteEndPoint + "成功");
234                         }
235                         else if (cbClientSocket.SelectedItem == null)
236                         {
237                             byte[] data = Encoding.Default.GetBytes(str);
238                             byte[] buffer = new byte[data.Length + 1];
239                             buffer[0] = 2;
240                             Buffer.BlockCopy(data, 0, buffer, 1, data.Length);
241                             item.Send(buffer, 0, buffer.Length, SocketFlags.None);
242                             ReceiveText("发送文件到:" + item.RemoteEndPoint + "成功");
243                         }
244                     }
245                 }
246                 
247             }));
248             th.SetApartmentState(ApartmentState.STA);
249             th.Start();
250         }
251 
252         private void tbClear_Click(object sender, EventArgs e)
253         {
254             cbClientSocket.SelectedItem =null;
255         }
256     }
257 }

客户端:

  1 using System;
  2 using System.Collections.Generic;
  3 using System.ComponentModel;
  4 using System.Data;
  5 using System.Drawing;
  6 using System.IO;
  7 using System.Linq;
  8 using System.Net;
  9 using System.Net.Sockets;
 10 using System.Text;
 11 using System.Text.RegularExpressions;
 12 using System.Threading;
 13 using System.Threading.Tasks;
 14 using System.Windows.Forms;
 15 
 16 namespace Socket编程窗体服务端与客户端
 17 {
 18     public partial class ClientFrm : Form
 19     {
 20         private Socket ClientSocket { get; set; }
 21         public ClientFrm()
 22         {
 23             InitializeComponent();
 24         }
 25 
 26         private void btConnect_Click(object sender, EventArgs e)
 27         {
 28             btConnect.Enabled = false;
 29             //1、获取本机IP
 30             //IPAddress[] ipAddress = Dns.GetHostAddresses(Dns.GetHostName());
 31             IPAddress iP = IPAddress.Parse(tbIp.Text);
 32             //2、创建一个用于链接的Socket
 33             Socket clientSocket = new Socket(
 34                 AddressFamily.InterNetwork,
 35                 SocketType.Stream,
 36                 ProtocolType.Tcp
 37             );
 38             //3、绑定IP
 39             IPEndPoint ipEndPoint = new IPEndPoint(iP, Convert.ToInt32(tbPort.Text));
 40 
 41             //4、开始链接
 42             clientSocket.Connect(ipEndPoint);
 43             ClientSocket = clientSocket;
 44             ReceiveText("到服务端:" + clientSocket.RemoteEndPoint + "链接成功");
 45             ThreadPool.QueueUserWorkItem((s) =>
 46             {
 47                 byte[] buffer = new byte[1024 * 1024];
 48                 while (true)
 49                 {
 50                     int iReceive = 0;
 51                     try
 52                     {
 53                         iReceive = clientSocket.Receive(buffer, 0, buffer.Length, SocketFlags.None);
 54                     }
 55                     catch
 56                     {
 57 
 58                     }
 59                     if (iReceive <= 0)
 60                     {
 61                         ReceiveText("断开与服务端:" + clientSocket.RemoteEndPoint + "链接");
 62                         return;
 63                     }
 64                     if (buffer[0] == 1)
 65                     {
 66                         ReceiveText("收到服务端" + clientSocket.RemoteEndPoint + "发来的消息:" + Encoding.Default.GetString(buffer, 1, iReceive-1));
 67                     }
 68                     else if (buffer[0] == 2)
 69                     {
 70                         Thread th = new Thread(new ThreadStart(() =>
 71                         {
 72                             using (SaveFileDialog sfd = new SaveFileDialog())
 73                             {
 74                                 if (sfd.ShowDialog() != DialogResult.OK)
 75                                 {
 76                                     return;
 77                                 }
 78                                 byte[] fileData = new byte[buffer.Length - 1];
 79                                 Buffer.BlockCopy(buffer, 1, fileData, 0, buffer.Length - 1);
 80                                 using (FileStream fs = new FileStream(sfd.FileName, FileMode.Create, FileAccess.Write))
 81                                 {
 82                                     using (StreamWriter sw = new StreamWriter(fs, Encoding.Default))
 83                                     {
 84                                         sw.Write(Encoding.Default.GetString(fileData, 0, fileData.Length));
 85                                     }
 86                                 }
 87                             }
 88                         }));
 89                         th.SetApartmentState(ApartmentState.STA);
 90                         th.Start();
 91                     }
 92                 }
 93             },clientSocket);
 94         }
 95         private void ReceiveText(string str)
 96         {
 97             if (rtbReceive.InvokeRequired)
 98             {
 99                 rtbReceive.Invoke(new Action<string>((s) =>
100                 {
101                     rtbReceive.Text = string.Format("{0}\r\n{1}", str, rtbReceive.Text);
102                 }), str);
103             }
104             else
105             {
106                 rtbReceive.Text = string.Format("{0}\r\n{1}", str, rtbReceive.Text);
107             }
108         }
109 
110         private void btSend_Click(object sender, EventArgs e)
111         {
112             byte[] data = Encoding.Default.GetBytes(tbSend.Text);
113             byte[] buffer = new byte[data.Length+1];
114             buffer[0] = 1;
115             Buffer.BlockCopy(data, 0, buffer, 1, data.Length);
116             ClientSocket.Send(buffer, 0, buffer.Length, SocketFlags.None);
117         }
118 
119         private void btSendFile_Click(object sender, EventArgs e)
120         {
121             string str = "";
122             Thread th = new Thread(new ThreadStart(() =>
123             {
124                 using (OpenFileDialog ofd = new OpenFileDialog())
125                 {
126                     if (ofd.ShowDialog() != DialogResult.OK)
127                     {
128                         return;
129                     }
130                     if (tbSendFileName.InvokeRequired)
131                     {
132                         tbSendFileName.Invoke(new Action<string>(delegate(string s) { this.tbSendFileName.Text = s; }), ofd.FileName);
133                     }
134                     else
135                     {
136                         this.tbSendFileName.Text = ofd.FileName;
137                     }
138                     
139                     using (FileStream fs = new FileStream(ofd.FileName, FileMode.Open, FileAccess.Read))
140                     {
141                         using (StreamReader sr = new StreamReader(fs,Encoding.Default))
142                         {
143                             if (!sr.EndOfStream)
144                             {
145                                 str = str + sr.ReadToEnd();
146                             }
147                         }
148                     }
149                 }
150                 byte[] data = Encoding.Default.GetBytes(str);
151 
152                 byte[] buffer = new byte[data.Length + 1];
153                 buffer[0] = 2;
154                 Buffer.BlockCopy(data, 0, buffer, 1, data.Length);
155                 ClientSocket.Send(buffer, 0, buffer.Length, SocketFlags.None);
156                 ReceiveText("发送文件到:" + ClientSocket.RemoteEndPoint + "成功");
157             }));
158             th.SetApartmentState(ApartmentState.STA);
159             th.Start();
160         }
161 
162         private void ClientFrm_FormClosed(object sender, FormClosedEventArgs e)
163         {
164             ClientSocket.Shutdown(SocketShutdown.Both);
165         }
166     }
167 } 

8、Response.Redirect原理

请求头(消息头)包含(客户机请求的服务器主机名,客户机的环境信息等):

1、Accept:用于告诉服务器,客户机支持的数据类型 (例如:Accept:text/html,image/*)

2、Accept-Charset:用于告诉服务器,客户机采用的编码格式

3、Accept-Encoding:用于告诉服务器,客户机支持的数据压缩格式

4、Accept-Language:客户机语言环境

5、Host:客户机通过这个服务器,想访问的主机名

6、If-Modified-Since:客户机通过这个头告诉服务器,资源的缓存时间

7、Referer:客户机通过这个头告诉服务器,它(客户端)是从哪个资源来访问服务器的(防盗链)

8、User-Agent:客户机通过这个头告诉服务器,客户机的软件环境(操作系统,浏览器版本等)

9、Cookie:客户机通过这个头,将Coockie信息带给服务器

10、Connection:告诉服务器,请求完成后,是否保持连接

11、Date:告诉服务器,当前请求的时间

一个http响应代表服务器端向客户端回送的数据,它包括:

一个状态行,若干个响应消息头,以及实体内容

状态行: 例如: HTTP/1.1 200 OK (协议的版本号是1.1 响应状态码为200 响应结果为 OK)

响应头(消息头)包含:

1、Location:这个头配合302状态吗,用于告诉客户端找谁

2、Server:服务器通过这个头,告诉浏览器服务器的类型

3、Content-Encoding:告诉浏览器,服务器的数据压缩格式

4、Content-Length:告诉浏览器,回送数据的长度

5、Content-Type:告诉浏览器,回送数据的类型

6、Last-Modified:告诉浏览器当前资源缓存时间

7、Refresh:告诉浏览器,隔多长时间刷新

8、Content- Disposition:告诉浏览器以下载的方式打开数据。例如:

context.Response.AddHeader("Content-Disposition","attachment:filename=icon.jpg");

context.Response.WriteFile("icon.jpg");

9、Transfer-Encoding:告诉浏览器,传送数据的编码格式

10、ETag:缓存相关的头(可以做到实时更新)

11、Expries:告诉浏览器回送的资源缓存多长时间。如果是-1或者0,表示不缓存

12、Cache-Control:控制浏览器不要缓存数据 no-cache

13、Pragma:控制浏览器不要缓存数据 no-cache

14、Connection:响应完成后,是否断开连接。 close/Keep-Alive

15、Date:告诉浏览器,服务器响应时间

 9、POST和GET请求处理方式的不同点:

POST通过http请求的请求体往后台服务器传数据,数据传递量较大GET通过queryString的方式来传递数据,会自动封装到请求行的url地址后面

10、表单要想提交数据必须具备以下条件:1)、表单标签必须要有name属性 2)、表单标签不能设置为disabled

11、ASP.NET中三层架构:

BLL:业务逻辑层

DAL:数据访问层

Model:实体层

Common:常用处理组件层

DBUtility:数据库应用层

12、上传图片文件

from的enctype属性一定得是multipart/form-data才能传文件
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
</head>
<body>
    <form method="post" enctype="multipart/form-data" action="ImageUpload.ashx">  //
        <input type="file" name="imgFile" />
        <input type="submit" value="上传" />
    </form>
</body>
</html>
public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/html";
            //拿到上传上来的文件
            HttpPostedFile file= context.Request.Files["imgFile"];
            string path = "/Upload/"+Guid.NewGuid().ToString()+file.FileName;
            file.SaveAs(context.Request.MapPath(path));
            string str = string.Format(@"<html><head></head><body><img src='{0}'/></body></html>"
                ,path);
            context.Response.Write(str);
        }

 像上面程序这样上传文件有一个问题,如果上传的是一个可执行的代码文件会直接运行,对网站安全造成影响,所以在前端上传的时候加一个判断

<script src="../Scripts/jQuery-3.2.1.js"></script>
    <script type="text/javascript">
        $(function () {
            $(":file").change(function () {
                var fileName = $(this).val();
                var ext = fileName.substr(fileName.lastIndexOf("."))
                if (ext == ".jpeg" || ext == ".jpg" || ext == ".png" || ext == ".gif"||ext==".bmp") {
                    return true;
                } else {
                    $(this).val("");
                    return false;
                }
            });
        });
    </script>

但是光前端判断还不够,这样只能防止普通用户误传文件,如果有人绕过前端直接访问后台,问题依然存在,所以后台也得加判断

public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/html";
            //拿到上传上来的文件
            HttpPostedFile file = context.Request.Files["imgFile"];
            string ext = Path.GetExtension(file.FileName);
            if(!(ext == ".jpeg" || ext == ".jpg" || ext == ".png" || ext == ".gif" || ext == ".bmp"))
            {
                context.Response.Write("你是猴子请来的逗b吗");
                context.Response.End();
            }
            else
            {
                string path = "/Upload/" + Guid.NewGuid().ToString() + file.FileName;
                file.SaveAs(context.Request.MapPath(path));
                string str = string.Format(@"<html><head></head><body><img src='{0}'/></body></html>"
                    , path);
                context.Response.Write(str);
            }
        }

 13、网站的防盗链

要是不做防盗链检查的话,很有可能本网站的资源会被别的网站盗链,相当于本网站免费给别的网站存储数据。

下面要做的就是防盗链:资源一般不直接显示在html里面,用一般处理程序可以在显示前进行防盗链判断,这里要判断当前请求是否来自本网站的域名和端口,是的话放行,不是就剁掉。

<body>
    <h1>这是主网站</h1>
    <!--<img src="a.bmp" />-->
    <img src="ShowImage.ashx" />
</body>
 public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "image/jpeg";
            //判断是否是本网站的请求,是的话放心,不是的话结束
            Uri refererUrl = context.Request.UrlReferrer;
            //判断:UrlRefrence的域名和端口是否是本网站的域名和端口
            Uri requestUrl = context.Request.Url;
            if (Uri.Compare(requestUrl, refererUrl, UriComponents.HostAndPort, UriFormat.SafeUnescaped, StringComparison.CurrentCulture) == 0)
            {
                context.Response.WriteFile("a.bmp");
            }
            else
            {
                context.Response.WriteFile("9.bmp");
            }
        }
<body>
    <h1>这是子网站</h1>
    <img src="http://localhost:9299/FileUpload/ShowImage.ashx" />

</body>

 14、给上传的图片加水印文字

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
    <script src="../Scripts/jQuery-3.2.1.js"></script>
    <script type="text/javascript">
        $(function () {
            $(":file").change(function () {
                var fileName = $(this).val();
                var ext = fileName.substr(fileName.lastIndexOf("."))
                if (ext == ".jpeg" || ext == ".jpg" || ext == ".png" || ext == ".gif" || ext == ".bmp") {
                    return true;
                } else {
                    $(this).val("");
                    return false;
                }
            });
        });
    </script>
</head>
<body>
    <form method="post" enctype="multipart/form-data" action="ImageProcess.ashx">
        <input type="file" name="imgFile" />
        <input type="submit" value="上传" />
    </form>
</body>
</html>
 public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/html";
            HttpPostedFile file = context.Request.Files["imgFile"];
            if (file == null)
            {
                context.Response.End();
            }
            //把上传的文件做成了一个image对象
            Image image = Image.FromStream(file.InputStream);

            Graphics graphics = Graphics.FromImage(image);
            string str="唐唐";  //要加的水印文字
            graphics.DrawString(str, new Font("宋体", 48), new SolidBrush(Color.Blue), new PointF(image.Width - (48 * str.Length), image.Height - 96));//绘制文字到上传的图片
            string strPath = "/Upload/" + Guid.NewGuid().ToString() + file.FileName;  //申明一个保存图片的路径
            image.Save(context.Request.MapPath(strPath), ImageFormat.Jpeg); //保存图片到指定的路径
            string strHtml = string.Format(@"<html><head></head><body><img src='{0}'/></body></html>",strPath);//将指定路径下的图片放到html字符串里
            context.Response.Write(strHtml);//显示上面拼写的html页面
        }

 15、缩略图

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
    <script src="../Scripts/jQuery-3.2.1.js"></script>
    <script type="text/javascript">
        $(function () {
            $(":file").change(function () {
                var fileName = $(this).val();
                var ext = fileName.substr(fileName.lastIndexOf("."))
                if (ext == ".jpeg" || ext == ".jpg" || ext == ".png" || ext == ".gif" || ext == ".bmp") {
                    return true;
                } else {
                    $(this).val("");
                    return false;
                }
            });
        });
    </script>
</head>
<body>
    <!--<form method="post" enctype="multipart/form-data" action="ImageProcess.ashx">-->
    <form method="post" enctype="multipart/form-data" action="SmallImage.ashx">
        <input type="file" name="imgFile" />
        <input type="submit" value="上传" />
    </form>
</body>
</html>
 public class SmallImage : IHttpHandler
    {

        public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "image/jpeg";
            HttpPostedFile file = context.Request.Files["imgFile"];
            if (file == null)
            {
                context.Response.End();
            }
            //把上传的文件做成了一个image对象
            Image image = Image.FromStream(file.InputStream);
            Bitmap smallImage = new Bitmap(100, 100);
            Graphics g = Graphics.FromImage(smallImage);
            g.DrawImage(image, new Rectangle(0, 0, 100, 100), new Rectangle(0, 0, image.Width, image.Height),
                GraphicsUnit.Pixel);
            string strPath = "/Upload/Small-" + Guid.NewGuid().ToString() + file.FileName;
            smallImage.Save(context.Request.MapPath(strPath));
            MemoryStream ms=new MemoryStream();
            smallImage.Save(ms,ImageFormat.Jpeg);//把缩略图写到内存流
            context.Response.BinaryWrite(ms.ToArray());   
        }

 16、asp.net基础工作原理图

 

 

 

 17、HttpApplication的处理管道19个事件。(转)

HttpApplication对象是由Asp.NET帮助我们创建的,它是asp.net中处理请求的重要对象。为了便于扩展,HttpApplication采用处理管道的方式进行处理,将处理的步骤分为多个步骤,每个步骤通过事件的形式暴露给程序员,这些事件按照固定的处理顺序依次触发,程序员通过编写事件处理方法就可以定义一个请求的扩展过程。

对于HttpApplication,到ASP.Net 4.0,提供了19个标准事件。

1.BeginRequest:asp.net开始处理请求的第一个事件,表示处理的开始。

2.AuthenticateRequest:验证请求,一般用来取得请求的用户信息。

3.PostAuthenticateRequest:已经获取请求的用户信息。

4.AuthorizeRequest:授权,一般用来检查用户的请求是否获得权限。

5.PostAuthorizeRequest:用户请求已经获得授权。

6.ResolveRequestCache:获取以前处理缓存的处理结果,如果以前缓存过,那么,不用再进行请求的处理工作,直接返回缓存的结果。

7.PostResolveRequestCache:已经完成缓存的处理工作。

8.PostMapRequestHandler:已经根据用户的请求,创建了请求的处理器对象。

9.AcquireRequestState:取得请求的状态,一般用于session

10.PostAcquireRequestState:已经获得了session

11.PreRequestHandlerExecute:准备执行处理程序。

12.PostRequestHandlerExecute:已经执行了处理程序

13.ReleaseRequestState:释放请求的状态。

14.PostReleaseRequestState:已经释放了请求的状态。

15.UpdateRequestCache:更新缓存。

16.PostUpdateRequestCache:已经更新了缓存。

17.LogRequest:请求的日志操作

18.PostLogRequest:已经完成请求的日志操作。

19.EndRequest:本次请求处理完成。

 

下面是请求管道中的19个事件.(转)

(1)BeginRequest: 开始处理请求

(2)AuthenticateRequest授权验证请求,获取用户授权信息

(3):PostAuthenticateRequest获取成功

(4): AunthorizeRequest 授权,一般来检查用户是否获得权限

(5):PostAuthorizeRequest:获得授权

(6):ResolveRequestCache:获取页面缓存结果

 

(7):PostResolveRequestCache 已获取缓存   当前请求映射到MvcHandler(pr):  创建控制器工厂 ,创建控制器,调用action执行,view→response

//action   Handler : PR()

(8):PostMapRequestHandler 创建页面对象:创建 最终处理当前http请求的 Handler  实例:  第一从HttpContext中获取当前的PR Handler   ,Create

(9):PostAcquireRequestState 获取Session

(10)PostAcquireRequestState 获得Session

(11)PreRequestHandlerExecute:准备执行页面对象 执行页面对象的ProcessRequest方法

(12)PostRequestHandlerExecute 执行完页面对象了

(13)ReleaseRequestState 释放请求状态

(14)PostReleaseRequestState 已释放请求状态

(15)UpdateRequestCache 更新缓存

(16)PostUpdateRequestCache 已更新缓存

(17)LogRequest 日志记录

(18)PostLogRequest 已完成日志

(19)EndRequest 完成、

 


18、Server.Transfer()和Response.Redirect()的区别

1)、Server.Transfer是实现了一个内部接管的效果,当浏览器发送请求到服务器时,服务器执行Server.Transfer将请求直接交给另外一个处理程序来处理,这个过程浏览器是感知不到的;

2)、Response.Redriect:当浏览器发送请求到服务器,服务器执行Response.Redirect返回一个302相应给浏览器,让浏览器重新请求另外一个地址,这个过程浏览器能够感知到;

3)、综上所述,两者实现的效果一样,但是Server.Transfer是用后台接管的方式实现,浏览器只用发起一次请求(因此只能访问内部网站),而Respnse.Redirect需要发起两次请求(因此可以访问外部网站)。

 

19、ViewState:帮助我们记住当前页面的状态,文本框,下拉列表的改变事件都通过此实现,其本质相当于一个内容经过Base64加密的隐藏域。适合给自己传值

20、cookie:一小段文本,明文,存储在客户端浏览器内存里面或磁盘,cookie和网站相关,cookie会随请求一起发送到后台,cookie有限制:4kb字节总数据,

使用场景:记住用户名,适用于帮助网站记住使用当前浏览器的用户相关信息。如果设置了过期时间就存在磁盘上,没有设置过期时间就存在内存。如果给cookie设置path路径就指定在该路劲下的网页才能使用cookie。子域可以访问父域的cookie,父域想要访问子域的cookie必须要将子域的cookie创建成父域的cookie。

21、Session:会话,就是持续的一段时间,如果是一般处理程序实现session必须要实现IRequiresSessionState接口。

 22、Application:全局变量,也可以用来存储数据。

posted @ 2018-03-21 17:53  你是我的四月天  阅读(345)  评论(0编辑  收藏  举报