一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - Java教程 - java實現(xiàn)基于Tcp的socket聊天程序

java實現(xiàn)基于Tcp的socket聊天程序

2021-05-19 14:12紫色的海丶 Java教程

這篇文章主要為大家詳細(xì)介紹了java實現(xiàn)基于Tcp的socket聊天程序,具有一定的參考價值,感興趣的小伙伴們可以參考一下

對于步入編程行業(yè)不深的初學(xué)者或是已經(jīng)有所領(lǐng)會的人來說,當(dāng)學(xué)習(xí)一項新的技術(shù)的時候,非常渴望有一個附上注釋完整的demo。本人深有體會,網(wǎng)上的例子多到是很多,但是很雜不完整,寫代碼這種東西來不得半點(diǎn)馬虎,要是錯了一點(diǎn),那也是運(yùn)行不了的。這對于初學(xué)者來說更加的頭疼,因為他根本不知道錯在哪里,盲目的改只能錯上加錯。最后不得不去找找看看有沒有能夠直接運(yùn)行的例子再加以模仿。

下面是博主在學(xué)習(xí)javasocket時寫的一個完整的例子,并且?guī)狭送暾淖⑨尅K且粋€簡單的聊天程序,但是它可以設(shè)置任意多用戶同時登錄,然后相互兩兩交流。博主僅僅在自己電腦上實現(xiàn)同時登錄,然后兩兩相互交流。

程序的大體思路是這樣的:

①該用戶作為服務(wù)端也就是被請求連接端和主動請求連接其他端時不一樣的,其次有可能被其他的用戶連接很多次,那么你作為服務(wù)端,就會有很多連接,同樣的道理,你作為客戶端也會有很多的連接。為了程序更加通俗易懂,博主寫的時候,設(shè)置了很多容器,將不一樣的東西分開放置。做到解耦合,不然到后面自己都分不清了。

②你可以一次寫兩個類,client1,client2,,client1先作為服務(wù)端,client2作為客戶端,客戶端去連接服務(wù)端,從而實現(xiàn)client1的服務(wù)端功能和client2的客戶端功能。每次實現(xiàn)一個功能就先將服務(wù)端和客戶端的功能整合一下,互換角色,看是否存在錯誤。

③在實現(xiàn)了兩個用戶的情況下再去寫第三個類client3,代碼就是復(fù)制粘貼。當(dāng)然你也可以直接創(chuàng)建一個client3的類,然后直接在類的main方法中改了端口號,和用戶名就行。第三個實現(xiàn)后,第四個第五個也就實了。

下面是具體的代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
package jack;
 
import java.awt.list;
import java.awt.event.actionevent;
import java.awt.event.actionlistener;
import java.io.bufferedreader;
import java.io.datainputstream;
import java.io.dataoutputstream;
import java.io.eofexception;
import java.io.ioexception;
import java.io.inputstream;
import java.io.inputstreamreader;
import java.io.printwriter;
import java.net.serversocket;
import java.net.socket;
import java.time.format.textstyle;
import java.util.arraylist;
 
import javax.swing.jbutton;
import javax.swing.jframe;
import javax.swing.jlabel;
import javax.swing.jpanel;
import javax.swing.jscrollpane;
import javax.swing.jtabbedpane;
import javax.swing.jtextarea;
import javax.swing.jtextfield;
import javax.swing.jtoolbar;
import javax.swing.plaf.basic.basictabbedpaneui.tabbedpanelayout;
import javax.xml.bind.annotation.adapters.xmljavatypeadapter.default;
 
import org.omg.corba.private_member;
/**
 * 被請求連接時稱為服務(wù)器;主動連接對方時稱為客戶端。
 * @author administrator
 *
 */
public class client4 extends jframe implements actionlistener{
 
