日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java socket/Serversocket编程详解(中/英文)

發(fā)布時(shí)間:2025/4/5 编程问答 70 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java socket/Serversocket编程详解(中/英文) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

socket /套接字?

??? Sockets let you send raw streams of bytes back and forth between two computers, giving you fairly low-level access to the TCP/IP protocol. See the File I/O Amanuensis for sample code to do that. In TCP/IP each computer has a name, such as roedy.mindprod.com. However, various TCP/IP programs could be running on that computer. Each Socket gets a assigned a number called a port. The HTTP server would usually be assigned 80. DbAnywhere is usually 8889. This way you can specify which service on the local or remote machine you want to connect with. The Socket is specified like this: roedy.mindprod.com:8889.?



???? socket提供了在主機(jī)之間傳遞原始字節(jié)流的功能,以比較底層的方式訪問tcp/ip協(xié)議層.可以類似訪問文件i/o的方式實(shí)現(xiàn)這一功能(在unix 中,系統(tǒng)資源是以文件的方式進(jìn)行訪問的,其中也包括網(wǎng)絡(luò)資源).tcp/ip協(xié)議規(guī)定,每臺(tái)主機(jī)都有一個(gè)名稱,例如 roedy.mindprod.com.然而,同一臺(tái)主機(jī)上有可能同時(shí)運(yùn)行很多tcp/ip程序.每個(gè)socket被指派了一個(gè)叫做端口的數(shù)字以加以區(qū)分不同的應(yīng)用或者連接.http應(yīng)用服務(wù)器的端口一般被指定為80,DbAnywhere通常指定為8889.我們通過這種方式區(qū)分你向遠(yuǎn)程或者本地主機(jī)請(qǐng)求連接的服務(wù).一個(gè)socket被定義為 地址:端口, 例如 roedy.mindprod.com:8889?


??? Flush / 刷新?


??? If you write to a Socket, you usually need to call flush to force the data out onto the net. If you fail to do that, you could wait forever for a response because your complete query was never sent. You don’t need flush if you are sending a steady stream of data that will push earlier data out onto the net.?



???? 如果向一個(gè)socket寫入數(shù)據(jù),通常需要調(diào)用flush方法去把數(shù)據(jù)發(fā)送到網(wǎng)絡(luò).如果操作失敗,可能由于完整的請(qǐng)求信息未曾發(fā)送成功而導(dǎo)致持續(xù)等待響應(yīng).如果使用穩(wěn)定的數(shù)據(jù)流的方式,不需要調(diào)用flush方法,因?yàn)閿?shù)據(jù)流會(huì)自動(dòng)把先前的數(shù)據(jù)發(fā)送到網(wǎng)絡(luò).?



??? Blocking Read / 讀堵塞?

?? If you read from a Socket, you can hang waiting forever if you use a blocking read. Socket.setSoTimeout controls the timeout. The read will eventually die when the Socket connection fails. This will happen when:?

??????? * You close the Socket at this end.?
??????? * The far end sends a disconnect signal.?
??????? * TCP cannot get an acknowlegement for packets it has sent, even after several retransmissions. These packets could either be data sent by the application, or keep-alive messages (if keep-alive has been turned on). Don’t confuse this with the meaningless HTTP Keep-Alive parameter.?



????? 由socket讀取數(shù)據(jù)時(shí),如果使用堵塞的讀操作,可能會(huì)導(dǎo)致永久地等待.Socket的setSoTimeout方法 控制了超時(shí)的期限.在socket連接失敗的情況下,讀取數(shù)據(jù)的操作最終會(huì)被停止.?

這種情況通常發(fā)生在以下幾種情況:?

??????? 1.本地關(guān)閉了socket,?

??????? 2.遠(yuǎn)程主機(jī)/終端發(fā)送了斷開連接的信號(hào),?

??????? 3.tcp協(xié)議實(shí)現(xiàn)在嘗試多次重發(fā)數(shù)據(jù)仍無法獲得對(duì)方針對(duì)已發(fā)送數(shù)據(jù)包的確認(rèn)信息,或者無法獲得keep-alive的信息(如果tcp協(xié)議的keep- alive選項(xiàng)已經(jīng)被啟用).另外不要和http協(xié)議的keep-alive參數(shù)相混淆.(http的keep-alive選項(xiàng)是指客戶端與服務(wù)器之間建立有效的長(zhǎng)連接,避免了重復(fù)建立連接的消耗,尤其對(duì)提供靜態(tài)資源訪問的網(wǎng)站能夠很大的提高訪問效率)?



??? Timeouts /超時(shí)?


??? Java offers Socket.setSoTimeout to control how long you are willing to wait for a read to complete and Socket.setSoLinger to control how long it lingers, (waits to close when there are still unsent data). When you shutdown, the other end should continue to read any buffered data to let the other end close before closing itself. setSoTimeout has no effect on how long you are willing to wait for a write (how long you are willing to wait for the other end to accept data), just on how long you are willing to wait for the other end to produce data.?

??? To add to the misery, Windows partially ignores the timeout. On connect, the JVM tries to resolve the hostname to IP/port. Windows tries a netbios ns query on UDP port 137 with a timeout of 1.5 seconds, ignores any ICMP port unreachable packets and repeats this two more times, adding up to a value of 4.5 seconds. I suggest putting critical hostnames in your HOSTS file to make sure they are resolved quickly. Another possibility is turning off NETBIOS altogether and running pure TCP/IP on your LAN.?



??? socket的java實(shí)現(xiàn)接口提供了setSoTimeout方法設(shè)置希望等待完成讀取操作的時(shí)間期限,提供setSoLinger方法控制關(guān)閉等待期限(等待尚未發(fā)送的數(shù)據(jù),然后關(guān)閉連接). 當(dāng)一方關(guān)閉連接時(shí),另一方仍會(huì)在讀取到緩沖區(qū)中的通知關(guān)閉連接的數(shù)據(jù)以后關(guān)閉連接(這句話不知道這樣翻譯是否準(zhǔn)確,不過實(shí)際操作應(yīng)該是這樣的,可以這樣理解,當(dāng)一端單方面關(guān)閉連接的時(shí)候,應(yīng)該通知另一方你已經(jīng)關(guān)閉連接,以便對(duì)方獲悉并且關(guān)閉連接).setSoTimeout選項(xiàng)對(duì)等待完成寫操作的期限沒有影響(等待對(duì)方對(duì)方接收數(shù)據(jù)的期限),只和等待對(duì)方產(chǎn)生數(shù)據(jù)的期限有關(guān).(setSoTimeout和對(duì)方發(fā)送響應(yīng)數(shù)據(jù)是否超時(shí)有關(guān)和對(duì)方何時(shí)接收數(shù)據(jù)沒有關(guān)系).?



???? 比較令人苦悶的是,windows系統(tǒng)不負(fù)責(zé)任地忽略超時(shí).對(duì)于一個(gè)連接.java虛擬機(jī)努力將域名解析為ip地址和端口號(hào).而windows使用udp 的137端口向域名解析服務(wù)器發(fā)送域名解析查詢,超時(shí)設(shè)為1.5秒.忽略了任何的icmp端口不可訪問的數(shù)據(jù)包并且連續(xù)再重復(fù)發(fā)送兩次相同的請(qǐng)求(一共是三次).總計(jì)需要等待4.5秒.因此強(qiáng)烈建議把常用的域名地址和對(duì)應(yīng)的ip地址和端口寫在hosts文件中以確保可以迅速解析.另外就是在局域網(wǎng)完全中關(guān)閉windows的NETBIOS服務(wù),完全使用tcp/ip訪問資源.?



??? Disconnet Detection / 探測(cè)連接關(guān)閉?


??? Since TCP/IP sends no packets except when there is traffic, without Socket.setKeepAlive( true ), it has no way of noticing a disconnect until you start trying to send (or to a certain extent receive) traffic again. Java has the Socket.setKeepAlive( true ) method to ask TCP/IP to handle heartbeat probing without any data packets or application programming. Unfortunately, you can’t tell it how frequently to send the heartbeat probes. If the other end does not respond in time, you will get a socket exception on your pending read. Heartbeat packets in both directions let the other end know you are still there. A heartbeat packet is just an ordinary TCP/IP ack packet without any piggybacking data.?



??? 當(dāng)網(wǎng)絡(luò)繁忙的時(shí)候,tcp/ip無法發(fā)送數(shù)據(jù)包.如果沒有設(shè)定socket的setKeepAlive為true,我們無法獲悉一個(gè)連接已經(jīng)關(guān)閉除非試圖再次進(jìn)行發(fā)送操作(或者進(jìn)行某些接收操作).java通過設(shè)定socket的setKeepAlive為true的方式要求tcp/ip協(xié)議進(jìn)行心跳檢測(cè),不需要發(fā)送任何數(shù)據(jù)包或者應(yīng)用級(jí)別的編程.然而不幸地是你無法肯定tcp/ip以怎樣的頻率發(fā)送心跳探測(cè)信號(hào).如果另一方無法及時(shí)響應(yīng),當(dāng)你試圖進(jìn)行讀取操作的時(shí)候就會(huì)產(chǎn)生socket的異常.心跳包使雙方都能獲知對(duì)方是否保持連接.心跳包只是一個(gè)普通的tcp/ip的ack報(bào)文不需要搭載任何的其他數(shù)據(jù).?


??? When the applications are idling, your applications could periodically send tiny heartbeat messages to each other. The receiver could just ignore them. However, they force the TCP/IP protocol to check if the other end is still alive. These are not part of the TCP/IP protocol. You would have to build them into your application protocols. They act as are-you-still-alive? messages. I have found Java’s connection continuity testing to be less that 100% reliable. My bullet-proof technique to detect disconnect is to have the server send an application-level heartbeat packet if it has not sent some packet in the last 30 seconds. It has to send some message every 30 seconds, not necessarily a dummy heartbeat packet. The heartbeat packets thus only appear when the server is idling. Otherwise normal traffic acts as the heartbeat. The Applet detects the lack of traffic on disconnect and automatically restarts the connection. The downside is your applications have to be aware of these heartbeats and they have to fit into whatever other protocol you are using, unlike relying on TCP/IP level heartbeats.?



???? 當(dāng)應(yīng)用處于空閑狀態(tài)的時(shí)候,你的應(yīng)用可以間斷地向彼此發(fā)送小的心跳信息.接收者可以完全忽視它們,但是它們強(qiáng)制tcp/ip協(xié)議去核實(shí)另一方是否存活.這不是tcp/ip協(xié)議通信規(guī)范的一部分,你需要建立自己的心跳協(xié)議,例如 發(fā)送內(nèi)容為' are-you-still-alive? '的信息,原作者通過測(cè)試發(fā)現(xiàn)java的連接持續(xù)性并非100%的可靠.他的銀彈技術(shù)是通過服務(wù)端每隔30秒發(fā)送一個(gè)應(yīng)用級(jí)別的心跳包,如果最近30秒內(nèi)沒有接收到任何數(shù)據(jù)包.服務(wù)器必須每隔30秒發(fā)送一個(gè)數(shù)據(jù)包,不一定必須是傀儡的心跳數(shù)據(jù)包.心跳數(shù)據(jù)包只當(dāng)服務(wù)器空閑的時(shí)候才會(huì)產(chǎn)生.否則的話,普通的網(wǎng)絡(luò)通信就可以替代心跳數(shù)據(jù)包的功能.applet探測(cè)發(fā)現(xiàn)由于斷開連接導(dǎo)致的通信中斷后就會(huì)重新建立連接.負(fù)面影響是你的應(yīng)用必須時(shí)時(shí)關(guān)注這些心跳狀態(tài),并且如果你使用其它網(wǎng)絡(luò)協(xié)議你也要實(shí)現(xiàn)相應(yīng)的心跳協(xié)議,不同余依賴于tcp/ip層的心跳.?


