亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C# > 正文

基于C#的socket編程的TCP異步的實現代碼

2020-01-24 00:56:56
字體:
來源:轉載
供稿:網友

一、摘要

本篇闡述基于TCP通信協議的異步實現。

二、實驗平臺

Visual Studio 2010

三、異步通信實現原理及常用方法

3.1 建立連接 

在同步模式中,在服務器上使用Accept方法接入連接請求,而在客戶端則使用Connect方法來連接服務器。相對地,在異步模式下,服務器可以使用BeginAccept方法和EndAccept方法來完成連接到客戶端的任務,在客戶端則通過BeginConnect方法和EndConnect方法來實現與服務器的連接。

BeginAccept在異步方式下傳入的連接嘗試,它允許其他動作而不必等待連接建立才繼續執行后面程序。在調用BeginAccept之前,必須使用Listen方法來偵聽是否有連接請求,BeginAccept的函數原型為:

BeginAccept(AsyncCallback AsyncCallback, Ojbect state)

參數:

AsyncCallBack:代表回調函數

state:表示狀態信息,必須保證state中包含socket的句柄

使用BeginAccept的基本流程是:

(1)創建本地終節點,并新建套接字與本地終節點進行綁定;

(2)在端口上偵聽是否有新的連接請求;

(3)請求開始接入新的連接,傳入Socket的實例或者StateOjbect的實例。

參考代碼:

//定義IP地址IPAddress local = IPAddress.Parse("127.0,0,1");IPEndPoint iep = new IPEndPoint(local,13000);//創建服務器的socket對象Socket server = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);server.Bind(iep);server.Listen(20);server.BeginAccecpt(new AsyncCallback(Accept),server);

當BeginAccept()方法調用結束后,一旦新的連接發生,將調用回調函數,而該回調函數必須包括用來結束接入連接操作的EndAccept()方法。

該方法參數列表為 Socket EndAccept(IAsyncResult iar)

下面為回調函數的實例:

void Accept(IAsyncResult iar){ //還原傳入的原始套接字 Socket MyServer = (Socket)iar.AsyncState; //在原始套接字上調用EndAccept方法,返回新的套接字 Socket service = MyServer.EndAccept(iar);}

至此,服務器端已經準備好了??蛻舳藨ㄟ^BeginConnect方法和EndConnect來遠程連接主機。在調用BeginConnect方法時必須注冊相應的回調函數并且至少傳遞一個Socket的實例給state參數,以保證EndConnect方法中能使用原始的套接字。下面是一段是BeginConnect的調用:

Socket socket=new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp)IPAddress ip=IPAddress.Parse("127.0.0.1");IPEndPoint iep=new IPEndPoint(ip,13000);socket.BeginConnect(iep, new AsyncCallback(Connect),socket);

EndConnect是一種阻塞方法,用于完成BeginConnect方法的異步連接誒遠程主機的請求。在注冊了回調函數后必須接收BeginConnect方法返回的IASynccReuslt作為參數。下面為代碼演示:

void Connect(IAsyncResult iar){ Socket client=(Socket)iar.AsyncState; try {  client.EndConnect(iar); } catch (Exception e) {  Console.WriteLine(e.ToString()); } finally { }}

除了采用上述方法建立連接之后,也可以采用TcpListener類里面的方法進行連接建立。下面是服務器端對關于TcpListener類使用BeginAccetpTcpClient方法處理一個傳入的連接嘗試。以下是使用BeginAccetpTcpClient方法和EndAccetpTcpClient方法的代碼:

public static void DoBeginAccept(TcpListener listner){ //開始從客戶端監聽連接 Console.WriteLine("Waitting for a connection"); //接收連接 //開始準備接入新的連接,一旦有新連接嘗試則調用回調函數DoAcceptTcpCliet listner.BeginAcceptTcpClient(new AsyncCallback(DoAcceptTcpCliet), listner);}//處理客戶端的連接public static void DoAcceptTcpCliet(IAsyncResult iar){ //還原原始的TcpListner對象 TcpListener listener = (TcpListener)iar.AsyncState; //完成連接的動作,并返回新的TcpClient TcpClient client = listener.EndAcceptTcpClient(iar); Console.WriteLine("連接成功");}

代碼的處理邏輯為:

(1)調用BeginAccetpTcpClient方法開開始連接新的連接,當連接視圖發生時,回調函數被調用以完成連接操作;

(2)上面DoAcceptTcpCliet方法通過AsyncState屬性獲得由BeginAcceptTcpClient傳入的listner實例;

(3)在得到listener對象后,用它調用EndAcceptTcpClient方法,該方法返回新的包含客戶端信息的TcpClient。

BeginConnect方法和EndConnect方法可用于客戶端嘗試建立與服務端的連接,這里和第一種方法并無區別。下面看實例:

public void doBeginConnect(IAsyncResult iar){ Socket client=(Socket)iar.AsyncState; //開始與遠程主機進行連接 client.BeginConnect(serverIP[0],13000,requestCallBack,client); Console.WriteLine("開始與服務器進行連接");}private void requestCallBack(IAsyncResult iar){ try {  //還原原始的TcpClient對象  TcpClient client=(TcpClient)iar.AsyncState;  //  client.EndConnect(iar);  Console.WriteLine("與服務器{0}連接成功",client.Client.RemoteEndPoint); } catch(Exception e) {  Console.WriteLine(e.ToString()); } finally { }}

以上是建立連接的兩種方法。可根據需要選擇使用。 

3.2 發送與接受數據

在建立了套接字的連接后,就可以服務器端和客戶端之間進行數據通信了。異步套接字用BeginSend和EndSend方法來負責數據的發送。注意在調用BeginSend方法前要確保雙方都已經建立連接,否則會出異常。下面演示代碼:

private static void Send(Socket handler, String data){ // Convert the string data to byte data using ASCII encoding.   byte[] byteData = Encoding.ASCII.GetBytes(data); // Begin sending the data to the remote device.   handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler);}private static void SendCallback(IAsyncResult ar){ try {  // Retrieve the socket from the state object.    Socket handler = (Socket)ar.AsyncState;  // Complete sending the data to the remote device.    int bytesSent = handler.EndSend(ar);  Console.WriteLine("Sent {0} bytes to client.", bytesSent);  handler.Shutdown(SocketShutdown.Both);  handler.Close(); } catch (Exception e) {  Console.WriteLine(e.ToString()); }}

接收數據是通過BeginReceive和EndReceive方法:

private static void Receive(Socket client){ try {  // Create the state object.    StateObject state = new StateObject();  state.workSocket = client;  // Begin receiving the data from the remote device.    client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state); } catch (Exception e) {  Console.WriteLine(e.ToString()); }}private static void ReceiveCallback(IAsyncResult ar){ try {  // Retrieve the state object and the client socket    // from the asynchronous state object.    StateObject state = (StateObject)ar.AsyncState;  Socket client = state.workSocket;  // Read data from the remote device.    int bytesRead = client.EndReceive(ar);  if (bytesRead > 0)  {   // There might be more data, so store the data received so far.     state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));   // Get the rest of the data.     client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);  }  else  {   // All the data has arrived; put it in response.     if (state.sb.Length > 1)   {    response = state.sb.ToString();   }   // Signal that all bytes have been received.     receiveDone.Set();  } } catch (Exception e) {  Console.WriteLine(e.ToString()); }}

上述代碼的處理邏輯為:

(1)首先處理連接的回調函數里得到的通訊套接字client,接著開始接收數據;

(2)當數據發送到緩沖區中,BeginReceive方法試圖從buffer數組中讀取長度為buffer.length的數據塊,并返回接收到的數據量bytesRead。最后接收并打印數據。

除了上述方法外,還可以使用基于NetworkStream相關的異步發送和接收方法,下面是基于NetworkStream相關的異步發送和接收方法的使用介紹。

NetworkStream使用BeginRead和EndRead方法進行讀操作,使用BeginWreite和EndWrete方法進行寫操作,下面看實例:

static void DataHandle(TcpClient client){ TcpClient tcpClient = client; //使用TcpClient的GetStream方法獲取網絡流 NetworkStream ns = tcpClient.GetStream(); //檢查網絡流是否可讀 if(ns.CanRead) { //定義緩沖區 byte[] read = new byte[1024]; ns.BeginRead(read,0,read.Length,new AsyncCallback(myReadCallBack),ns);  } else { Console.WriteLine("無法從網絡中讀取流數據"); }}public static void myReadCallBack(IAsyncResult iar){ NetworkStream ns = (NetworkStream)iar.AsyncState; byte[] read = new byte[1024]; String data = ""; int recv; recv = ns.EndRead(iar); data = String.Concat(data, Encoding.ASCII.GetString(read, 0, recv)); //接收到的消息長度可能大于緩沖區總大小,反復循環直到讀完為止 while (ns.DataAvailable) {  ns.BeginRead(read, 0, read.Length, new AsyncCallback(myReadCallBack), ns); } //打印 Console.WriteLine("您收到的信息是" + data);}

 

3.3 程序阻塞與異步中的同步問題

.Net里提供了EventWaitHandle類來表示一個線程的同步事件。EventWaitHandle即事件等待句柄,他允許線程通過操作系統互發信號和等待彼此的信號來達到線程同步的目的。這個類有2個子類,分別為AutoRestEevnt(自動重置)和ManualRestEvent(手動重置)。下面是線程同步的幾個方法:

(1)Rset方法:將事件狀態設為非終止狀態,導致線程阻塞。這里的線程阻塞是指允許其他需要等待的線程進行阻塞即讓含WaitOne()方法的線程阻塞;

(2)Set方法:將事件狀態設為終止狀態,允許一個或多個等待線程繼續。該方法發送一個信號給操作系統,讓處于等待的某個線程從阻塞狀態轉換為繼續運行,即WaitOne方法的線程不在阻塞;

(3)WaitOne方法:阻塞當前線程,直到當前的等待句柄收到信號。此方法將一直使本線程處于阻塞狀態直到收到信號為止,即當其他非阻塞進程調用set方法時可以繼續執行。

public static void StartListening(){ // Data buffer for incoming data.   byte[] bytes = new Byte[1024]; // Establish the local endpoint for the socket.   // The DNS name of the computer   // running the listener is "host.contoso.com".   //IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName()); //IPAddress ipAddress = ipHostInfo.AddressList[0]; IPAddress ipAddress = IPAddress.Parse("127.0.0.1"); IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000); // Create a TCP/IP socket.   Socket listener = new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp); // Bind the socket to the local   //endpoint and listen for incoming connections.   try {  listener.Bind(localEndPoint);  listener.Listen(100);  while (true)  {   // Set the event to nonsignaled state.     allDone.Reset();   // Start an asynchronous socket to listen for connections.     Console.WriteLine("Waiting for a connection...");   listener.BeginAccept(new AsyncCallback(AcceptCallback),listener);   // Wait until a connection is made before continuing.     allDone.WaitOne();  } } catch (Exception e) {  Console.WriteLine(e.ToString()); } Console.WriteLine("/nPress ENTER to continue..."); Console.Read();}

上述代碼的邏輯為:

(1)試用了ManualRestEvent對象創建一個等待句柄,在調用BeginAccept方法前使用Rest方法允許其他線程阻塞;

(2)為了防止在連接完成之前對套接字進行讀寫操作,務必要在BeginAccept方法后調用WaitOne來讓線程進入阻塞狀態。

當有連接接入后系統會自動調用會調用回調函數,所以當代碼執行到回調函數時說明連接已經成功,并在函數的第一句就調用Set方法讓處于等待的線程可以繼續執行。

四、實例

下面是一個實例,客戶端請求連接,服務器端偵聽端口,當連接建立之后,服務器發送字符串給客戶端,客戶端收到后并回發給服務器端。

服務器端代碼:

using System;using System.Net;using System.Net.Sockets;using System.Text;using System.Threading;// State object for reading client data asynchronously  public class StateObject{ // Client socket.   public Socket workSocket = null; // Size of receive buffer.   public const int BufferSize = 1024; // Receive buffer.   public byte[] buffer = new byte[BufferSize]; // Received data string.   public StringBuilder sb = new StringBuilder();}public class AsynchronousSocketListener{ // Thread signal.   public static ManualResetEvent allDone = new ManualResetEvent(false); public AsynchronousSocketListener() { } public static void StartListening() {  // Data buffer for incoming data.    byte[] bytes = new Byte[1024];  // Establish the local endpoint for the socket.    // The DNS name of the computer    // running the listener is "host.contoso.com".    //IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());  //IPAddress ipAddress = ipHostInfo.AddressList[0];  IPAddress ipAddress = IPAddress.Parse("127.0.0.1");  IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000);  // Create a TCP/IP socket.    Socket listener = new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp);  // Bind the socket to the local    //endpoint and listen for incoming connections.    try  {   listener.Bind(localEndPoint);   listener.Listen(100);   while (true)   {    // Set the event to nonsignaled state.      allDone.Reset();    // Start an asynchronous socket to listen for connections.      Console.WriteLine("Waiting for a connection...");    listener.BeginAccept(new AsyncCallback(AcceptCallback),listener);    // Wait until a connection is made before continuing.      allDone.WaitOne();   }  }  catch (Exception e)  {   Console.WriteLine(e.ToString());  }  Console.WriteLine("/nPress ENTER to continue...");  Console.Read(); } public static void AcceptCallback(IAsyncResult ar) {  // Signal the main thread to continue.    allDone.Set();  // Get the socket that handles the client request.    Socket listener = (Socket)ar.AsyncState;  Socket handler = listener.EndAccept(ar);  // Create the state object.    StateObject state = new StateObject();  state.workSocket = handler;  handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state); } public static void ReadCallback(IAsyncResult ar) {  String content = String.Empty;  // Retrieve the state object and the handler socket    // from the asynchronous state object.    StateObject state = (StateObject)ar.AsyncState;  Socket handler = state.workSocket;  // Read data from the client socket.    int bytesRead = handler.EndReceive(ar);  if (bytesRead > 0)  {   // There might be more data, so store the data received so far.     state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));   // Check for end-of-file tag. If it is not there, read     // more data.     content = state.sb.ToString();   if (content.IndexOf("<EOF>") > -1)   {    // All the data has been read from the      // client. Display it on the console.      Console.WriteLine("Read {0} bytes from socket. /n Data : {1}", content.Length, content);    // Echo the data back to the client.      Send(handler, content);   }   else   {    // Not all data received. Get more.      handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);   }  } } private static void Send(Socket handler, String data) {  // Convert the string data to byte data using ASCII encoding.    byte[] byteData = Encoding.ASCII.GetBytes(data);  // Begin sending the data to the remote device.    handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler); } private static void SendCallback(IAsyncResult ar) {  try  {   // Retrieve the socket from the state object.     Socket handler = (Socket)ar.AsyncState;   // Complete sending the data to the remote device.     int bytesSent = handler.EndSend(ar);   Console.WriteLine("Sent {0} bytes to client.", bytesSent);   handler.Shutdown(SocketShutdown.Both);   handler.Close();  }  catch (Exception e)  {   Console.WriteLine(e.ToString());  } } public static int Main(String[] args) {  StartListening();  return 0; }}

客戶端代碼:

using System;using System.Net;using System.Net.Sockets;using System.Threading;using System.Text;// State object for receiving data from remote device.  public class StateObject{ // Client socket.   public Socket workSocket = null; // Size of receive buffer.   public const int BufferSize = 256; // Receive buffer.   public byte[] buffer = new byte[BufferSize]; // Received data string.   public StringBuilder sb = new StringBuilder();}public class AsynchronousClient{ // The port number for the remote device.   private const int port = 11000; // ManualResetEvent instances signal completion.   private static ManualResetEvent connectDone = new ManualResetEvent(false); private static ManualResetEvent sendDone = new ManualResetEvent(false); private static ManualResetEvent receiveDone = new ManualResetEvent(false); // The response from the remote device.   private static String response = String.Empty; private static void StartClient() {  // Connect to a remote device.    try  {   // Establish the remote endpoint for the socket.     // The name of the     // remote device is "host.contoso.com".     //IPHostEntry ipHostInfo = Dns.Resolve("user");   //IPAddress ipAddress = ipHostInfo.AddressList[0];   IPAddress ipAddress = IPAddress.Parse("127.0.0.1");   IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);   // Create a TCP/IP socket.     Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);   // Connect to the remote endpoint.     client.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), client);   connectDone.WaitOne();   // Send test data to the remote device.     Send(client, "This is a test<EOF>");   sendDone.WaitOne();   // Receive the response from the remote device.     Receive(client);   receiveDone.WaitOne();   // Write the response to the console.     Console.WriteLine("Response received : {0}", response);   // Release the socket.     client.Shutdown(SocketShutdown.Both);   client.Close();   Console.ReadLine();  }  catch (Exception e)  {   Console.WriteLine(e.ToString());  } } private static void ConnectCallback(IAsyncResult ar) {  try  {   // Retrieve the socket from the state object.     Socket client = (Socket)ar.AsyncState;   // Complete the connection.     client.EndConnect(ar);   Console.WriteLine("Socket connected to {0}", client.RemoteEndPoint.ToString());   // Signal that the connection has been made.     connectDone.Set();  }  catch (Exception e)  {   Console.WriteLine(e.ToString());  } } private static void Receive(Socket client) {  try  {   // Create the state object.     StateObject state = new StateObject();   state.workSocket = client;   // Begin receiving the data from the remote device.     client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);  }  catch (Exception e)  {   Console.WriteLine(e.ToString());  } } private static void ReceiveCallback(IAsyncResult ar) {  try  {   // Retrieve the state object and the client socket     // from the asynchronous state object.     StateObject state = (StateObject)ar.AsyncState;   Socket client = state.workSocket;   // Read data from the remote device.     int bytesRead = client.EndReceive(ar);   if (bytesRead > 0)   {    // There might be more data, so store the data received so far.      state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));    // Get the rest of the data.      client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);   }   else   {    // All the data has arrived; put it in response.      if (state.sb.Length > 1)    {     response = state.sb.ToString();    }    // Signal that all bytes have been received.      receiveDone.Set();   }  }  catch (Exception e)  {   Console.WriteLine(e.ToString());  } } private static void Send(Socket client, String data) {  // Convert the string data to byte data using ASCII encoding.    byte[] byteData = Encoding.ASCII.GetBytes(data);  // Begin sending the data to the remote device.    client.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), client); } private static void SendCallback(IAsyncResult ar) {  try  {   // Retrieve the socket from the state object.     Socket client = (Socket)ar.AsyncState;   // Complete sending the data to the remote device.     int bytesSent = client.EndSend(ar);   Console.WriteLine("Sent {0} bytes to server.", bytesSent);   // Signal that all bytes have been sent.     sendDone.Set();  }  catch (Exception e)  {   Console.WriteLine(e.ToString());  } } public static int Main(String[] args) {  StartClient();  return 0; }}

五、實驗結果

圖1 服務器端界面
圖2 客戶端界面

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
中文字幕日韩免费视频| 国产欧美日韩中文| 色午夜这里只有精品| 青青a在线精品免费观看| 日韩美女视频免费在线观看| 久久中文字幕国产| 两个人的视频www国产精品| 亚洲大胆人体在线| 日韩精品免费在线播放| 中文字幕日韩av综合精品| 国产亚洲一级高清| 国产亚洲精品成人av久久ww| 国产成人福利夜色影视| 国产精品美腿一区在线看| 亚洲精品一区中文字幕乱码| 亚洲一区美女视频在线观看免费| 在线免费观看羞羞视频一区二区| 亚洲欧美激情一区| 欧美性xxxx极品hd满灌| 亚洲欧美国产一区二区三区| 国产精品美腿一区在线看| 一区二区亚洲欧洲国产日韩| 久久精品在线播放| 国产精品白丝av嫩草影院| 91禁外国网站| 久久精品国产清自在天天线| 北条麻妃一区二区三区中文字幕| 亚洲影院高清在线| 国产精品成人免费电影| 日韩经典第一页| 色偷偷91综合久久噜噜| 欧美视频在线观看 亚洲欧| 亚洲www在线| 中文字幕亚洲欧美日韩在线不卡| 欧美激情一二区| 日韩av影院在线观看| 一本色道久久综合狠狠躁篇怎么玩| 久久国产精品网站| 久久国产精品视频| 欧美日韩中文字幕在线视频| 亚洲3p在线观看| 久久精品精品电影网| 一区二区在线视频| 久久久国产精品免费| 91理论片午午论夜理片久久| 国产福利成人在线| 欧美日本中文字幕| 国产视频精品久久久| 久久久精品国产一区二区| 亚洲电影免费在线观看| 狠狠操狠狠色综合网| 亚洲系列中文字幕| 国产成人拍精品视频午夜网站| 在线观看91久久久久久| 中文字幕亚洲无线码在线一区| 国产精品日韩在线| 欧美日韩国产影院| 欧美高清在线观看| 亚洲欧美在线免费观看| 亚洲已满18点击进入在线看片| 九九热最新视频//这里只有精品| 久久久免费精品| 自拍偷拍亚洲欧美| 亚洲精品久久久久久久久久久久| 国产成人精品视频在线观看| 亚洲欧洲xxxx| 久久久久久久久久久人体| 美女视频黄免费的亚洲男人天堂| 日韩暖暖在线视频| 在线日韩日本国产亚洲| 久久影院资源网| 97av在线影院| 亚洲天天在线日亚洲洲精| 国产精品老牛影院在线观看| 成人自拍性视频| 精品久久久久久久久中文字幕| 精品成人久久av| 国产在线视频一区| 在线观看欧美日韩国产| 色伦专区97中文字幕| 欧美亚洲视频在线看网址| 7777免费精品视频| 国产欧美日韩高清| 欧美日韩亚洲视频一区| 午夜精品久久久久久久白皮肤| 亚洲精品在线视频| 中文字幕久热精品在线视频| 国产999在线观看| 浅井舞香一区二区| 欧美激情视频一区二区三区不卡| 日本一本a高清免费不卡| 91久久精品一区| 亚洲**2019国产| 欧美日韩激情视频| 538国产精品一区二区在线| 一个色综合导航| 日韩精品中文字幕视频在线| 成人黄色短视频在线观看| 久久久久久久久久久av| 亚洲欧美国产一本综合首页| 欧美最顶级丰满的aⅴ艳星| 中文字幕日韩欧美| 国产视频亚洲视频| 亚洲国产精品99| 久久理论片午夜琪琪电影网| 国产成人在线一区| 欧美激情视频给我| 欧美国产日韩一区二区| 国产精品久久久久久久美男| 国产一区二区香蕉| 久久999免费视频| 国产91精品久久久久久久| 国产日韩中文字幕在线| 中文字幕av一区二区| 色诱女教师一区二区三区| 精品日韩视频在线观看| 欧美性猛交xxxx偷拍洗澡| 国产精品视频一区国模私拍| 亚洲第一区第一页| 欧美性一区二区三区| 亚洲国产成人精品一区二区| 91美女高潮出水| 精品激情国产视频| 黄色一区二区在线| 国产精品黄页免费高清在线观看| 中文字幕日韩av综合精品| 91免费电影网站| 2023亚洲男人天堂| 国产精品福利网站| 国产有码在线一区二区视频| 久久综合免费视频影院| 国产成人一区二区| 欧美一区二区大胆人体摄影专业网站| 久久国产精品网站| 日韩久久午夜影院| 亚洲精品视频网上网址在线观看| 亚洲已满18点击进入在线看片| 欧美视频一区二区三区…| 欧美激情第6页| 91网站免费观看| 国产91亚洲精品| 欧美日本精品在线| 欧美成人免费视频| 日韩毛片在线看| 日韩av免费在线观看| 亚洲社区在线观看| 亚洲三级 欧美三级| 91久久在线播放| 亚洲自拍小视频免费观看| 亚洲国产精品久久久久| 91大神福利视频在线| 欧美在线视频免费播放| 成人美女免费网站视频| 亚洲第一级黄色片| 性欧美长视频免费观看不卡| 精品久久久视频| 在线精品播放av| 亚洲aa在线观看| 国产精品久久久久久av福利软件| 国产视频欧美视频| 国产精品wwww| 亚洲精品99久久久久| 日韩视频在线观看免费| 久久久成人的性感天堂|