 private static int sign = 0;    //用來記錄選項卡的標(biāo)簽,0標(biāo)示第一個。
 private jtoolbar toolbar1,toolbar2;
 private jlabel waitportlabel,hostlabel,portlabel;
 private jtextfield waitporttf,hosttf,porttf,sendtf;
 private jtabbedpane tab;
 private jbutton sendb,leaveb,deleteb,connb;
 private arraylist<chatthread> serverthreads; //存放服務(wù)器線程的容器。即存放被請求連接時所創(chuàng)建的線程的容器。
 private arraylist<chatthread> clientthreads; //存放客戶端線程的容器。即存放主動連接對方時所創(chuàng)建的線程的容器。
 private arraylist<serversocket> servers;  //服務(wù)對象的容器。
 private arraylist<myjtextarea> servertextareas; //作為服務(wù)器時,存放所創(chuàng)建的對話記錄顯示區(qū)域的容器。
 private arraylist<myjtextarea> clienttextareas; //作為客戶端時,岑芳所創(chuàng)建的對話記錄顯示區(qū)域的容器。
 private arraylist<socket> serversockets;  //存放被請求連接時所創(chuàng)建的socket的容器。
 private arraylist<socket> clientsockets; //存放主動請求連接時所創(chuàng)立的socket的容器。
 private arraylist<printwriter> serverpwriters;  //存放服務(wù)端輸出流對象的容器。
 private arraylist<bufferedreader> serverbreaders; //存放服務(wù)端輸入流對象的容器。
 private arraylist<printwriter> clientpwriters;  //存放客戶端輸出流對象的容器。
 private arraylist<bufferedreader> clientbreaders; //存放客戶端輸入流對象的容器。
 private arraylist<integer> ports;  //存放作為服務(wù)器時已連接的端口。
 private int port = 2041; //指定自己開放的第一個端口號,方便其他人連接。
 private string name;     //儲存自己的名稱。
 