??? However, it is simpler to use the built-in Socket.setKeepAlive( true ) method to ask TCP/IP to handle the heartbeat probing without any data packets or application programming. Each end with nothing to say just periodically sends an empty data packet with its current sequence, acknowledgement and window numbers.?


?? 然而,使用socket內(nèi)置的setKeepAlive(true)方法去要求tcp/ip進(jìn)行心跳探測(cè)不使用任何數(shù)據(jù)包或者應(yīng)用級(jí)別地編程實(shí)現(xiàn)看起來更加容易一些.每個(gè)終端只需間歇地發(fā)送一個(gè)包含當(dāng)前序列的空的數(shù)據(jù)包,確認(rèn)信息和滑動(dòng)窗口號(hào)就可以了.?


??? The advantage of application level heartbeats is they let you know the applications at both ends are alive, not just the communications software.?



??? 應(yīng)用級(jí)別的心跳優(yōu)點(diǎn)在于它們能夠使你了解兩端的應(yīng)用都是否存活,而不在于只是通信軟件.?



Server Side Socketing /服務(wù)器端套接字?


??? For a server to accept connections from the outside world, first it opens a ServerSocket on a port, but not connected to any client in particular.?



??? 對(duì)于一個(gè)接收外部連接的服務(wù)器,首先在某個(gè)沒有連接任何客戶端的端口上開啟一個(gè)serversocket,代碼如下?


??? ServerSocket serverSocket = new ServerSocket( port );?

??? Then it calls accept, which blocks until a call comes in.?

??? Socket clientSocket = serverSocket.accept();?

??? At that point a new ordinary Socket gets created that is connected to the incoming caller. Usually the server would spin off a Thread, or assign a Thread from a pool to deal with the new Socket and loop back to do another accept.?



???? 當(dāng)接收到一個(gè)請(qǐng)求時(shí)會(huì)新建一個(gè)的普通的socket,通常服務(wù)器會(huì)啟動(dòng)一個(gè)線程或者由線程池中取出一個(gè)線程處理新產(chǎn)生的socket,然后循環(huán)處理下一個(gè)請(qǐng)求.?


??? You can set up your miniature server even if you don’t have a domain name. They can get to you by name: ip:port e.g. 65.110.21.43:2222. Even if your are behind a firewall, you use the external facing IP of the firewall. You must then configure your firewall to let incoming calls through and to direct them to the correct server on the lan.?



???? 即使你并不擁有一個(gè)域名,你也可以建立自己的服務(wù)器.他人可以通過ip地址和端口的方式( e.g. 65.110.21.43:2222)訪問你的服務(wù)器(如果在廣域網(wǎng)上這要求你擁有自己的固定ip,這一般比擁有域名的成本還要高,不過在局域網(wǎng)內(nèi)你可以嘗試局域網(wǎng)地址),如果你在處于防火墻保護(hù)的局域網(wǎng)內(nèi),你可以使用防火墻的對(duì)外ip.你必須配置你的防火墻以便請(qǐng)求數(shù)據(jù)包可以通過并且訪問局域網(wǎng)內(nèi)正確的服務(wù)器.?



??? Flow Control / 流控制?


??? With Socket.setReceiveBufferSize() you can hint to the underlying OS how much to buffer up incoming data. It is not obligated to listen to you. Don’t confuse this with the buffer on the BufferedInputStream. This is the lower level buffer on the raw socket. Large buffers are not always desirable. Using small buffers can tell the other end you are getting behind, and it won’t send data as quickly. If the data is real time, and the amount of data sent is variable depending on how fast you process it, large buffers mean you can get way behind and never catch up.?



???? 使用socket的setReceiveBufferSize()方法你可以告訴底層的操作系統(tǒng)緩存多大的接收數(shù)據(jù).但是這并非完全由你決定.不要將 socket的緩沖區(qū)和BufferedInputStream的緩沖區(qū)混淆.這是原始socket的底層的緩沖區(qū).過大的緩沖區(qū)并不總能很好地滿足需要.使用小的緩沖區(qū)能夠通知另一端你的處理速度已經(jīng)落后了,因此對(duì)方不會(huì)繼續(xù)馬上發(fā)送數(shù)據(jù)過來(大的緩沖區(qū),對(duì)方發(fā)送過來的數(shù)據(jù)有可能還沒有讀取并被處理,但還留有很大的空間,因此對(duì)方會(huì)繼續(xù)發(fā)送數(shù)據(jù)填滿余下的空間,但是有可能導(dǎo)致大量的數(shù)據(jù)堆積在緩沖區(qū)中無法處理,理想狀態(tài)是使用小的緩存區(qū),處理完當(dāng)前數(shù)據(jù)后在接收,處理下一個(gè)數(shù)據(jù)).如果數(shù)據(jù)不是實(shí)時(shí)的,發(fā)送過來的數(shù)據(jù)量動(dòng)態(tài)地依賴于處理數(shù)據(jù)的速度,過大的緩沖區(qū)會(huì)導(dǎo)致你處理的數(shù)據(jù)量一直落后于接收的數(shù)據(jù)量,并且永遠(yuǎn)無法趕上.?


??? There is a mysterioous method Socket.setTcpNoDelay( true ) to "disable Nagle’s algorithm". As is typical, there is no explanation what Nagle’s algorinthm is. My TCP/IP text book makes no mention of it. If you are dealing with near real-time data then you may want to look into disabling Nagle’s algorithm. That algorithm attempts to ensure that TCP doesn’t send lots of undersized IP packets by buffering-up submitted data and keeping it for typically for a few milliseconds to see if you are going to give it some more data that could go into the same packet. I am not sure if flush is sufficient to send a packet on its way immediately.?



???? socket的setTcpNoDelay( true )很神秘地用來關(guān)閉Nagle算法.正如這里不解釋Nagle算法一樣,這里也不討論這個(gè)setTcpNoDelay方法. 如果你處理近乎實(shí)時(shí)的數(shù)據(jù),你可能會(huì)研究如何關(guān)閉Nagle算法.Nagle算法通過暫存已經(jīng)提交發(fā)送的數(shù)據(jù)包許多毫秒的時(shí)間以便判斷是否還需要向這個(gè)數(shù)據(jù)包寫入更多數(shù)據(jù),確保tcp不發(fā)送大量的長(zhǎng)度過小的數(shù)據(jù)包.我不確定是否flush方法能夠充分地立即發(fā)送一個(gè)數(shù)據(jù)包.?



?? Graceful Shutdown / 優(yōu)雅地關(guān)閉?


??? If you simply close a socket, you can lose data that were previously sent but which have not yet been delivered. You may chop things off in mid message. So, how to shut down gracefully? My approach is this. When the client wants to shut down, it sends a close message. The server echos it back and on receipt of the close message, the client closes the socket. That way the client is guaranteed to be unhooked from waiting on a read, and you are guaranteed the server and client each recieved the last remaining messages before the socket was closed.?



???? 如果你簡(jiǎn)單地關(guān)閉一個(gè)socket連接,你可能會(huì)丟失先前發(fā)送但并未抵達(dá)(交付)的數(shù)據(jù).這可能會(huì)導(dǎo)致數(shù)據(jù)不完整.所以,如果優(yōu)雅地關(guān)閉連接呢?作者的理論是:當(dāng)客戶端試圖關(guān)閉連接時(shí),它首先要發(fā)送一條關(guān)閉信息.服務(wù)器原樣返回關(guān)閉信息內(nèi)容和確認(rèn)關(guān)閉信息(增加確認(rèn)關(guān)閉信息的做法可能是為了避免發(fā)送超時(shí)的數(shù)據(jù)包返回給發(fā)送者,兩者內(nèi)容可能是相同的),客戶端收到確認(rèn)信息后關(guān)閉連接.這時(shí)客戶端要確保解除等待讀取操作的狀態(tài),并且你要確保客戶端和服務(wù)器在關(guān)閉前都收到了最后的信息.?




?

本篇文章觀點(diǎn)和例子來自 《Java網(wǎng)絡(luò)編程精解》, 作者為孫衛(wèi)琴, 出版社為電子工業(yè)出版社。

?

????? 在客戶/服務(wù)器通信模式中, 客戶端需要主動(dòng)創(chuàng)建與服務(wù)器連接的 Socket(套接字), 服務(wù)器端收到了客戶端的連接請(qǐng)求, 也會(huì)創(chuàng)建與客戶連接的 Socket. Socket可看做是通信連接兩端的收發(fā)器, 服務(wù)器與客戶端都通過 Socket 來收發(fā)數(shù)據(jù).

?

這篇文章首先介紹Socket類的各個(gè)構(gòu)造方法, 以及成員方法的用法, 接著介紹 Socket的一些選項(xiàng)的作用, 這些選項(xiàng)可控制客戶建立與服務(wù)器的連接, 以及接收和發(fā)送數(shù)據(jù)的行為.

?

一. 構(gòu)造Socket

?

