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();
}
}); th.IsBackground = true;//线程默认是前台线程,一个进程结束的标志是所有前台线程都结束之后。 th.Priority = ThreadPriority.Normal;//后台线程不会组塞 进程的退出 th.Start();//告诉操作系统线程准备就绪 th.Join();//等待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 = ; i < ; i++)
{
Label lb = new Label();
lb.Text = "";
lb.AutoSize = true; lb.Location = new Point( * i + , );
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(, ).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();
}
});
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[]; //索引
int index = -; //创建10个消费者
for (int i = ; i < ; i++)
{
Thread th = new Thread(() => {
while (true)
{
lock(connectArry) //lock后面要跟一个引用类型的实例,锁住同一个对象(引用的地址)就互斥
{
if (index > )
{
connectArry[index+] = null;
Console.WriteLine("消费了一个产品:"+index);
index--;
}
}
Thread.Sleep();
}
});
th.IsBackground = true;
th.Start();
} //创建5个生产者
for (int i = ; i <; i++)
{
Thread th = new Thread(() =>
{
while (true)
{
lock(connectArry)
{
if (index < )
{
connectArry[index+] = new MyConnection();
Console.WriteLine("生产了一个产品:" + (index+));
index++;
}
}
Thread.Sleep();
}
});
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 = ;
int runNumMax = ;
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(, , 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(, , MyAsyncCallback, "");
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); //
}
static void Main(string[] args)
{
//创建一个委托
Func<int, int, string> func = delegate(int a, int b) { return (a + b).ToString(); };
//异步调用委托
func.BeginInvoke(, , 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); //
}
static void Main(string[] args)
{
//创建一个委托
Func<string, string, bool> func = delegate(string stra, string strb) { return stra == strb; };
func.BeginInvoke("", "", 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编程
服务端:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms; namespace Socket编程窗体服务端与客户端
{
public partial class ServerFrm : Form
{
List<Socket> proxSocketList = new List<Socket>();
public ServerFrm()
{
InitializeComponent();
} private void btStart_Click(object sender, EventArgs e)
{
btStart.Enabled=false;
//1、获取本机IP
//IPAddress[] ipAddress = Dns.GetHostAddresses(Dns.GetHostName());
IPAddress iP = IPAddress.Parse(tbIp.Text);
//2、创建一个用于监听的Socket
Socket serverSocket = new Socket(
AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp
);
//3、绑定IP
IPEndPoint ipEndPoint=new IPEndPoint(iP,Convert.ToInt32(tbPort.Text));
serverSocket.Bind(ipEndPoint); ReceiveText("服务端开始监听");
//4、建立监听队列,默认为10
serverSocket.Listen(); //5、主线程一直负责监听,线程池的线程来接受客户端连接请求
ThreadPool.QueueUserWorkItem((s) =>
{
while (true)
{
Socket proxSocket = serverSocket.Accept();
ReceiveText("客户端:" + proxSocket.RemoteEndPoint + "链接成功");
proxSocketList.Add(proxSocket);
if (cbClientSocket.InvokeRequired)
{
cbClientSocket.Invoke(new Action<IPEndPoint>((a) => { cbClientSocket.Items.Add(a); }), proxSocket.RemoteEndPoint);
}
else
{
cbClientSocket.Items.Add(proxSocket.RemoteEndPoint);
}
ThreadPool.QueueUserWorkItem(new WaitCallback( ReceiveCallback), proxSocket);
}
},serverSocket);
} private void ReceiveCallback(object ar)
{
Socket proxSocket = (Socket)ar;
byte[] buffer = new byte[ * ];
while (true)
{
int iReceive=;
try
{
iReceive = proxSocket.Receive(buffer, , buffer.Length, SocketFlags.None);
}
catch
{ }
if (iReceive <= )
{
ReceiveText("客户端:" + proxSocket.RemoteEndPoint + "断开链接");
proxSocketList.Remove(proxSocket);
if (cbClientSocket.InvokeRequired)
{
cbClientSocket.Invoke(new Action<Socket>((s) => { cbClientSocket.Items.Remove(s.RemoteEndPoint); }), proxSocket);
}
else
{
cbClientSocket.Items.Remove(proxSocket.RemoteEndPoint);
}
return;
}
if (buffer[] == )
{
ReceiveText("收到来自:" + proxSocket.RemoteEndPoint + "的消息:" + Encoding.Default.GetString(buffer, , iReceive-));
}
else if (buffer[] == )
{
Thread th = new Thread(new ThreadStart(() =>
{
using (SaveFileDialog sfd = new SaveFileDialog())
{
if (sfd.ShowDialog() != DialogResult.OK)
{
return;
}
byte[] fileData = new byte[buffer.Length - ];
Buffer.BlockCopy(buffer, , fileData, , buffer.Length - );
using (FileStream fs = new FileStream(sfd.FileName, FileMode.Create, FileAccess.Write))
{
using (StreamWriter sw = new StreamWriter(fs, Encoding.Default))
{
sw.Write(Encoding.Default.GetString(fileData, , fileData.Length));
}
}
}
}));
th.SetApartmentState(ApartmentState.STA);
th.Start();
}
}
}
private void ReceiveText(string str)
{
if (rtbReceive.InvokeRequired)
{
rtbReceive.Invoke(new Action<string>((s) =>
{
rtbReceive.Text = string.Format("{0}\r\n{1}", str, rtbReceive.Text);
}),str);
}
else
{
rtbReceive.Text = string.Format("{0}\r\n{1}", str, rtbReceive.Text);
}
} private void btSend_Click(object sender, EventArgs e)
{
foreach (var item in proxSocketList)
{
if (cbClientSocket.SelectedItem == null)
{
byte[] data = Encoding.Default.GetBytes(tbSend.Text);
byte[] buffer = new byte[data.Length + ];
buffer[] = ;
Buffer.BlockCopy(data, , buffer, , data.Length);
item.Send(buffer, , buffer.Length, SocketFlags.None);
}
else
{
if (item.RemoteEndPoint == cbClientSocket.SelectedItem)
{
byte[] data = Encoding.Default.GetBytes(tbSend.Text);
byte[] buffer = new byte[data.Length + ];
buffer[] = ;
Buffer.BlockCopy(data, , buffer, , data.Length);
item.Send(buffer, , buffer.Length, SocketFlags.None);
}
}
}
} private void btSendFile_Click(object sender, EventArgs e)
{
string str = "";
Thread th = new Thread(new ThreadStart(() =>
{
using (OpenFileDialog ofd = new OpenFileDialog())
{
if (ofd.ShowDialog() != DialogResult.OK)
{
return;
}
if (tbFileName.InvokeRequired)
{
tbFileName.Invoke(new Action<string>(delegate(string s) { this.tbFileName.Text = s; }), ofd.FileName);
}
else
{
this.tbFileName.Text = ofd.FileName;
} using (FileStream fs = new FileStream(ofd.FileName, FileMode.Open, FileAccess.Read))
{
using (StreamReader sr = new StreamReader(fs, Encoding.Default))
{
if (!sr.EndOfStream)
{
str = str + sr.ReadToEnd();
}
}
}
}
foreach (var item in proxSocketList)
{
if (cbClientSocket.InvokeRequired)
{
cbClientSocket.Invoke(new Action<Socket>((s) =>
{
if (s.RemoteEndPoint == cbClientSocket.SelectedItem)
{
byte[] data = Encoding.Default.GetBytes(str);
byte[] buffer = new byte[data.Length + ];
buffer[] = ;
Buffer.BlockCopy(data, , buffer, , data.Length);
s.Send(buffer, , buffer.Length, SocketFlags.None);
ReceiveText("发送文件到:" + s.RemoteEndPoint + "成功");
}
else if (cbClientSocket.SelectedItem == null)
{
byte[] data = Encoding.Default.GetBytes(str);
byte[] buffer = new byte[data.Length + ];
buffer[] = ;
Buffer.BlockCopy(data, , buffer, , data.Length);
s.Send(buffer, , buffer.Length, SocketFlags.None);
ReceiveText("发送文件到:" + s.RemoteEndPoint + "成功");
}
}),item);
}
else
{
if (item.RemoteEndPoint == cbClientSocket.SelectedItem)
{
byte[] data = Encoding.Default.GetBytes(str);
byte[] buffer = new byte[data.Length + ];
buffer[] = ;
Buffer.BlockCopy(data, , buffer, , data.Length);
item.Send(buffer, , buffer.Length, SocketFlags.None);
ReceiveText("发送文件到:" + item.RemoteEndPoint + "成功");
}
else if (cbClientSocket.SelectedItem == null)
{
byte[] data = Encoding.Default.GetBytes(str);
byte[] buffer = new byte[data.Length + ];
buffer[] = ;
Buffer.BlockCopy(data, , buffer, , data.Length);
item.Send(buffer, , buffer.Length, SocketFlags.None);
ReceiveText("发送文件到:" + item.RemoteEndPoint + "成功");
}
}
} }));
th.SetApartmentState(ApartmentState.STA);
th.Start();
} private void tbClear_Click(object sender, EventArgs e)
{
cbClientSocket.SelectedItem =null;
}
}
}
客户端:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms; namespace Socket编程窗体服务端与客户端
{
public partial class ClientFrm : Form
{
private Socket ClientSocket { get; set; }
public ClientFrm()
{
InitializeComponent();
} private void btConnect_Click(object sender, EventArgs e)
{
btConnect.Enabled = false;
//1、获取本机IP
//IPAddress[] ipAddress = Dns.GetHostAddresses(Dns.GetHostName());
IPAddress iP = IPAddress.Parse(tbIp.Text);
//2、创建一个用于链接的Socket
Socket clientSocket = new Socket(
AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp
);
//3、绑定IP
IPEndPoint ipEndPoint = new IPEndPoint(iP, Convert.ToInt32(tbPort.Text)); //4、开始链接
clientSocket.Connect(ipEndPoint);
ClientSocket = clientSocket;
ReceiveText("到服务端:" + clientSocket.RemoteEndPoint + "链接成功");
ThreadPool.QueueUserWorkItem((s) =>
{
byte[] buffer = new byte[ * ];
while (true)
{
int iReceive = ;
try
{
iReceive = clientSocket.Receive(buffer, , buffer.Length, SocketFlags.None);
}
catch
{ }
if (iReceive <= )
{
ReceiveText("断开与服务端:" + clientSocket.RemoteEndPoint + "链接");
return;
}
if (buffer[] == )
{
ReceiveText("收到服务端" + clientSocket.RemoteEndPoint + "发来的消息:" + Encoding.Default.GetString(buffer, , iReceive-));
}
else if (buffer[] == )
{
Thread th = new Thread(new ThreadStart(() =>
{
using (SaveFileDialog sfd = new SaveFileDialog())
{
if (sfd.ShowDialog() != DialogResult.OK)
{
return;
}
byte[] fileData = new byte[buffer.Length - ];
Buffer.BlockCopy(buffer, , fileData, , buffer.Length - );
using (FileStream fs = new FileStream(sfd.FileName, FileMode.Create, FileAccess.Write))
{
using (StreamWriter sw = new StreamWriter(fs, Encoding.Default))
{
sw.Write(Encoding.Default.GetString(fileData, , fileData.Length));
}
}
}
}));
th.SetApartmentState(ApartmentState.STA);
th.Start();
}
}
},clientSocket);
}
private void ReceiveText(string str)
{
if (rtbReceive.InvokeRequired)
{
rtbReceive.Invoke(new Action<string>((s) =>
{
rtbReceive.Text = string.Format("{0}\r\n{1}", str, rtbReceive.Text);
}), str);
}
else
{
rtbReceive.Text = string.Format("{0}\r\n{1}", str, rtbReceive.Text);
}
} private void btSend_Click(object sender, EventArgs e)
{
byte[] data = Encoding.Default.GetBytes(tbSend.Text);
byte[] buffer = new byte[data.Length+];
buffer[] = ;
Buffer.BlockCopy(data, , buffer, , data.Length);
ClientSocket.Send(buffer, , buffer.Length, SocketFlags.None);
} private void btSendFile_Click(object sender, EventArgs e)
{
string str = "";
Thread th = new Thread(new ThreadStart(() =>
{
using (OpenFileDialog ofd = new OpenFileDialog())
{
if (ofd.ShowDialog() != DialogResult.OK)
{
return;
}
if (tbSendFileName.InvokeRequired)
{
tbSendFileName.Invoke(new Action<string>(delegate(string s) { this.tbSendFileName.Text = s; }), ofd.FileName);
}
else
{
this.tbSendFileName.Text = ofd.FileName;
} using (FileStream fs = new FileStream(ofd.FileName, FileMode.Open, FileAccess.Read))
{
using (StreamReader sr = new StreamReader(fs,Encoding.Default))
{
if (!sr.EndOfStream)
{
str = str + sr.ReadToEnd();
}
}
}
}
byte[] data = Encoding.Default.GetBytes(str); byte[] buffer = new byte[data.Length + ];
buffer[] = ;
Buffer.BlockCopy(data, , buffer, , data.Length);
ClientSocket.Send(buffer, , buffer.Length, SocketFlags.None);
ReceiveText("发送文件到:" + ClientSocket.RemoteEndPoint + "成功");
}));
th.SetApartmentState(ApartmentState.STA);
th.Start();
} private void ClientFrm_FormClosed(object sender, FormClosedEventArgs e)
{
ClientSocket.Shutdown(SocketShutdown.Both);
}
}
}
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) == )
{
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("宋体", ), new SolidBrush(Color.Blue), new PointF(image.Width - ( * str.Length), image.Height - ));//绘制文字到上传的图片
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(, );
Graphics g = Graphics.FromImage(smallImage);
g.DrawImage(image, new Rectangle(, , , ), new Rectangle(, , 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:全局变量,也可以用来存储数据。
ASP.NET相关的更多相关文章
- asp.net相关的一些代码
显示目录下的内容 using System.IO; DirectoryInfo di = new DirectoryInfo(Server.MapPath("Views/video" ...
- ASP.NET相关事件及JS的执行顺序
实验代码: ASPX: <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="We ...
- ASP.NET相关技术整理
- ASP.NET 相关小知识
后台修改前台html控件属性 添加 runat=server ,后台获取// 客户端隐藏 a.Attributes[ "style "] = "display:none ...
- Asp.net相关知识和经验的碎片化记录
1.解决IIS7.0下“HTTP 错误 404.15 - Not Found 请求筛选模块被配置为拒绝包含的查询字符串过长的请求”问题 方案1:在程序的web.config中system.web节点里 ...
- 分享阿里云推荐码 IC1L2A,购买服务器可以直接打9折,另附阿里云服务器部署ASP.NET MVC5关键教程
阿里云推荐码为:IC1L2A 阿里云还是不错滴. 以windows server 2008 R2为例,介绍如何从全新的服务器部署MVC5 站点. 新购买的阿里云服务器是没有IIS的,要安装IIS: 控 ...
- 解读ASP.NET 5 & MVC6系列(4):核心技术与环境配置
asp.net 5是下一代的asp.net,该版本进行了全部重写以适用于跨平台,新新版本中,微软引入了如下工具与命令:DNVM.DNX.DNU. DNVM(.NET Version Manager): ...
- 初识ASP.NET Core 1.0
本文将对微软下一代ASP.NET框架做个概括性介绍,方便大家进一步熟悉该框架. 在介绍ASP.NET Core 1.0之前有必要澄清一些产品名称及版本号.ASP.NET Core1.0是微软下一代AS ...
- ASP.NET MVC 从零开始 - Web.config
这篇文章是从我的 github 博客 http://lxconan.github.io 导入的. 在上一篇中,我们从零开始创建了一个非常简单的 ASP.NET MVC 应用程序.接下来,你是不是期望我 ...
随机推荐
- 【转】 Pro Android学习笔记(四七):Dialog(4):一些补充和思考
目录(?)[-] 编程思想封装接口 fragment和activity以其他fragment之间的通信 编程思想:封装接口 在小例子中,fragment会调用activity的onDialogDone ...
- js---window对象的三种窗口
============================================================================ window对象的三种窗口.html < ...
- sql 根据年份、月份查询数据
CREATE TABLE [dbo].[T_UserAccess]( ,) NOT NULL, [UserId] [int] NULL, [UserType] [int] NULL, ) NULL, ...
- linux日常管理-防火墙netfilter工具-iptables-1
防火墙的名字叫 netfilter 工具/命令叫iptables 命令:iptables 选项: -t 指定表 -A 在最上面增加一条规则 -I 在最下面增加一条规则 -D 删除一条规则 -A-I ...
- day18-事务与连接池 4.事务特性
- [51nod1058]求N!的长度
法1:stirling公式近似 $n! \approx \sqrt {2\pi n} {(\frac{n}{e})^n}$ (如果怕n不够大下式不成立,可以当数小于10000时用for求阶层) 也可以 ...
- (转)JAVA中的权限修饰符
注:本博文是转载的,原文地址:http://blog.csdn.net/xk632172748/article/details/51755438 Java中修饰符总结: 访问控制修饰符 访问控制修饰符 ...
- Installshield build all installer in development computer
Step: Copy all "SetupPrerequisites" from build server. please make sure below items: Insta ...
- hadoop slf4j-api 1.6.x (or later) is incompatible with this binding
hadoop slf4j-api 1.6.x (or later) is incompatible with this binding 解决方法: 在POM文件最前面加入: <dependenc ...
- C++基础之多态性和动态联编
(1)多态性是指相同的函数名对应不同的实现.多态性采用两种方式:重载方式和覆盖方式.重载方式表现在函数重载和运算符重载:覆盖方式表现在基类与派生类中相同说明的函数.(2)函数重载要求被重载的函数应该在 ...