 public client4(string name) throws ioexception{
 super(name);
 this.name = name;    
 toolbar1 = new jtoolbar();
 toolbar2 = new jtoolbar();
 waitportlabel = new jlabel("等待端口");
 hostlabel = new jlabel("主機(jī)");
 portlabel = new jlabel("端口");
 waitporttf = new jtextfield("2041");
 hosttf = new jtextfield("127.0.0.1");
 porttf = new jtextfield(5);
 sendtf = new jtextfield();
 tab = new jtabbedpane();
 sendb = new jbutton("發(fā)送");
 leaveb = new jbutton("離線");
 deleteb = new jbutton("刪除頁");
 connb = new jbutton("連接端口");
 
 servers = new arraylist<serversocket>();
 servertextareas = new arraylist<myjtextarea>();
 clienttextareas = new arraylist<myjtextarea>();
 serversockets = new arraylist<socket>();
 clientsockets = new arraylist<socket>();
 serverpwriters = new arraylist<printwriter>();
 serverbreaders = new arraylist<bufferedreader>();
 clientpwriters = new arraylist<printwriter>();
 clientbreaders = new arraylist<bufferedreader>();
 serverthreads = new arraylist<chatthread>();
 clientthreads = new arraylist<chatthread>();
 ports = new arraylist<integer>();
 
 toolbar1.add(waitportlabel);
 toolbar1.add(waitporttf);
 toolbar1.add(hostlabel);
 toolbar1.add(hosttf);
 toolbar1.add(portlabel);
 toolbar1.add(porttf);
 toolbar1.add(connb);
 
 toolbar2.add(sendtf);
 toolbar2.add(sendb);
 toolbar2.add(leaveb);
 toolbar2.add(deleteb);
 
 waitporttf.setenabled(false);   //設(shè)置等待的textfield不可以編輯。
 hosttf.setenabled(false); //設(shè)置連接的ip地址不可編輯,當(dāng)然這里可以更改成其他電腦的ip地址。
 this.getcontentpane().add(toolbar1, "north"); //添加工具欄到最上方。
 this.getcontentpane().add(tab,"center"); //添加選項卡窗格。
 this.getcontentpane().add(toolbar2,"south"); //添加工具欄到下方。
 
 this.setbounds(200, 200, 350, 300);
 this.setvisible(true);
 this.setdefaultcloseoperation(jframe.exit_on_close);
 
 sendb.addactionlistener(this);
 leaveb.addactionlistener(this);
 deleteb.addactionlistener(this);
 connb.addactionlistener(this);
 
 //主線程進(jìn)入之后 在server.accept()阻塞等待客戶端來連接。
 while(true){
 serversocket server = new serversocket(port); //作為服務(wù)器,開發(fā)自己供連接的端口。
 servers.add(server); 
 socket serversocket = server.accept();  //等待對方連接。
 serversockets.add(serversocket);
 ports.add(port);   //將已連接的端口加入容器。
 printwriter serverpwriter = new printwriter(serversocket.getoutputstream(),true);//初始化輸出流對象。
 serverpwriters.add(serverpwriter);
 bufferedreader serverbreader = new bufferedreader(new inputstreamreader(serversocket.getinputstream()));//初始化輸入流對象。
 serverbreaders.add(serverbreader);
 serverpwriter.println("連接"+name+"成功");  //將連接成功的消息發(fā)送給請求方,提醒對方連接成功。
 serverpwriter.println(name);  //將自己的名稱發(fā)送給對方,方便對方設(shè)置選項卡的名稱。
 string content = serverbreader.readline();  //此時對方也發(fā)送了上面兩條消息過來。讀入對方發(fā)送過來的提醒消息。
 string name2 = serverbreader.readline(); //讀取對方的名稱。方便后面設(shè)置選項卡的名稱。
 system.out.println(content);
 system.out.println(name2);
 myjtextarea servertextarea = new myjtextarea(sign);
 sign++;      //new了一個textarea后,sign自動增加1,好和選項卡對應(yīng),
       //知道這個選項卡加到哪個容器了,是服務(wù)器的還是客戶端的。
 servertextareas.add(servertextarea);
 this.tab.addtab(name2,new jscrollpane(servertextarea));//在選項卡窗格中添加一個選項卡。
 servertextarea.seteditable(false); //設(shè)置對話記錄顯示區(qū)域不可編輯。
 servertextarea.setlinewrap(true); //設(shè)置對話記錄顯示區(qū)域自動換行。
 servertextarea.append(content+"\n"); //在對話記錄區(qū)域輸出連接成功這條消息。
 chatthread thread = new chatthread(); //new了一個線程去執(zhí)行run方法,用于和對方交流,對方也會開啟一個線程來和你交流。
  //這里要開啟新線程的原因是main線程經(jīng)過一輪后會在上面accept方法處阻塞。
 serverthreads.add(thread);
 thread.start();     //啟動該線程,方便接收對方發(fā)來的消息。
 port++;  //端口號加一,開放下一個供連接的端口。
 waitporttf.settext(port+"");   //更新顯示等待的下個端口。
 }
 }
 
 private class chatthread extends thread {
 
 private string[] servercontents = new string[10]; //當(dāng)作為服務(wù)端時,用來存放相互發(fā)送消息時的一句話。
 private string[] clientcontents = new string[10]; //當(dāng)作為客戶端時,用來存放相互發(fā)送消息時的一句話。
 private boolean isserverthread = true//判斷當(dāng)前在執(zhí)行run方法的線程是不是服務(wù)端線程。
 