???? Socket的構(gòu)造方法有以下幾種重載形式:??

  • Socket()
  • Socket(InetAddress address, int port) throws UnknowHostException, IOException
  • Socket(InetAddress address, int port, InetAddress localAddr, int localPort) throws IOException
  • Socket(String host, int port) throws UnknowHostException, IOException
  • Socket(String host, int port, InetAddress localAddr, int localPort) throws IOException
  • ???? 除了第一個(gè)不帶參數(shù)的構(gòu)造方法以外, 其他構(gòu)造方法都會(huì)試圖建立與服務(wù)器的連接, 如果連接成功, 就返回 Socket對(duì)象; 如果因?yàn)槟承┰蜻B接失敗, 就會(huì)拋出IOException .

    ?

    1.1 使用無參數(shù)構(gòu)造方法, 設(shè)定等待建立連接的超時(shí)時(shí)間

    ???

    ??Socket socket = new Socket();
    ??SocketAddress remoteAddr = new InetSocketAddress("localhost",8000);
    ??socket.connect(remoteAddr, 60000); ?//等待建立連接的超時(shí)時(shí)間為1分鐘

    ?

    ????? 以上代碼用于連接到本地機(jī)器上的監(jiān)聽8000端口的服務(wù)器程序, 等待連接的最長(zhǎng)時(shí)間為1分鐘. 如果在1分鐘內(nèi)連接成功則connet()方法順利返回; 如果在1分鐘內(nèi)出現(xiàn)某種異常, 則拋出該異常; 如果超過1分鐘后, 即沒有連接成功, 也沒有出現(xiàn)其他異常, 那么會(huì)拋出 SocketTimeoutException. Socket 類的 connect(SocketAddress endpoint, int?timeout) 方法負(fù)責(zé)連接服務(wù)器, 參數(shù)endpoint 指定服務(wù)器的地址, 參數(shù)timeout 設(shè)定超時(shí)數(shù)據(jù), 以毫秒為單位. 如果參數(shù)timeout 設(shè)為0, 表示永遠(yuǎn)不會(huì)超時(shí), 默認(rèn)是不會(huì)超時(shí)的.?

    ?

    1.2?設(shè)定服務(wù)器的地址

    ?

    ??????除了第一個(gè)不帶參數(shù)的構(gòu)造方法, 其他構(gòu)造方法都需要在參數(shù)中設(shè)定服務(wù)器的地址, 包括服務(wù)器的IP地址或主機(jī)名, 以及端口:

    ??Socket(InetAddress address, int port)????????????? //第一個(gè)參數(shù)address 表示主機(jī)的IP地址
    ??Socket(String host, int port)??????????????????????????????//第一個(gè)參數(shù)host 表示主機(jī)的名字

    ?

    ????? InetAddress 類表示服務(wù)器的IP地址, InetAddress 類提供了一系列靜態(tài)工廠方法, 用于構(gòu)造自身的實(shí)例, 例如:

    ?

    ??//返回本地主機(jī)的IP地址
    ??InetAddress addr1 = InetAddress.getLocalHost();
    ??//返回代表 "222.34.5.7"的 IP地址
    ??InetAddress addr2 = InetAddress.getByName("222.34.5.7");
    ??//返回域名為"www.javathinker.org"的 IP地址
    ??InetAddress addr3 = InetAddress.getByName("www.javathinker.org");

    ?

    ?

    1.3 設(shè)定客戶端的地址

    ?

    ????? 在一個(gè)Socket 對(duì)象中, 即包含遠(yuǎn)程服務(wù)器的IP 地址和端口信息, 也包含本地客戶端的IP 地址和端口信息. 默認(rèn)情況下, 客戶端的IP 地址來自于客戶程序所在的主機(jī), 客戶端的端口則由操作系統(tǒng)隨機(jī)分配. Socket類還有兩個(gè)構(gòu)造方法允許顯式地設(shè)置客戶端的IP 地址和端口:

    ?

    ??//參數(shù)localAddr 和 localPort 用來設(shè)置客戶端的IP 地址和端口
    ??Socket(InetAddress address, int port, InetAddress localAddr, int localPort) throws IOException
    ??Socket(String host, int port, InetAddress localAddr, int localPort) throws IOException

    ?

    ?????如果一個(gè)主機(jī)同時(shí)屬于兩個(gè)以上的網(wǎng)絡(luò), 它就可能擁有兩個(gè)以上的IP 地址. 例如, 一個(gè)主機(jī)在Internet 網(wǎng)絡(luò)中的IP 地址為 "222.67.1.34", 在一個(gè)局域網(wǎng)中的IP 地址為 "112.5.4.3". 假定這個(gè)主機(jī)上的客戶程序希望和同一個(gè)局域網(wǎng)的一個(gè)服務(wù)器程序(地址為:"112.5.4.45: 8000")通信, 客戶端可按照如下方式構(gòu)造Socket 對(duì)象:

    ?????

    ??InetAddress remoteAddr1 = InetAddress.getByName("112.5.4.45");
    ??InetAddress localAddr1 = InetAddress.getByName("112.5.4.3");
    ??Socket socket1 = new Socket(remoteAddr1, 8000, localAddr1, 2345);?? //客戶端使用端口2345

    ?

    ?

    ?1.4 客戶連接服務(wù)器時(shí)可能拋出的異常

    ?

    ?????? 當(dāng)Socket 的構(gòu)造方法請(qǐng)求連接服務(wù)器時(shí), 可能會(huì)拋出下面的異常.

    • UnKnownHostException: 如果無法識(shí)別主機(jī)的名字或IP 地址, 就會(huì)拋出這種異常.
    • ConnectException: 如果沒有服務(wù)器進(jìn)程監(jiān)聽指定的端口, 或者服務(wù)器進(jìn)程拒絕連接, 就會(huì)拋出這種異常.
    • SocketTimeoutException: 如果等待連接超時(shí), 就會(huì)拋出這種異常.
    • BindException: 如果無法把Socket 對(duì)象與指定的本地IP 地址或端口綁定, 就會(huì)拋出這種異常.

    ?????? 以上4中異常都是IOException的直接或間接子類.??????如圖2-1所示.

    ?

    ??????? IOException-------? UnknownHostException

    ????????????????????????????? |---- InterruptedIOException??-----------? SocketTimeoutException

    ????????????????????????????? |---- SocketException????????????? -----------? BindException

    ?????????????????????????????????????????????????????????????????????????????|----------? ConnectException

    ???????

    ??????????????????????????????????? 圖2-1 客戶端連接服務(wù)器時(shí)可能拋出的異常

    ?

    ?

    二. 獲取Socket 的信息

    ?

    ????

    ????? 在一個(gè)Socket 對(duì)象中同時(shí)包含了遠(yuǎn)程服務(wù)器的IP 地址和端口信息, 以及客戶本地的IP 地址和端口信息. 此外, 從Socket 對(duì)象中還可以獲得輸出流和輸入流, 分別用于向服務(wù)器發(fā)送數(shù)據(jù), 以及接收從服務(wù)器端發(fā)來的數(shù)據(jù). 以下方法用于獲取Socket的有關(guān)信息.

    • getInetAddress(): 獲得遠(yuǎn)程服務(wù)器的IP 地址.
    • getPort(): 獲得遠(yuǎn)程服務(wù)器的端口.
    • getLocalAddress(): 獲得客戶本地的IP 地址.
    • getLocalPort(): 獲得客戶本地的端口.
    • getInputStream(): 獲得輸入流. 如果Socket 還沒有連接, 或者已經(jīng)關(guān)閉, 或者已經(jīng)通過 shutdownInput() 方法關(guān)閉輸入流, 那么此方法會(huì)拋出IOException.
    • getOutputStream(): 獲得輸出流, 如果Socket 還沒有連接, 或者已經(jīng)關(guān)閉,?或者已經(jīng)通過 shutdownOutput() 方法關(guān)閉輸出流, 那么此方法會(huì)拋出IOException.

    ?????這里有個(gè)HTTPClient 類的例子, 代碼我是寫好了, 也測(cè)試過了, 因?yàn)槠蚓筒毁N了. 這個(gè)HTTPClient 類用于訪問網(wǎng)頁?www.javathinker.org/index.jsp. 該網(wǎng)頁位于一個(gè)主機(jī)名(也叫域名)為?www.javathinker.org?的遠(yuǎn)程HTTP服務(wù)器上,?它監(jiān)聽?80 端口. 在HTTPClient 類中, 先創(chuàng)建了一個(gè)連接到該HTTP服務(wù)器的Socket對(duì)象, 然后發(fā)送符合HTTP 協(xié)議的請(qǐng)求, 接著接收從HTTP 服務(wù)器上發(fā)回的響應(yīng)結(jié)果.

    ?

    三. 關(guān)閉Socket

    ?

    ???? 當(dāng)客戶與服務(wù)器的通信結(jié)束, 應(yīng)該及時(shí)關(guān)閉Socket , 以釋放Socket 占用的包括端口在內(nèi)的各種資源. Socket 的 close() 方法負(fù)責(zé)關(guān)閉Socket. 當(dāng)一個(gè)Socket對(duì)象被關(guān)閉, 就不能再通過它的輸入流和輸出流進(jìn)行I/O操作, 否則會(huì)導(dǎo)致IOException.

    ?

    ????? 為了確保關(guān)閉Socket 的操作總是被執(zhí)行, 強(qiáng)烈建議把這個(gè)操作放在finally 代碼塊中:

    ?

    ???Socket socket = null;
    ???try{
    ????????socket = new Socket(www.javathinker.org,80);
    ????????//執(zhí)行接收和發(fā)送數(shù)據(jù)的操作
    ????????..........
    ???}catch(IOException e){
    ?????????e.printStackTrace();
    ???}finally{
    ????????try{
    ?????????????if(socket != null)? socket.close();
    ???????}catch(IOException e){e.printStackTrace();}
    ???}

    ?

    ???

    ? ??Socket 類提供了3 個(gè)狀態(tài)測(cè)試方法.

    • isClosed(): 如果Socket已經(jīng)連接到遠(yuǎn)程主機(jī), 并且還沒有關(guān)閉, 則返回true , 否則返回false .
    • isConnected(): 如果Socket曾經(jīng)連接到遠(yuǎn)程主機(jī), 則返回true , 否則返回false .
    • isBound(): 如果Socket已經(jīng)與一個(gè)本地端口綁定, 則返回true , 否則返回false .

    ???? 如果要判斷一個(gè)Socket 對(duì)象當(dāng)前是否處于連接狀態(tài), 可采用以下方式:

    ?

    ??????boolean isConnected = socket.isConnected() && !socket.isClosed();??????????????????????????????????????

    ?

    ?

    四. 半關(guān)閉Socket

    ?

    ???? 進(jìn)程A 與進(jìn)程B 通過Socket 通信, 假定進(jìn)程A 輸出數(shù)據(jù), 進(jìn)程B 讀入數(shù)據(jù). 進(jìn)程A 如何告訴進(jìn)程B 所有數(shù)據(jù)已經(jīng)輸出完畢? 下文略......

    ?

    ?

    五. 設(shè)置Socket 的選項(xiàng)

    ?

    ???? Socket 有以下幾個(gè)選項(xiàng).

    • TCP_NODELAY: 表示立即發(fā)送數(shù)據(jù).
    • SO_RESUSEADDR: 表示是否允許重用Socket 所綁定的本地地址.
    • SO_TIMEOUT: 表示接收數(shù)據(jù)時(shí)的等待超時(shí)數(shù)據(jù).
    • SO_LINGER: 表示當(dāng)執(zhí)行Socket 的 close()方法時(shí), 是否立即關(guān)閉底層的Socket.
    • SO_SNFBUF: 表示發(fā)送數(shù)據(jù)的緩沖區(qū)的大小.
    • SO_RCVBUF: 表示接收數(shù)據(jù)的緩沖區(qū)的大小.
    • SO_KEEPALIVE: 表示對(duì)于長(zhǎng)時(shí)間處于空閑狀態(tài)的Socket , 是否要自動(dòng)把它關(guān)閉.
    • OOBINLINE: 表示是否支持發(fā)送一個(gè)字節(jié)的TCP 緊急數(shù)據(jù).

    ?

    5.1 TCP_NODELAY 選項(xiàng)

    • 設(shè)置該選項(xiàng): public void setTcpNoDelay(boolean on) throws SocketException
    • 讀取該選項(xiàng): public boolean getTcpNoDelay() throws SocketException

    ?????默認(rèn)情況下, 發(fā)送數(shù)據(jù)采用Negale 算法. Negale 算法是指發(fā)送方發(fā)送的數(shù)據(jù)不會(huì)立即發(fā)出, 而是先放在緩沖區(qū), 等緩存區(qū)滿了再發(fā)出. 發(fā)送完一批數(shù)據(jù)后, 會(huì)等待接收方對(duì)這批數(shù)據(jù)的回應(yīng), 然后再發(fā)送下一批數(shù)據(jù). Negale 算法適用于發(fā)送方需要發(fā)送大批量數(shù)據(jù), 并且接收方會(huì)及時(shí)作出回應(yīng)的場(chǎng)合, 這種算法通過減少傳輸數(shù)據(jù)的次數(shù)來提高通信效率.

    ?

    ???? 如果發(fā)送方持續(xù)地發(fā)送小批量的數(shù)據(jù), 并且接收方不一定會(huì)立即發(fā)送響應(yīng)數(shù)據(jù), 那么Negale 算法會(huì)使發(fā)送方運(yùn)行很慢. 對(duì)于GUI 程序, 如網(wǎng)絡(luò)游戲程序(服務(wù)器需要實(shí)時(shí)跟蹤客戶端鼠標(biāo)的移動(dòng)), 這個(gè)問題尤其突出. 客戶端鼠標(biāo)位置改動(dòng)的信息需要實(shí)時(shí)發(fā)送到服務(wù)器上, 由于Negale 算法采用緩沖, 大大減低了實(shí)時(shí)響應(yīng)速度, 導(dǎo)致客戶程序運(yùn)行很慢.

    ?

    ????? TCP_NODELAY 的默認(rèn)值為 false, 表示采用 Negale 算法. 如果調(diào)用setTcpNoDelay(true)方法, 就會(huì)關(guān)閉 Socket的緩沖, 確保數(shù)據(jù)及時(shí)發(fā)送:

    ?

    ?????? if(!socket.getTcpNoDelay()) socket.setTcpNoDelay(true);???????????????????????????????????????????????????????????????????????????????????

    ?

    ??????如果Socket 的底層實(shí)現(xiàn)不支持TCP_NODELAY 選項(xiàng), 那么getTcpNoDelay() 和 setTcpNoDelay 方法會(huì)拋出 SocketException.

    ?

    ?

    5.2 SO_RESUSEADDR 選項(xiàng)

    • 設(shè)置該選項(xiàng): public void setResuseAddress(boolean on) throws SocketException
    • 讀取該選項(xiàng): public boolean getResuseAddress() throws SocketException

    ?????當(dāng)接收方通過Socket 的close() 方法關(guān)閉Socket 時(shí), 如果網(wǎng)絡(luò)上還有發(fā)送到這個(gè)Socket 的數(shù)據(jù), 那么底層的Socket 不會(huì)立即釋放本地端口, 而是會(huì)等待一段時(shí)間, 確保接收到了網(wǎng)絡(luò)上發(fā)送過來的延遲數(shù)據(jù), 然后再釋放端口.? Socket接收到延遲數(shù)據(jù)后, 不會(huì)對(duì)這些數(shù)據(jù)作任何處理. Socket 接收延遲數(shù)據(jù)的目的是, 確保這些數(shù)據(jù)不會(huì)被其他碰巧綁定到同樣端口的新進(jìn)程接收到.

    ?

    ?????客戶程序一般采用隨機(jī)端口, 因此出現(xiàn)兩個(gè)客戶程序綁定到同樣端口的可能性不大. 許多服務(wù)器程序都使用固定的端口. 當(dāng)服務(wù)器程序關(guān)閉后, 有可能它的端口還會(huì)被占用一段時(shí)間, 如果此時(shí)立刻在同一個(gè)主機(jī)上重啟服務(wù)器程序, 由于端口已經(jīng)被占用, 使得服務(wù)器程序無法綁定到該端口, 啟動(dòng)失敗. (第三篇文章會(huì)對(duì)此作出介紹).

    ?

    ???? 為了確保一個(gè)進(jìn)程關(guān)閉Socket 后, 即使它還沒釋放端口, 同一個(gè)主機(jī)上的其他進(jìn)程還可以立即重用該端口, 可以調(diào)用Socket 的setResuseAddress(true) 方法:

    ?

    ?????? ?if(!socket.getResuseAddress()) socket.setResuseAddress(true);????????????????????????????????????????????????????????????????????????????

    ?

    ????值得注意的是?socket.setResuseAddress(true) 方法必須在 Socket 還沒有綁定到一個(gè)本地端口之前調(diào)用, 否則執(zhí)行?socket.setResuseAddress(true) 方法無效. 因此必須按照以下方式創(chuàng)建Socket 對(duì)象, 然后再連接遠(yuǎn)程服務(wù)器:

    ???

    ? Socket socket = new Socket();??????????? //此時(shí)Socket對(duì)象未綁定本地端口,并且未連接遠(yuǎn)程服務(wù)器
    ??socket.setReuseAddress(true);
    ??SocketAddress remoteAddr = new InetSocketAddress("localhost",8000);
    ??socket.connect(remoteAddr); ???????????? //連接遠(yuǎn)程服務(wù)器, 并且綁定匿名的本地端口

    ?

    ??? 或者:?

    ?

    ??Socket socket = new Socket();????????????? //此時(shí)Socke 對(duì)象為綁定本地端口, 并且未連接遠(yuǎn)程服務(wù)器
    ??socket.setReuseAddress(true);
    ??SocketAddress localAddr = new InetSocketAddress("localhost",9000);
    ??SocketAddress remoteAddr = new InetSocketAddress("localhost",8000);
    ??socket.bind(localAddr);?????????????//與本地端口綁定
    ??socket.connect(remoteAddr); //連接遠(yuǎn)程服務(wù)器

    ?

    ????此外, 兩個(gè)共用同一個(gè)端口的進(jìn)程必須都調(diào)用 socket.setResuseAddress(true) 方法, 才能使得一個(gè)進(jìn)程關(guān)閉 Socket后, 另一個(gè)進(jìn)程的 Socket 能夠立即重用相同端口.

    ?

    ?

    ?5.3 SO_TIMEOUT 選項(xiàng)

    • 設(shè)置該選項(xiàng): public void setSoTimeout(int milliseconds) throws SocketException
    • 讀取該選項(xiàng): public int getSoTimeout() throws SocketException

    ?????當(dāng)通過Socket 的輸入流讀數(shù)據(jù)時(shí), 如果還沒有數(shù)據(jù), 就會(huì)等待. 例如, 在以下代碼中, in.read(buff) 方法從輸入流中讀入 1024個(gè)字節(jié):?

    ?

    ??byte[] buff = new byte[1024];
    ??InputStream in = socket.getInputStream();
    ??in.read(buff);?

    ?

    ???? 如果輸入流中沒有數(shù)據(jù), in.read(buff) 就會(huì)等待發(fā)送方發(fā)送數(shù)據(jù), 直到滿足以下情況才結(jié)束等待:

    ?

    ???? 略...............

    ?

    ???? Socket 類的 SO_TIMEOUT 選項(xiàng)用于設(shè)定接收數(shù)據(jù)的等待超時(shí)時(shí)間, 單位為毫秒, 它的默認(rèn)值為 0, 表示會(huì)無限等待, 永遠(yuǎn)不會(huì)超時(shí). 以下代碼把接收數(shù)據(jù)的等待超時(shí)時(shí)間設(shè)為 3 分鐘:

    ?

    ??????? if(socket.getSoTimeout() == 0) socket.setSoTimeout(60000 * 3);???//注意, 原書中這里的代碼錯(cuò)誤, 里面的方法名字都少了"So"???

    ?

    ?????Socket?的 setSoTimeout() 方法必須在接收數(shù)據(jù)之前執(zhí)行才有效. 此外, 當(dāng)輸入流的 read()方法拋出 SocketTimeoutException 后, Socket 仍然是連接的, 可以嘗試再次讀數(shù)據(jù):?????

    ?

    ??socket.setSoTimeout(180000);
    ??byte[] buff = new byte[1024];
    ??InputStream in = socket.getInputStream();
    ??int len = -1;
    ??do{
    ???try{
    ????len = in.read(buff);
    ????//處理讀到的數(shù)據(jù)
    ????//.........
    ???}catch(SocketTimeoutException e){
    ????//e.printStackTrace();?
    ??? System.out.println("等待讀超時(shí)!");
    ????len = 0;
    ???}????
    ??}while(len != -1);

    ?

    ???? 例子ReceiveServer.java 和 SendClient.java 是一對(duì)簡(jiǎn)單的服務(wù)器/客戶程序. sendClient 發(fā)送字符串 "hello everyone" ,接著睡眠 1 分鐘, 然后關(guān)閉 Socket. ReceiveServer 讀取 SendClient 發(fā)送來的數(shù)據(jù), 直到抵達(dá)輸入流的末尾, 最后打印 SendClient 發(fā)送來的數(shù)據(jù).

    ?

    ???? ReceiveServer.java 略....... ,???????? SendClient.java 略..........

    ?

    ???? 在 SendClient 發(fā)送字符串 "hello everyone" 后, 睡眠 1 分鐘. 當(dāng) SendClient 在睡眠時(shí), ReceiveServer 在執(zhí)行 in.read(buff) 方法, 不能讀到足夠的數(shù)據(jù)填滿 buff 緩沖區(qū), 因此會(huì)一直等待 SendClient 發(fā)送數(shù)據(jù). 如果在 ReceiveServer 類中 socket.setSoTimeout(20000) , 從而把等待接收數(shù)據(jù)的超時(shí)時(shí)間設(shè)為 20 秒, 那么 ReceiveServer 在等待數(shù)據(jù)時(shí), 每當(dāng)超過 20 秒, 就會(huì)拋出SocketTimeoutException . 等到 SendClient 睡眠 1 分鐘后, SendClient 調(diào)用 Socket 的 close() 方法關(guān)閉 Socket, 這意味著 ReceiveServer 讀到了輸入流的末尾, ReceiveServer 立即結(jié)束讀等待, read() 方法返回 -1 . ReceiveServer最后打印接收到的字符串 "hello everyone", 結(jié)果如下:

    ??等待讀超時(shí)!
    ??等待讀超時(shí)!
    ??hello everyone

    5.4 SO_LINGER 選項(xiàng)

    • 設(shè)置該選項(xiàng): public void setSoLinger(boolean on, int seconds) throws SocketException
    • 讀取該選項(xiàng): public int getSoLinger() throws SocketException

    ????? SO_LINGER 選項(xiàng)用來控制 Socket 關(guān)閉時(shí)的行為. 默認(rèn)情況下, 執(zhí)行 Socket 的 close() 方法, 該方法會(huì)立即返回, 但底層的 Socket 實(shí)際上并不立即關(guān)閉, 它會(huì)延遲一段時(shí)間, 直到發(fā)送完所有剩余的數(shù)據(jù), 才會(huì)真正關(guān)閉 Socket, 斷開連接.

    ?

    ????? 如果執(zhí)行以下方法:

    ?

    ????? socket.setSoLinger(true, 0);???????????????????????????????????????????????????????????????????????????????????????????????

    ?

    ????? 那么執(zhí)行Socket 的close() 方法, 該方法也會(huì)立即返回, 并且底層的 Socket 也會(huì)立即關(guān)閉, 所有未發(fā)送完的剩余數(shù)據(jù)被丟棄.

    ?

    ????? 如果執(zhí)行以下方法:

    ?

    ????? socket.setSoLinger(true, 3600);???????????????????????????????????????????????????????????????????????????????????????????

    ?

    ????? 那么執(zhí)行Socket 的 close() 方法, 該方法不會(huì)立即返回, 而是進(jìn)入阻塞狀態(tài). 同時(shí), 底層的 Socket 會(huì)嘗試發(fā)送剩余的數(shù)據(jù). 只有滿足以下兩個(gè)條件之一, close() 方法才返回:

    ????? ⑴ 底層的 Socket 已經(jīng)發(fā)送完所有的剩余數(shù)據(jù);

    ?

    ????? ⑵ 盡管底層的 Socket 還沒有發(fā)送完所有的剩余數(shù)據(jù), 但已經(jīng)阻塞了 3600 秒(注意這里是秒, 而非毫秒), close() 方法的阻塞時(shí)間超過 3600 秒, 也會(huì)返回, 剩余未發(fā)送的數(shù)據(jù)被丟棄.

    ?

    ????? 值得注意的是, 在以上兩種情況內(nèi), 當(dāng)close() 方法返回后, 底層的 Socket 會(huì)被關(guān)閉, 斷開連接. 此外, setSoLinger(boolean on, int seconds) 方法中的 seconds 參數(shù)以秒為單位, 而不是以毫秒為單位.????

    ?

    ????? 如果未設(shè)置 SO_LINGER 選項(xiàng), getSoLinger()? 返回的結(jié)果是 -1, 如果設(shè)置了 socket.setSoLinger(true, 80) , getSoLinger()? 返回的結(jié)果是 80.

    ?

    Tips: 當(dāng)程序通過輸出流寫數(shù)據(jù)時(shí), 僅僅表示程序向網(wǎng)絡(luò)提交了一批數(shù)據(jù), 由網(wǎng)絡(luò)負(fù)責(zé)輸送到接收方. 當(dāng)程序關(guān)閉 Socket, 有可能這批數(shù)據(jù)還在網(wǎng)絡(luò)上傳輸, 還未到達(dá)接收方. 這里所說的 "未發(fā)送完的數(shù)據(jù)" 就是指這種還在網(wǎng)絡(luò)上傳輸, 未被接收方接收的數(shù)據(jù).

    ?

    ??? 例子 SimpleClient.java 與 SimpleServer.java 所示是一對(duì)簡(jiǎn)單的客戶/服務(wù)器程序. SimpleClient 類發(fā)送一萬個(gè)字符給 SimpleServer, 然后調(diào)用Socket 的 close() 方法關(guān)閉 Socket.

    ?

    ??? SimpleServer 通過 ServerSocket 的 accept() 方法接受了 SimpleClient 的連接請(qǐng)求后,? 并不立即接收客戶發(fā)送的數(shù)據(jù), 而是睡眠 5 秒鐘后再接收數(shù)據(jù). 等到 SimpleServer 開始接收數(shù)據(jù)時(shí), SimpleClient 有可能已經(jīng)執(zhí)行了 Socket 的close() 方法, 那么 SimpleServer 還能接收到 SimpleClient 發(fā)送的數(shù)據(jù)嗎?

    ?

    ??? SimpleClient.java 略..., SimpleServer.java 略......

    ?

    ??? SimpleClient.java中

    ??System.out.println("開始關(guān)閉 Socket");
    ??long begin = System.currentTimeMillis();
    ??socket.close();
    ??long end = System.currentTimeMillis();
    ??System.out.println("關(guān)閉Socket 所用的時(shí)間為:" + (end - begin) + "ms");

    ?

    ??? 下面分 3 種情況演示 SimpleClient 關(guān)閉 Socket 的行為.??

    ??? ⑴ 未設(shè)置 SO_LINGER 選項(xiàng), 當(dāng) SimpleClient 執(zhí)行 Socket 的close() 方法時(shí), 立即返回, SimpleClient 的打印結(jié)果如下:

    ?

    ? 開始關(guān)閉 Socket
    ??關(guān)閉Socket 所用的時(shí)間為:0ms

    ?

    ???? 等到 SimpleClient 結(jié)束運(yùn)行, SimpleServer 可能才剛剛結(jié)束睡眠, 開始接收 SimpleClient 發(fā)送的數(shù)據(jù). 此時(shí)盡管 SimpleClient 已經(jīng)執(zhí)行了 Socket 的 close() 方法, 并且 SimpleClient 程序本身也運(yùn)行結(jié)束了, 但從 SimpleServer 的打印結(jié)果可以看出, SimpleServer 仍然接收到了所有的數(shù)據(jù). 之所以出現(xiàn)這種情況, 是因?yàn)楫?dāng) SimpleClient 執(zhí)行了 Socket 的 close() 方法后, 底層的 Socket 實(shí)際上并沒有真正關(guān)閉, 與 SimpleServer 的連接依然存在. 底層的 Socket 會(huì)存在一段時(shí)間, 直到發(fā)送完所有的數(shù)據(jù).

    ?

    ?????⑵ 設(shè)置SO_LINGER 選項(xiàng), socket.setSoLinger(true, 0). 這次當(dāng) SimpleClient 執(zhí)行 Socket 的 close() 方法時(shí), 會(huì)強(qiáng)行關(guān)閉底層的 Socket, 所有未發(fā)送完的數(shù)據(jù)丟失. SimpleClient 的打印結(jié)果如下:

    ?

    ? 開始關(guān)閉 Socket
    ??關(guān)閉Socket 所用的時(shí)間為:0ms

    ?

    ?????從打印結(jié)果看出, SimpleClient 執(zhí)行 Socket 的 close() 方法時(shí), 也立即返回. 當(dāng) SimpleServer 結(jié)束睡眠, 開始接收 SimpleClient 發(fā)送的數(shù)據(jù)時(shí),?由于 SimpleClient 已經(jīng)關(guān)閉底層 Socket, 斷開連接, 因此 SimpleServer 在讀數(shù)據(jù)時(shí)會(huì)拋出 SocketException:

    ?

    ?? ?????java.net.SocketException: Connection reset?????????????????????????????????????? ?

    ?

    ???? ⑶ 設(shè)置SO_LINGER 選項(xiàng), socket.setSoLinger(true, 3600). 這次當(dāng) SimpleClient 執(zhí)行 Socket 的close() 方法時(shí), 會(huì)進(jìn)入阻塞狀態(tài), 知道等待了 3600 秒, 或者底層 Socket 已經(jīng)把所有未發(fā)送的剩余數(shù)據(jù)發(fā)送完畢, 才會(huì)從 close() 方法返回. SimpleClient 的打印結(jié)果如下:

    ?

    ? 開始關(guān)閉 Socket
    ??關(guān)閉Socket 所用的時(shí)間為:5648ms

    ?

    ?????當(dāng) SimpleServer 結(jié)束了 5 秒鐘的睡眠, 開始接收 SimpleClient 發(fā)送的數(shù)據(jù)時(shí), SimpleClient 還在這些 Socket 的close() 方法, 并且處于阻塞狀態(tài). SimpleClient 與 SimpleServer 之間的連接依然存在, 因此 SimpleServer 能夠接收到 SimpleClient 發(fā)送的所有數(shù)據(jù).

    ?

    5.5 SO_RCVBUF 選項(xiàng)

    • 設(shè)置該選項(xiàng): public void setReceiveBufferSize(int size) throws SocketException
    • 讀取該選項(xiàng): public int getReceiveBufferSize() throws SocketException

    ??? ?SO_RCVBUF 表示 Socket 的用于輸入數(shù)據(jù)的緩沖區(qū)的大小. 一般說來, 傳輸大的連續(xù)的數(shù)據(jù)塊(基于HTTP 或 FTP 協(xié)議的通信) 可以使用較大的緩沖區(qū), 這可以減少傳輸數(shù)據(jù)的次數(shù), 提高傳輸數(shù)據(jù)的效率. 而對(duì)于交互頻繁且單次傳送數(shù)據(jù)量比較小的通信方式(Telnet 和 網(wǎng)絡(luò)游戲), 則應(yīng)該采用小的緩沖區(qū), 確保小批量的數(shù)據(jù)能及時(shí)發(fā)送給對(duì)方. 這種設(shè)定緩沖區(qū)大小的原則也同樣適用于 Socket 的 SO_SNDBUF 選項(xiàng).

    ?

    ????? 如果底層 Socket 不支持 SO_RCVBUF 選項(xiàng), 那么 setReceiveBufferSize() 方法會(huì)拋出 SocketException.

    ?

    5.6 SO_SNDBUF 選項(xiàng)

    • 設(shè)置該選項(xiàng): public void setSendBufferSize(int size) throws SocketException
    • 讀取該選項(xiàng): public int getSendBufferSize() throws SocketException

    ???? SO_SNDBUF 表示 Socket 的用于輸出數(shù)據(jù)的緩沖區(qū)的大小. 如果底層 Socket 不支持 SO_SNDBUF 選項(xiàng), setSendBufferSize() 方法會(huì)拋出 SocketException.

    ?

    5.7 SO_KEEPALIVE 選項(xiàng)

    • 設(shè)置該選項(xiàng): public void setKeepAlive(boolean on) throws SocketException
    • 讀取該選項(xiàng): public boolean getKeepAlive() throws SocketException?//原書中這個(gè)方法返回的類型是int

    ?? ?? 當(dāng) SO_KEEPALIVE?選項(xiàng)為 true 時(shí), 表示底層的TCP 實(shí)現(xiàn)會(huì)監(jiān)視該連接是否有效. 當(dāng)連接處于空閑狀態(tài)(連接的兩端沒有互相傳送數(shù)據(jù)) 超過了 2 小時(shí)時(shí), 本地的TCP 實(shí)現(xiàn)會(huì)發(fā)送一個(gè)數(shù)據(jù)包給遠(yuǎn)程的 Socket. 如果遠(yuǎn)程Socket 沒有發(fā)回響應(yīng), TCP實(shí)現(xiàn)就會(huì)持續(xù)嘗試 11 分鐘, 直到接收到響應(yīng)為止. 如果在 12 分鐘內(nèi)未收到響應(yīng), TCP 實(shí)現(xiàn)就會(huì)自動(dòng)關(guān)閉本地Socket, 斷開連接. 在不同的網(wǎng)絡(luò)平臺(tái)上, TCP實(shí)現(xiàn)嘗試與遠(yuǎn)程Socket 對(duì)話的時(shí)限有所差別.

    ?

    ????? SO_KEEPALIVE 選項(xiàng)的默認(rèn)值為 false, 表示TCP 不會(huì)監(jiān)視連接是否有效, 不活動(dòng)的客戶端可能會(huì)永遠(yuǎn)存在下去, 而不會(huì)注意到服務(wù)器已經(jīng)崩潰.

    ?

    ????? 以下代碼把 SO_KEEPALIVE 選項(xiàng)設(shè)為 true:

    ?

    ??????? if(!socket.getKeepAlive()) socket.setKeepAlive(true);??????????????????????????????????????????????????????????????

    ?

    5.8 OOBINLINE 選項(xiàng)

    • 設(shè)置該選項(xiàng): public void setOOBInline(boolean on) throws SocketException
    • 讀取該選項(xiàng): public boolean getOOBInline() throws SocketException??//原書中這個(gè)方法返回的類型是int

    ???? 當(dāng) OOBINLINE 為 true 時(shí), 表示支持發(fā)送一個(gè)字節(jié)的 TCP 緊急數(shù)據(jù). Socket 類的 sendUrgentData(int data) 方法用于發(fā)送一個(gè)字節(jié)的 TCP緊急數(shù)據(jù).

    ?

    ???? OOBINLINE 的默認(rèn)值為 false, 在這種情況下, 當(dāng)接收方收到緊急數(shù)據(jù)時(shí)不作任何處理, 直接將其丟棄. 如果用戶希望發(fā)送緊急數(shù)據(jù), 應(yīng)該把 OOBINLINE 設(shè)為 true:

    ?

    ????????? socket.setOOBInline(true);?????????????????????????????????????????????????????????????

    ?

    ??????此時(shí)接收方會(huì)把接收到的緊急數(shù)據(jù)與普通數(shù)據(jù)放在同樣的隊(duì)列中. 值得注意的是, 除非使用一些更高層次的協(xié)議, 否則接收方處理緊急數(shù)據(jù)的能力有限, 當(dāng)緊急數(shù)據(jù)到來時(shí), 接收方不會(huì)得到任何通知, 因此接收方很難區(qū)分普通數(shù)據(jù)與緊急數(shù)據(jù), 只好按照同樣的方式處理它們.

    ?

    ?

    5.9 服務(wù)類型選項(xiàng)

    ?

    ??????當(dāng)用戶通過郵局發(fā)送普通信、掛號(hào)信或快件時(shí), 實(shí)際上是選擇了郵局提供的不同的服務(wù).? 發(fā)送普通信的價(jià)格最低, 但發(fā)送速度慢, 并且可靠性沒有保證. 發(fā)送掛號(hào)信的價(jià)格稍高,? 但可靠性有保證. 發(fā)送快件的價(jià)格最高, 發(fā)送速度最快, 并且可靠性有保證.

    ?

    ????? 在 Internet 上傳輸數(shù)據(jù)也分為不同的服務(wù)類型, 它們有不同的定價(jià). 用戶可以根據(jù)自己的需求, 選擇不同的服務(wù)類型. 例如, 發(fā)送視頻需要較高的帶寬, 快速到達(dá)目的地, 以保證接收方看到連續(xù)的畫面. 而發(fā)送電子郵件可以使用較低的帶寬, 延遲幾個(gè)小時(shí)到達(dá)目的地也沒有關(guān)系.

    ?

    ??????IP 規(guī)定了 4 種服務(wù)類型, 用來定性地描述服務(wù)的質(zhì)量.

    • 低成本: 發(fā)送成本低.
    • 高可靠性: 保證把數(shù)據(jù)可靠地送達(dá)目的地.
    • 最高吞吐量: 一次可以接收或發(fā)送大批量的數(shù)據(jù).
    • 最小延遲: 傳輸數(shù)據(jù)的速度快, 把數(shù)據(jù)快速送達(dá)目的地.

    ??????這 4?種服務(wù)類型還可以進(jìn)行組合. 例如, 可以同時(shí)要求獲得高可靠性和最小延遲.

    ?

    ????? Socket 類中提供了設(shè)置和讀取服務(wù)類型的方法.

    • 設(shè)置服務(wù)類型: public void setTrafficClass(int trafficClass) throws SocketException
    • 讀取服務(wù)類型: public int getTrafficClass() throws SocketException

    ??????Socket?類用?4 個(gè)整數(shù)表示服務(wù)類型.

    • 低成本: 0x02 (二進(jìn)制的倒數(shù)第二位為1)
    • 高可靠性: 0x04 (二進(jìn)制的倒數(shù)第三位為1)
    • 最高吞吐量: 0x08 (二進(jìn)制的倒數(shù)第四位為1)
    • 最小延遲: 0x10 (二進(jìn)制的倒數(shù)第五位為1)

    ????? 例如,?以下代碼請(qǐng)求高可靠性傳輸服務(wù):

    ??socket = new Socket(host, port);
    ??socket.setTrafficClass(0x04);

    ?

    ????? 再例如, 以下代碼請(qǐng)求高可靠性和最小延遲傳輸服務(wù):

    socket.setTrafficClass(0x04|0x10);??????? //把 0x04 與 0x10 進(jìn)行位或運(yùn)算?????

    ?

    5.10?設(shè)定連接時(shí)間、延遲和帶寬的相對(duì)重要性

    ?

    ??????在 JDK 1.5 中, 還為 Socket 類提供了一個(gè) setPerformancePreferences() ?方法:

    ??????? public void?setPerformancePreferences(int connectionTime, int latency, int bandwidth)????????????? ?

    ?

    ??????以上方法的 3 個(gè)參數(shù)表示網(wǎng)絡(luò)傳輸數(shù)據(jù)的 3 選指標(biāo).

    • 參數(shù) connectionTime: 表示用最少時(shí)間建立連接.
    • 參數(shù) latency: 表示最小延遲.
    • 參數(shù) bandwidth: 表示最高帶寬.

    ??????setPerformancePreferences() 方法用來設(shè)定這 3 項(xiàng)指標(biāo)之間的相對(duì)重要性. 可以為這些參數(shù)賦予任意的整數(shù), 這些整數(shù)之間的相對(duì)大小就決定了相應(yīng)參數(shù)的相對(duì)重要性.

    ?

    ??????例如, 如果參數(shù) connectionTime 為 2, 參數(shù) latency 為 1, 而參數(shù)bandwidth 為 3, 就表示最高帶寬最重要, 其次是最少連接時(shí)間, 最后是最小延遲.

    轉(zhuǎn)載于:https://www.cnblogs.com/balaamwe/archive/2012/02/02/2335902.html

    總結(jié)

    以上是生活随笔為你收集整理的java socket/Serversocket编程详解(中/英文)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

    91麻豆视频网站 | .国产精品成人自产拍在线观看6 | 国产九九精品 | 日日夜夜添 | 国产网红在线观看 | 99电影| 中文字幕在线不卡国产视频 | 久久黄网站 | 夜夜夜夜猛噜噜噜噜噜初音未来 | 成人av在线一区二区 | 久久综合国产伦精品免费 | 免费h在线观看 | 精品视频久久 | 日韩一区二区三区视频在线 | 日韩在线免费观看视频 | 日韩性片| 国产精品18久久久久vr手机版特色 | 69精品视频在线观看 | 欧美精品久久久久久久久久丰满 | 日韩黄色网络 | 亚洲精品国产视频 | 欧美福利精品 | 亚洲免费精彩视频 | www..com黄色片 | 精品99视频 | 日韩精品视频一二三 | 免费网站看v片在线a | 99re6热在线精品视频 | 婷婷色九月 | 成人av影视观看 | 久久综合亚洲鲁鲁五月久久 | 18国产精品福利片久久婷 | 亚洲精品乱码久久久久久蜜桃欧美 | 99免费观看视频 | 免费色视频网站 | 成人av资源站 | 日韩国产在线观看 | 亚洲少妇自拍 | 国产香蕉视频在线播放 | 久久精品国产亚洲精品 | 免费观看版 | 亚洲国产成人在线播放 | 精品国产欧美一区二区 | 欧美另类xxxx| 亚洲精品综合在线观看 | 日韩精品一区二区三区丰满 | 99电影456麻豆 | av天天澡天天爽天天av | 国产精品乱码久久 | 午夜少妇一区二区三区 | 国产精品一码二码三码在线 | 成人免费视频播放 | 国产99久久久国产精品免费二区 | 久久乐九色婷婷综合色狠狠182 | 亚洲国产三级在线 | 亚洲九九九在线观看 | 国产手机视频在线观看 | 看av在线 | 开心激情综合网 | 国产a视频免费观看 | 精品亚洲免费视频 | 精品一区二区在线免费观看 | 中文字幕在线视频免费播放 | 丁香五月缴情综合网 | 国产中文在线视频 | 在线精品亚洲 | 久草手机视频 | 日本黄色大片儿 | 蜜桃麻豆www久久囤产精品 | 99超碰在线播放 | www.五月天婷婷 | 日本性xxxxx| 99视频在线观看一区三区 | 91久久丝袜国产露脸动漫 | 伊人色**天天综合婷婷 | 国产又粗又猛又爽又黄的视频先 | 天无日天天操天天干 | 亚洲精品午夜久久久久久久久久久 | 日日夜夜人人精品 | 97超碰成人在线 | av日韩国产 | 一级黄色片在线观看 | 99精品一级欧美片免费播放 | 久久免费的精品国产v∧ | 免费热情视频 | 久久在线免费观看视频 | 国产视频每日更新 | 久久www免费人成看片高清 | 午夜男人影院 | 国内精品久久久久久久久久清纯 | 中文字幕一区二区三区乱码不卡 | 99av在线视频 | 丁香婷婷电影 | 男女视频91| 综合影视| 国产成人精品综合久久久 | 色av男人的天堂免费在线 | av电影不卡在线 | 最近中文字幕第一页 | 99视频国产在线 | 久久黄色精品视频 | 久久久久久久久久网站 | 毛片网站观看 | 国产在线看| 亚洲一区二区观看 | 91视频在线观看下载 | 十八岁以下禁止观看的1000个网站 | 一区中文字幕在线观看 | av在线永久免费观看 | 成年人在线视频观看 | 日韩激情三级 | 国产日产精品一区二区三区四区 | 四虎国产精品免费观看视频优播 | 色综合天天爱 | 天天天天射| 国产在线一区二区三区播放 | 久久精品视频免费播放 | 国产精品黄色在线观看 | 色偷偷网站视频 | 亚州精品国产 | 久久涩涩网站 | 欧美亚洲免费在线一区 | 午夜国产一区二区 | 欧美日韩在线观看一区二区三区 | 久久伊人热 | 国产精品三级视频 | 黄色在线成人 | 又爽又黄在线观看 | 天天综合中文 | 免费a v视频 | 国产亚洲观看 | 香蕉网在线| 久草在线综合 | 日韩在线欧美在线 | 亚洲综合色视频在线观看 | 免费亚洲视频在线观看 | www.久久色 | 日韩二区在线观看 | 丁香综合网 | 色片网站在线观看 | 久久成人精品电影 | 色综合天天综合 | 在线视频第一页 | 国产精品99久久久久久久久久久久 | 国产精华国产精品 | 国产69精品久久久久久久久久 | 国产精品久久嫩一区二区免费 | 在线观看中文av | 久久99久久精品国产 | 久久久久久久久久国产精品 | 日韩av片无码一区二区不卡电影 | 97超碰精品 | 成人福利av| 视频在线99 | 一级黄色视屏 | 在线国产一区二区 | 婷婷性综合 | 国产精品久久久久一区二区国产 | 久久热亚洲 | 天天躁日日躁狠狠躁 | 免费av电影网站 | 天天射天天操天天色 | 夜夜躁日日躁狠狠久久av | 婷婷久月 | 国产精品一区二 | 久久久久在线观看 | 午夜久久视频 | 视频 国产区 | 亚洲免费公开视频 | 国产黄色高清 | 天天射狠狠干 | 伊人五月在线 | 黄色小说视频网站 | 99麻豆视频| 在线小视频你懂得 | 九九视频网 | 激情网色 | 中文字幕在线视频一区二区 | 久久国产精品99国产 | 国产18精品乱码免费看 | 一区二区视频在线观看免费 | 国产精品 中文在线 | 久久免费视频6 | 天天干天天色2020 | 国产视频久久久久 | 在线中文字幕观看 | 亚洲综合黄色 | 久久免费黄色 | 亚洲国产精品电影在线观看 | 91免费网站在线观看 | 国产 欧美 日韩 | 在线99| 国内精品久久久久影院日本资源 | 丁香久久综合 | 亚洲国产精品久久久久 | 亚洲成人免费在线 | 国产精品国产亚洲精品看不卡15 | 国产一级片免费播放 | 97久久精品午夜一区二区 | 国产啊v在线 | 亚洲人人精品 | 日韩精品专区 | 免费在线观看av网址 | 黄色国产区 | 国内精品视频在线 | 欧美精品国产综合久久 | 麻豆视频免费入口 | 久久久综合九色合综国产精品 | av大片免费在线观看 | 成人h在线观看 | 亚洲欧美激情精品一区二区 | 久久夜色精品亚洲噜噜国4 午夜视频在线观看欧美 | 日韩电影久久久 | 久草免费在线观看视频 | 免费精品在线观看 | 日本一区二区三区视频在线播放 | 91桃色免费视频 | 免费视频久久 | 国产成人亚洲在线电影 | 97手机电影网 | 国产91影院 | www178ccom视频在线 | 国产露脸91国语对白 | 久久久久久久久久免费 | 亚洲一二三久久 | 99精品视频免费看 | 日韩免| 五月婷婷在线播放 | 色噜噜狠狠狠狠色综合 | 91桃色免费视频 | 欧美日韩久久 | 五月丁香 | 97国产| 亚洲精品视频免费在线观看 | 日韩最新在线 | 免费成人在线视频网站 | 日韩性色 | 中文字幕在线观看三区 | 亚洲精品在线观看的 | 超碰在线98 | 久久久久久高潮国产精品视 | 狠狠干在线| 99久久精品久久久久久动态片 | 久久99操 | 欧美激情综合五月 | a黄色片在线观看 | 免费在线观看中文字幕 | 亚洲国产中文在线 | 97成人在线观看视频 | 五月激情五月激情 | 亚洲激情小视频 | 一级片免费视频 | 久久精品国产一区二区 | 99精品热| 天天草天天干天天射 | 亚洲一二三在线 | 在线看福利av | 国产精久久久 | a黄在线观看 | 欧美日韩免费网站 | 国产精品系列在线 | 色综合五月 | www五月 | 国产精品麻豆果冻传媒在线播放 | 亚洲欧美日本A∨在线观看 青青河边草观看完整版高清 | 色吧av色av| 国产成人精品久久久久 | 久久久久免费看 | 成人黄色小说在线观看 | 91精品国产电影 | 青青河边草手机免费 | 久久精品在线视频 | 狠狠干成人综合网 | 免费网站色 | 亚洲欧美在线综合 | 福利视频入口 | 麻豆精品在线 | 手机av电影在线 | 国产在线一线 | 2024av | 六月色播 | 国产高清不卡av | 国产精品粉嫩 | 狠狠狠狠狠狠干 | 欧美精品一区二区在线观看 | 久久久久久麻豆 | 一区二区伦理 | 日本三级香港三级人妇99 | 在线视频第一页 | 一区二区三区高清不卡 | 国产自在线| 久精品视频免费观看2 | 国产裸体bbb视频 | 色天天久久 | 成人黄色电影在线播放 | 欧美精品国产综合久久 | 亚洲婷婷丁香 | 波多野结衣小视频 | 色综合久久久久 | 99久久婷婷国产一区二区三区 | 精产嫩模国品一二三区 | 亚洲欧美成人综合 | 精品久久久久久国产偷窥 | 精品在线免费视频 | 91在线产啪| 欧美激情精品久久久久久免费 | 久久国产精彩视频 | 三级av中文字幕 | 日韩视频一二三区 | 国产福利不卡视频 | 成人av片免费观看app下载 | 日韩三级视频在线观看 | 91精品影视 | 久久午夜免费视频 | 午夜狠狠操 | 亚欧洲精品视频在线观看 | 国产精品久久一区二区三区不卡 | 久久亚洲区 | av免费在线观看1 | 91福利影院在线观看 | 天天射综合 | 黄色电影小说 | 国产一区二区视频在线 | 激情图片久久 | 国产在线观看你懂的 | 国产一级不卡视频 | 国产二区电影 | 最近乱久中文字幕 | 国内成人av | 天天爱天天操 | 久久人人爽人人片 | 亚洲视频六区 | 成人蜜桃 | 丁香六月婷婷 | 亚洲最新视频在线 | 在线观看国产区 | 国产玖玖视频 | 91av欧美| 黄色av成人在线观看 | 天天综合网久久综合网 | 天天操天天弄 | 亚洲精品在线视频播放 | 成人91在线观看 | 成人三级网站在线观看 | 日韩免费不卡视频 | 最近日本韩国中文字幕 | 992tv在线成人免费观看 | 97超碰成人在线 | 精品国产一区二区三区日日嗨 | 丝袜一区在线 | 五月天av在线 | 91福利影院在线观看 | 草久视频在线观看 | 中文字幕乱码在线播放 | 亚洲午夜剧场 | 91亚洲夫妻| 97综合视频 | 中文字幕在线观看网站 | 九九天堂| 国产精品9999 | 精品亚洲成a人在线观看 | 91精品久久香蕉国产线看观看 | 久久精品亚洲 | 少妇精69xxtheporn| 爱爱一区 | 久久精品久久久久 | 久久精品视频免费观看 | 久草在线免费看视频 | 久久久久久久av | 日韩欧美在线免费观看 | 在线观看的a站 | 麻豆精品视频 | 丁香影院在线 | 六月丁香激情综合色啪小说 | 国产免费xvideos视频入口 | 97国产电影 | 91 在线视频 | 人人爽人人搞 | av高清在线 | 人人爽人人舔 | 日韩欧美xxxx | 久久综合中文色婷婷 | 99精品影视 | www.天天射 | 久久综合久久综合这里只有精品 | 日韩欧美一区二区在线 | 波多野结衣在线视频一区 | 天天操人人要 | 天天射天天干天天爽 | 精品国自产在线观看 | 欧美激情视频一区二区三区 | 激情五月婷婷激情 | 国产精品美女久久久久久久网站 | 国产色在线观看 | 91精品国产自产在线观看 | 国内精品久久久久久久久久清纯 | 亚洲成a人片在线观看中文 中文字幕在线视频第一页 狠狠色丁香婷婷综合 | 国产高清成人在线 | 国产精品久久久久免费观看 | 亚洲日本在线一区 | 日韩av影视在线观看 | 国产一区在线免费观看 | 国产精品综合av一区二区国产馆 | 亚洲激精日韩激精欧美精品 | 免费日韩 精品中文字幕视频在线 | 久久国产精品视频免费看 | 午夜精品视频免费在线观看 | mm1313亚洲精品国产 | 六月丁香色婷婷 | 韩国三级av在线 | 国产资源免费在线观看 | 日韩免费不卡av | 国产免费黄视频在线观看 | 精品久久精品 | 一级全黄毛片 | 激情欧美丁香 | 久久综合久色欧美综合狠狠 | 欧美精品你懂的 | 色综合人人 | 亚洲一区美女视频在线观看免费 | 操久久免费视频 | 在线黄色国产电影 | 精品福利视频在线观看 | 精品一区二区日韩 | 中文字幕久久久精品 | 在线观看黄色国产 | 91免费试看| 日韩免费观看高清 | 久久免费大片 | 国产精品综合在线 | 亚洲精品99久久久久久 | 天天操天天干天天爱 | 国产免费高清视频 | 亚洲专区在线播放 | 黄色亚洲片 | 深爱婷婷 | 免费亚洲黄色 | 婷婷五情天综123 | 又黄又爽又无遮挡的视频 | 天天躁日日躁狠狠躁av中文 | 中文字幕av在线电影 | 一区二区三区高清不卡 | 亚一亚二国产专区 | 免费在线视频一区二区 | 成片免费观看视频 | 在线精品在线 | 成人啪啪18免费游戏链接 | www.夜夜操.com | 中文字幕免费高清av | 精品久久国产精品 | 久久成人欧美 | 免费福利视频网站 | 欧美一级激情 | 久久久久久不卡 | 国产精品久久嫩一区二区免费 | 国产四虎影院 | 91丨九色丨91啦蝌蚪老版 | 日韩中字在线 | 亚洲黄色免费观看 | 亚洲人成人在线 | 国产精品一区免费在线观看 | 日日爱视频 | 五月天天色 | 99精品视频在线 | 国产成人精品一区二区 | 精品国产一区二区三区av性色 | 日韩欧美一区二区在线播放 | 激情综合啪| 狠狠色狠狠色综合系列 | 午夜视频日本 | 欧美激情精品久久久久久变态 | 欧美成人999| 久久久国产一区二区三区 | 亚洲午夜久久久久久久久电影网 | 伊人婷婷 | 午夜精品久久久久久久久久久 | 天天操天| 欧美黄污视频 | 免费看国产视频 | 久久伊99综合婷婷久久伊 | 少妇bbw搡bbbb搡bbb | 日韩在线观看 | 中文字幕乱在线伦视频中文字幕乱码在线 | 亚洲综合在线五月天 | 中文在线免费观看 | 久久久99久久 | 免费黄色在线 | 97免费视频在线播放 | 亚洲成色777777在线观看影院 | 99视频在线免费观看 | aa级黄色大片 | 在线精品视频在线观看高清 | 久久免费成人网 | 国产精品美女免费看 | 国产精品高潮久久av | 国产色一区 | 91热爆视频| 亚洲免费视频在线观看 | 中文字幕在线观看第一页 | 在线观看日韩中文字幕 | 在线之家免费在线观看电影 | 亚洲国产精品va在线看黑人 | 色婷婷丁香 | 天天干天天操天天拍 | 97精品国产91久久久久久久 | 日韩视频一区二区三区在线播放免费观看 | 婷婷国产在线 | 美女国产| 99久久日韩精品视频免费在线观看 | 91在线影视 | 色就是色综合 | 婷婷五月色综合 | 91久久久国产精品 | 成人久久影院 | 伊人狠狠 | 中文字幕永久在线 | 国产精品igao视频网网址 | 久久免费国产视频 | 欧美精品中文在线免费观看 | 久久男人中文字幕资源站 | 一区二区视频播放 | 亚洲资源一区 | 免费观看视频的网站 | 人人插人人草 | 在线观看麻豆av | 国产主播大尺度精品福利免费 | 少妇高潮流白浆在线观看 | 免费在线国产 | 日韩在线三级 | 免费午夜av | 精品在线观看视频 | 国产精品美女视频 | 国产成人一区二区三区在线观看 | 波多野结衣日韩 | 日av免费| 毛片随便看 | 色综合久久久久综合99 | 久久免费视频播放 | 91中文在线视频 | 探花视频在线观看免费 | 就要干b| 国产福利电影网址 | 伊人五月 | 免费在线观看av的网站 | 久久99热精品 | 日本黄色免费看 | 在线观看亚洲电影 | 国产一区二区在线免费播放 | 麻豆传媒在线免费看 | 性日韩欧美在线视频 | 欧美一区二区在线 | 免费av在线 | 超黄视频网站 | 91av视频导航| 亚洲精品三级 | 亚洲精品在线观看视频 | 天天干,天天操 | 五月丁婷婷 | 亚洲精品无 | 国产精品久久人 | 一本色道久久综合亚洲二区三区 | 国产精品免费视频网站 | 色午夜影院 | 女女av在线| av片一区 | 亚洲精品乱码久久久久久蜜桃动漫 | bbbbb女女女女女bbbbb国产 | 五月综合 | 一区二区精品 | 成人蜜桃视频 | 91色国产| 成年人在线免费看视频 | wwwwww黄| 在线观看免费色 | 毛片888| 国产玖玖精品视频 | 久久久久成人精品免费播放动漫 | 亚洲精品久久久蜜桃 | 欧美成人视| 中文字幕在线免费97 | 91日韩在线 | 久久久三级视频 | 久久99中文字幕 | 97免费中文视频在线观看 | 日韩欧美一区二区在线观看 | 久久人人97超碰com | 日韩免费电影一区二区 | 国产精品国产三级国产aⅴ无密码 | 制服丝袜欧美 | 中文字幕在线看视频国产中文版 | av福利在线看 | 五月婷婷在线视频观看 | 一区二区av | 国产麻豆成人传媒免费观看 | 色综合天天视频在线观看 | 日韩精品在线观看av | 91精品入口 | 久久一本综合 | 日本福利视频在线 | 一区二区三区视频在线 | 国产精品一区二区三区电影 | 久草精品视频在线看网站免费 | 精品一区二区三区久久 | 亚洲电影网站 | 97在线视频免费播放 | 久久久久国产精品一区 | 欧美aⅴ在线观看 | 国产日韩精品在线 | 国产精品美女久久久久久网站 | 在线观看免费视频 | 天天草天天插 | 免费看的国产视频网站 | 国产高清不卡一区二区三区 | 成年人免费电影在线观看 | 丝袜美女在线 | 日韩欧美99| 91桃色视频 | a成人在线| 四季av综合网站 | 不卡av电影在线 | 亚洲作爱 | 日本婷婷色 | 成人国产精品久久久久久亚洲 | 国产高清视频免费在线观看 | 丁香六月五月婷婷 | 美女在线国产 | 久久一区国产 | 国产一级免费片 | 久久亚洲成人网 | 国产午夜在线 | 美女视频黄是免费的 | 日韩精品久久久久久久电影竹菊 | 久久一区二区三区超碰国产精品 | 欧美调教网站 | 欧美另类巨大 | 国产在线a | 人人藻人人澡人人爽 | 99情趣网视频 | 国产字幕av| 九九热av| 成人av电影免费在线播放 | 日韩在线精品视频 | 色在线高清 | 久久ww| 久久er99热精品一区二区三区 | 国产美女黄网站免费 | 免费在线观看日韩视频 | 国产免费嫩草影院 | wwwwwww色 | 91高清免费观看 | 天天干夜夜 | 国产精品va在线播放 | 久久久久久毛片精品免费不卡 | 久久99国产精品免费网站 | 久久久69| 日韩在线一区二区免费 | 91视频亚洲 | 亚洲色影爱久久精品 | 最新成人av| 免费a级黄色毛片 | 久久成人一区二区 | 成人免费观看完整版电影 | 久久久色 | 涩涩网站在线观看 | 日韩视频中文字幕在线观看 | 天天干夜夜 | 国产三级精品三级在线观看 | 午夜精品久久久久久久99婷婷 | 亚洲第一区在线观看 | 蜜臀aⅴ国产精品久久久国产 | 婷婷精品国产欧美精品亚洲人人爽 | 日本精品久久久久影院 | 久久综合狠狠综合久久综合88 | 亚州日韩中文字幕 | 天天操天天干天天干 | 91亚洲精品国偷拍 | 超碰人人国产 | 免费看污污视频的网站 | 天天插视频 | 久草电影免费在线观看 | 成人免费视频观看 | 在线观看免费av片 | 日韩美女久久 | 四虎在线免费 | 国产精品欧美精品 | 天天操夜夜操夜夜操 | 日韩精品中字 | 91在线资源 | 黄色成人免费电影 | 黄色一级动作片 | 国产很黄很色的视频 | 婷婷久久亚洲 | 黄色视屏av | 日日夜夜噜噜噜 | 97热久久免费频精品99 | 夜夜夜夜夜夜操 | 久av在线 | 成人性生交大片免费观看网站 | 96久久精品| 免费在线国产黄色 | 久久久91精品国产一区二区三区 | 国产高清视频在线播放 | 少妇bbw搡bbbb搡bbb | 精品久久久久一区二区国产 | 日韩视频免费播放 | 国产精品99久久久久久大便 | 永久免费毛片在线观看 | 欧美一二三区在线观看 | 视频在线观看国产 | 在线看国产视频 | 欧美精品在线一区 | 亚洲成人精品国产 | 在线亚洲观看 | 99精品一区二区 | 日韩黄色在线电影 | 亚洲在线国产 | 国产午夜三级一区二区三桃花影视 | 91日韩精品视频 | 黄色大片入口 | 久久久久久高潮国产精品视 | 午夜成人免费电影 | 国产护士hd高朝护士1 | 园产精品久久久久久久7电影 | 欧美在线不卡一区 | 九九视频精品免费 | 在线蜜桃视频 | 亚洲国产中文字幕在线观看 | 久久国产精品影片 | 日韩一级黄色av | 99久高清在线观看视频99精品热在线观看视频 | 久久伊99综合婷婷久久伊 | 亚洲男男gaygayxxxgv | 久久综合亚洲鲁鲁五月久久 | 国产精品欧美一区二区三区不卡 | 丰满少妇高潮在线观看 | 国产区久久 | 草 免费视频 | 欧美精品乱码99久久影院 | 亚一亚二国产专区 | 久久久久久久久久久电影 | 日韩一级片网址 | 国产精品自拍av | 欧美国产高清 | 久久夜色网 | 一级黄色在线免费观看 | 粉嫩一区二区三区粉嫩91 | 日韩成人精品一区二区 | 91aaa在线观看| 91黄色影视| 成年人在线观看 | 日韩丝袜在线观看 | 久久免费视频3 | 色爱成人网| 国产性天天综合网 | 久久爱综合 | www.伊人色.com | 一区在线免费观看 | 久久8| 狠狠色丁香久久综合网 | 一区二区毛片 | av免费看在线 | a久久久久久 | 国产麻豆剧果冻传媒视频播放量 | 天天射射天天 | 精品美女在线视频 | 欧美日韩在线观看一区 | 摸bbb搡bbb搡bbbb | 中文字幕日韩av | 日韩av一区二区三区四区 | 久久99这里只有精品 | 四虎在线永久免费观看 | 久久精品视频18 | 久久久久久久久久久网 | 国产麻豆精品一区二区 | 日韩欧美在线不卡 | 99电影 | 亚洲区精品视频 | 91看片成人 | 国产高清视频在线观看 | 精品在线观看一区二区 | 国产精品成人一区二区三区吃奶 | 日韩手机在线 | 美女久久久久久久久久久 | 国产精品网红福利 | 日日夜夜精品网站 | 人人狠狠综合久久亚洲 | 欧美a级在线 | 国产69精品久久99不卡的观看体验 | 国产成a人亚洲精v品在线观看 | 国产成年免费视频 | 国产成人精品久久亚洲高清不卡 | av字幕在线 | 久久久久国产a免费观看rela | 91在线日本| 日韩精品中文字幕在线观看 | 久久激情婷婷 | 久久综合干 | 亚洲高清网站 | 人人插人人搞 | 亚洲精品国产成人av在线 | 国产色影院 | 中文字幕视频三区 | 婷婷久月 | 欧美在线视频免费 | 视频一区在线免费观看 | 日韩欧美黄色网址 | 九九热在线精品视频 | 天天操天天操天天操天天操 | 中文字幕视频一区二区 | 中文字幕在线播出 | 国产精品毛片一区二区在线 | 一区二区男女 | 亚洲精品乱码 | 最近高清中文字幕 | 综合色天天| 99九九热只有国产精品 | 日韩欧美国产激情在线播放 | avav片| 一级成人在线 | 久久免费视频这里只有精品 | 日日日操 | 久久久私人影院 | 91丨九色丨国产在线 | 深爱激情婷婷网 | 在线观看国产 | 蜜桃av综合网 | 麻豆一精品传二传媒短视频 | av天天澡天天爽天天av | 亚洲精色 | 国产精品video爽爽爽爽 | 免费观看全黄做爰大片国产 | 亚洲理论在线观看电影 | 欧美福利在线播放 | se婷婷 | 久久九九网站 | 天天射天天干天天爽 | 正在播放国产一区 | 午夜婷婷网 | 成人av一区二区在线观看 | 欧美日本高清视频 | 一级a性色生活片久久毛片波多野 | 亚洲毛片视频 | 美女网站色在线观看 | 婷婷色影院 | 在线视频a | 精品一区二区在线免费观看 | 国产一区二区在线观看免费 | 国产成人61精品免费看片 | 91中文在线 | 日韩在线观看视频免费 | 久久久久欧美精品999 | 国产亚洲精品久久久久久移动网络 | 欧美成人亚洲成人 | 色激情五月| 黄色三级免费 | 国内一区二区视频 | 伊人久久国产 | 国产二区电影 | 天天干,天天操,天天射 | 黄色网在线免费观看 | 四虎在线观看网址 | 亚洲一级片在线看 | 亚洲另类视频在线 | 欧美精品视 | 日韩午夜小视频 | 狠狠干婷婷 | 婷婷视频 | 欧美午夜理伦三级在线观看 | 国产黄a三级三级三级三级三级 | av五月婷婷| 91天堂素人约啪 | 久久网页 | 久久久久久久免费 | 日韩成人免费电影 | 欧美精品在线一区 | 成人国产亚洲 | 亚av在线 | 成人免费在线看片 | 免费av小说| 少妇搡bbbb搡bbb搡忠贞 | 日韩在线视频看看 | 日韩黄色大片在线观看 | 在线国产一区二区三区 | 91av在线视频播放 | 精品亚洲欧美一区 | 91完整版在线观看 | 亚洲九九影院 | 久久国产免费看 | 五月天色丁香 | 欧美a√大片 | 亚洲日本色 | 99热最新地址 | 午夜精品一区二区三区在线观看 | 欧美日韩在线观看不卡 | 国产精品午夜久久久久久99热 | 国产精品成人自产拍在线观看 | 一区二区三区日韩视频在线观看 | 中文字幕精品www乱入免费视频 | 亚洲春色综合另类校园电影 | 婷婷六月综合网 | 天天爽夜夜爽人人爽一区二区 | 久久av网址 | 国产精品久久久久免费观看 | 国产成人精品久久二区二区 | 色综合中文字幕 | 五月天六月丁香 | 黄色电影网站在线观看 | 三级视频日韩 | 日韩欧美视频在线观看免费 | 亚洲mv大片欧洲mv大片免费 | 欧美一二三视频 | 97在线观看视频免费 | 不卡电影一区二区三区 | 狠狠狠色丁香综合久久天下网 | 欧美日一级片 | av中文字幕在线免费观看 | 欧洲精品视频一区二区 | 五月婷丁香网 | 亚洲欧美999 | 欧美精品色 | 伊人成人激情 | 国产精品18久久久久久首页狼 | 激情视频一区二区 | 操夜夜操 | 久久精品aaa | 色综合久久中文字幕综合网 | 精品国产aⅴ麻豆 | 亚洲高清免费在线 | 日本久久久影视 | 国产人成在线视频 | 日韩欧美视频在线播放 | 免费在线观看污 | 国产精品孕妇 | 国产婷婷色 | 国产成人一区二区啪在线观看 | 激情视频综合网 | 国产高清在线看 | 91色综合| 亚洲视频电影在线 | 国产精品美女毛片真酒店 | 久久经典国产视频 | 国产午夜麻豆影院在线观看 | 亚洲91中文字幕无线码三区 | 亚洲老妇xxxxxx| 最近中文字幕大全中文字幕免费 | 色激情五月 | 欧美巨大荫蒂茸毛毛人妖 | 亚洲精品美女久久久久 | 亚洲3级| 日韩爱爱网站 | 亚洲免费在线观看视频 | 欧美久久影院 | 久久伊人精品天天 | 黄色aaa级片 | 久久久久免费观看 | 日韩免费高清在线 | 欧美日韩久久一区 | 日韩乱码在线 | 国产一区高清在线 | 在线日本看片免费人成视久网 | 国产男女免费完整视频 | 欧美极品在线播放 | 久久永久视频 | 亚洲视屏在线播放 | 欧美成天堂网地址 | 在线性视频日韩欧美 | 精品国产一区二区三区久久久久久 | 亚洲精品www久久久久久 | 久久国产精品一区二区 | 久久艹影院 | 天天天天爱天天躁 | 在线小视频| 中文在线字幕免费观看 | 欧美激情一区不卡 | 天天色官网 | 国产精品欧美一区二区三区不卡 | 亚洲一区精品二人人爽久久 | 国产一级大片在线观看 | 91激情视频在线播放 | 在线免费观看的av网站 | 免费精品人在线二线三线 | 91视频电影 | av免费福利 | 免费av在线网站 | 亚洲免费视频在线观看 | 色综合咪咪久久网 | 日韩精品一区在线观看 | 五月婷婷丁香色 | 亚洲天堂精品 | 日韩av午夜 | 国产明星视频三级a三级点| 91福利社区在线观看 | 国内视频一区二区 | 欧美成人xxxx| 最近更新好看的中文字幕 | 天天干天天天天 | 久久国产精品系列 | 国产999视频|