 @override
 public void run() {
 
 while(true){
 if(serverthreads.size()>0){ //判斷當(dāng)前的線程是否是服務(wù)線程。先判斷是否大于0,是為了防止serverthreads
 for(int i=0;i<serverthreads.size();i++){ //報數(shù)組越界。
 if(thread.currentthread() == serverthreads.get(i)){ //拿當(dāng)前線程和服務(wù)端容器里的線程去比,看是否是服務(wù)端的線程。
 isserverthread = true;
 }
 }
 }
 
 if(clientthreads.size()>0){   //判斷當(dāng)前的線程是否是客戶線程。 先判斷是否大于0,是為了防止clientthreads
 for(int i=0;i<clientthreads.size();i++){ //報數(shù)組越界。
 if(thread.currentthread() == clientthreads.get(i)){ //拿當(dāng)前線程和客戶端容器里的線程去比,看是否是客戶端的線程。
 isserverthread = false;
 }
 }
 }
 
 if(isserverthread){   //如果是服務(wù)端的線程,將readline方法接受到的值賦給相應(yīng)的content。
 for(int i=0;i<serverthreads.size();i++){
 if(thread.currentthread() == serverthreads.get(i)){ //判斷具體是服務(wù)端里的那條線程。
 try {
 servercontents[i] = serverbreaders.get(i).readline();//將對方發(fā)送過來的消息賦值給這條線程的接受消息字符串。
 } catch (ioexception e) {
 e.printstacktrace();
 return//出現(xiàn)異常時直接退出方法。
 }
 if(servercontents[i]==null){  //在自己點(diǎn)擊離線按鈕時,servercontents[i]為null,
 return//因此在這里進(jìn)行處理,避免后面報錯。
 }
 if(servercontents[i].equals("關(guān)閉")){ //接收到對方因點(diǎn)擊離開按鈕而發(fā)出的消息“離開”,關(guān)閉自己的連接。
 sendtf.settext("已斷開連接");
 serverpwriters.get(i).close();
 try {
  serverbreaders.get(i).close();
  serversockets.get(i).close();
 } catch (ioexception e) {
  e.printstacktrace();
 }
 return;    //關(guān)閉完后退出。
 }
 servertextareas.get(i).append(servercontents[i]+"\n");//將接受到的消息顯示在自己的對話記錄區(qū)域。
 break;
 }
 
 }
 }else{    //如果是客戶線程,將readline方法接受到的值賦給相應(yīng)的content。
 for(int i=0;i<clientthreads.size();i++){
 if(thread.currentthread() == clientthreads.get(i)){ //判斷具體是客戶端中的哪一條線程。
 try {
 clientcontents[i] = clientbreaders.get(i).readline();//拿到對方發(fā)送過來的消息并保存給自己的字符串。
 } catch (ioexception e) {
 e.printstacktrace();
 }
 if(clientcontents[i] == null){ //當(dāng)自己點(diǎn)擊離線按鈕時,clientcontents[i]會為null,
 return; //為了防止下面報錯,在這里進(jìn)行處理。
 }
 if(clientcontents[i].equals("關(guān)閉")){ //接收到對方因點(diǎn)擊離線按鈕而發(fā)出的消息“關(guān)閉”,而關(guān)閉自己的連接。
 sendtf.settext("已斷開連接");
 clientpwriters.get(i).close();
 try {
  clientbreaders.get(i).close();
  clientsockets.get(i).close();
 } catch (ioexception e) {
  e.printstacktrace();
 }
 return;
 }
 clienttextareas.get(i).append(clientcontents[i]+"\n");//作為客戶端時,將接受到的消息顯示在對話記錄顯示區(qū)域。
 break;
 }
 }
 }
 }
 }
 }
 
 @override
 public void actionperformed(actionevent e) {
 switch(e.getactioncommand()){
 case "連接端口":      //如果是連接端口,則執(zhí)行以下操作。
 try {
 socket clientsocket = new socket(hosttf.gettext(),integer.parseint(porttf.gettext()));//拿到工具欄一中填的端口號并生成socket去連接對方。
 clientsockets.add(clientsocket);
 printwriter clientpwriter = new printwriter(clientsocket.getoutputstream(),true);//初始化輸出流對象。
 clientpwriters.add(clientpwriter);
 bufferedreader clientbreader = new bufferedreader(new inputstreamreader(clientsocket.getinputstream()));//初始化輸入流對象。
 clientbreaders.add(clientbreader);
 clientpwriter.println("連接"+name+"成功");  //將連接成功的消息發(fā)送給對方,提醒對方連接成功。
 clientpwriter.println(name); //將自己的名稱發(fā)送給對方,方便對方設(shè)置選項卡的名稱。
 system.out.println(11111111);
 string content = clientbreader.readline(); //讀入對方發(fā)送過來的提醒消息。對方已執(zhí)行了上面兩條語句,發(fā)送了對應(yīng)的消息。
 system.out.println(22222222);
 string name2 = clientbreader.readline(); //讀取對方的名稱。
 system.out.println(content);
 system.out.println(name2);
 myjtextarea clienttextarea = new myjtextarea(sign);
 sign++;  //配和選項卡的index,記錄每個選項卡加到那個容器里去了,是服務(wù)器的容器還是客戶端的容器。
 clienttextareas.add(clienttextarea);
 this.tab.addtab(name2,new jscrollpane(clienttextarea)); //在選項卡窗格中添加一個選項卡。
 clienttextarea.seteditable(false);  //設(shè)置對話記錄區(qū)域不可編輯。
 clienttextarea.setlinewrap(true);  //設(shè)置對話記錄區(qū)域自動換行。
 clienttextarea.append(content+"\n"); //在對話記錄區(qū)域顯示連接成功這條消息。
 chatthread clientthread = new chatthread();
 clientthreads.add(clientthread);
 clientthread.start();    //啟動該線程,方便和對方相互發(fā)送消息,因為主線程已經(jīng)在上面accept()處阻塞。
 } catch (ioexception e1) {
 e1.printstacktrace();
 }
 break;
 case "發(fā)送":
 if(servertextareas.size()>0){    //如果是被請求連接時而創(chuàng)建的選項卡要發(fā)送消息。即服務(wù)端。
 for(int i=0;i<servertextareas.size();i++){
 if(tab.getselectedindex() == servertextareas.get(i).getsign()){ //通過獲取當(dāng)前選項卡的index去和jtextarea的sign比,因為他們的index和sign是匹配的,
 string sendcontent = sendtf.gettext(); //從而確定它是服務(wù)端的哪條線程,該用那對輸入輸出流進(jìn)行發(fā)送和接受消息。
 if(serversockets.get(i).isclosed()){ //如果已斷開連接,則直接返回。
 sendtf.settext("已斷開連接");
 return;
 }
 if(sendcontent.equals("")){  //如果發(fā)送的內(nèi)容為空則直接接結(jié)束。
 sendtf.settext("請輸入內(nèi)容");
 return;
 }else{
 serverpwriters.get(i).println(name+": "+sendcontent); //將發(fā)送消息框中的消息發(fā)送出去,并在前面加上自己的姓名。
 servertextareas.get(i).append("我: "+sendcontent+"\n");//在自己的對話記錄區(qū)域加上這句話。
 sendtf.settext("");     //將發(fā)送消息框中的數(shù)據(jù)清空。
 return;
 }
 
 }
 }
 }
 
 if(clienttextareas.size()>0){    //如果是客戶端。
 for(int i=0;i<clienttextareas.size();i++){
 if(tab.getselectedindex() == clienttextareas.get(i).getsign()){ //通過獲取當(dāng)前選項卡的index去和jtextarea的sign比,因為他們的index和sign是匹配的,
 string sendcontent = sendtf.gettext();   //從而確定它是客戶端的哪條線程,該用那對輸入輸出流進(jìn)行發(fā)送和接受消息。
 if(clientsockets.get(i).isclosed()){ //如果連接已斷開則直接返回。
 sendtf.settext("已斷開連接");
 return;
 }
 if(sendcontent.equals("")){  //如果發(fā)送的內(nèi)容為空則直接接結(jié)束。
 sendtf.settext("請輸入內(nèi)容");
 return;
 }else{
 clientpwriters.get(i).println(name+": "+sendcontent); //將發(fā)送消息框中的消息發(fā)送出去,并在前面加上自己的姓名。
 clienttextareas.get(i).append("我: "+sendcontent+"\n"); //在自己的對話記錄區(qū)域加上這句話
 sendtf.settext("");     //將發(fā)送消息框中的數(shù)據(jù)清空。
 return;
 }
 }
 }
 }
 
 break;
 case "離開":
 if(servertextareas.size()>0){      //如果是服務(wù)端。
 for(int i=0;i<servertextareas.size();i++){
 if(tab.getselectedindex() == servertextareas.get(i).getsign()){ //更前面一樣的道理,判斷是服務(wù)端的那個選項卡需要閉關(guān)。
 serverpwriters.get(i).println("關(guān)閉");   //發(fā)送關(guān)閉消息,提醒對方也要關(guān)閉該socket連接。
 sendtf.settext("已斷開連接");
 serverpwriters.get(i).close();
 try {
 serverbreaders.get(i).close();
 serversockets.get(i).close();   
 } catch (ioexception e1) {
 e1.printstacktrace();
 }
 break;
 }
 }
 }
 
 if(clienttextareas.size()>0){      //如果是客戶端。
 for(int i=0;i<clienttextareas.size();i++){
 if(tab.getselectedindex() == clienttextareas.get(i).getsign()){ //更前面一樣的道理,判斷是客戶端的那個選項卡需要閉關(guān)。
 clientpwriters.get(i).println("關(guān)閉");   //發(fā)送關(guān)閉消息,提醒對方也要關(guān)閉該socket連接。
 sendtf.settext("已斷開連接");
 clientpwriters.get(i).close();
 try {
 clientbreaders.get(i).close();
 clientsockets.get(i).close();   
 } catch (ioexception e1) {
 e1.printstacktrace();
 }
 break;
 }
 }
 }
 break;
 case "刪除頁":
 if(servertextareas.size()>0){ //為了防止下面的servertextareas數(shù)組越界。
 for(int i=0;i<servertextareas.size();i++){
 if(tab.getselectedindex() == servertextareas.get(i).getsign()){ //跟上面一樣的道理,判斷當(dāng)前選項卡是屬于服務(wù)端還是客戶端。
 if(serversockets.get(i).isclosed()){ //先判斷是否斷開連接,否則不允許關(guān)閉。
 tab.remove(i);  //刪除當(dāng)前選項卡。
 }else{
 sendtf.settext("請先關(guān)閉當(dāng)前的連接");
 return;
 }
 }
 }
 }
 if(clienttextareas.size()>0){ //為了防止下面的servertextareas數(shù)組越界。
 for(int i=0;i<clienttextareas.size();i++){
 if(tab.getselectedindex() == clienttextareas.get(i).getsign()){ //跟上面一樣的道理,判斷當(dāng)前選項卡是屬于服務(wù)端還是客戶端。
 if(clientsockets.get(i).isclosed()){ //先判斷是否斷開連接,否則不允許關(guān)閉。
 tab.remove(i);   //刪除當(dāng)前選項卡。
 }else{
 sendtf.settext("請先關(guān)閉當(dāng)前的連接");
 return;
 }
 }
 }
 }
 break;
 default:
 break;
 }
 }
 
 public static void main(string[] args) throws ioexception{
 new client4("喜洋洋");
 }
}

效果圖:

java實現(xiàn)基于Tcp的socket聊天程序

源碼下載:java基于tcp的socket聊天程序

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。

原文鏈接:https://blog.csdn.net/qq_34748644/article/details/64125883

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国产玖玖在线观看 | 日本中文字幕一区二区有码在线 | 范冰冰上面好大下面好紧 | 奶茶视频官网免费 | 日韩欧美推理片免费看完整版 | 2021最新国产成人精品免费 | 思思久久精品在热线热 | 国模李丽莎大尺度啪啪 | 日韩成人在线影院 | 全彩成人18h漫画 | 午夜国产精品福利在线观看 | 国产一级片视频 | 国产精品视频播放 | 五月色婷婷网在线观看 | 99久久国产综合精品网成人影院 | 万域之王在线观看 | 色综合天天五月色 | 奇米7777第四色 | 学生小泬无遮挡女HD | 国产夜趣福利第一视频 | 日韩亚洲人成在线 | 肉肉小说在线阅读 | 校花在公车上被内射好舒 | 小货SAO边洗澡边CAO你动漫 | 视频在线精品 | 91亚洲精品丁香在线观看 | 忘忧草在线社区WWW日本-韩国 | 精品无码人妻一区二区免费AV | 国产极品久久 | 国产日产精品久久久久快鸭 | 四虎精品永久免费 | 丝瓜视频黄色在线观看 | 精品无人区一区二区三区 | 色综合欧美色综合七久久 | 色偷偷91久久综合噜噜噜 | 特黄一级| 精品国产福利片在线观看 | 亚洲国产精品嫩草影院久久 | 精品一区二区三区免费站 | 我和黑色丝袜班主任 | 5g影院天天影院天天爽影院网站 |