java socket編程實例 JAVA編程實例

大家好,今天小編來為大家解答java這個問題,JAVA編程實例很多人還不知道,現在讓我們一起來看看吧!遇到java.net.SocketTimeoutException...
大家好,今天小編來為大家解答java這個問題,JAVA編程實例很多人還不知道,現在讓我們一起來看看吧!
遇到java.net.SocketTimeoutException:Readtimedout怎么辦
連接超時,確保網絡通暢后重連,若還連不上是他們服務器的問題這樣可以么?
java socket客戶端怎樣確認服務器端是否收到數據
在服務端接收完數據之后返回一個接收完畢的通知給客戶端,告訴客戶端我已經把數據接收完了。
如何使用Socket在客戶端實現長連接
長連接貌似是一個很高深莫測的知識,但是只要你做直播、IM、游戲、彈幕里面的任何一種,或者是你的app想要實時的接收某些消息,你就會要接觸到長連接技術。本文主要教你如何在客戶端如何使用Socket實現長連接。
Socket背景知識
要做長連接的話,是不能用http協議來做的,因為http協議已經是應用層協議了,并且http協議是無狀態的,而我們要做長連接,肯定是需要在應用層封裝自己的業務,所以就需要基于TCP協議來做,而基于TCP協議的話,就要用到Socket了。
Socket是java針對tcp層通信封裝的一套網絡方案
TCP協議我們知道,是基于ip(或者域名)和端口對指定機器進行的點對點訪問,他的連接成功有兩個條件,就是對方ip可以到達和端口是開放的
Socket能幫完成TCP三次握手,而應用層的頭部信息需要自己去解析,也就是說,自己要制定好協議,并且要去解析byte
http也有長連接。在http1.0的時候,使用的是短連接,也就是說,每次請求一次數據,都要重新建立連接。但是從http1.1之后,我們看到頭部會有一個
Connection:keep-alive
這個表示tcp連接建立之后不會馬上銷毀,而是保存一段時間,在這段時間內如果需要請求改網站的其他數據,都是使用這個連接來完成傳輸的。
Socket使用方式
Socket看上去不是很好用,因為他是基于java.io來實現的,你要直接跟InputStream和OutputStream打交道,也就是直接跟byte[]打交道,所以用起來并不是這么友好。
下面通過一個簡單的例子,往一臺服務器發\01\00\00\00\00這一串字節,服務器也返回相同的字節流,上代碼:
@Test
publicvoidtestSocket()throwsException{
logger.debug("start");
Socketsocket=newSocket();
socket.connect(address);
byte[]output=newbyte[]{(byte)1,(byte)0,(byte)0,(byte)0,(byte)0};
socket.getOutputStream().write(output);
byte[]input=newbyte[64];
intreadByte=socket.getInputStream().read(input);
logger.debug("readByte"+readByte);
for(inti=0;i<readByte;i++){
logger.debug("read["+i+"]:"+input[i]);
}
socket.close();
}
輸出:
11:40:40.326[main]DEBUGcom.roy.test.SocketTest-start
11:40:40.345[main]DEBUGcom.roy.test.SocketTest-readByte5
11:40:40.345[main]DEBUGcom.roy.test.SocketTest-read1
11:40:40.345[main]DEBUGcom.roy.test.SocketTest-read0
11:40:40.345[main]DEBUGcom.roy.test.SocketTest-read0
11:40:40.345[main]DEBUGcom.roy.test.SocketTest-read0
11:40:40.345[main]DEBUGcom.roy.test.SocketTest-read0
看出來寫起來還是比較麻煩的,主要就是InputStream,OutputStream和byte[]使用起來太不方便了。
SocketChannelblocking
Socket為了優化自己的封裝和并發性能,推出了nio包下面的SocketChannel,這個相比于Socket的好處就是并發性能的提高和封裝的優化了。
SocketChannel有兩種方式——阻塞和非阻塞的,阻塞的用法和Socket差不多,都是在read和write的時候會阻塞線程,下面用一段代碼來實現相同的功能。
@Test
publicvoidtestSocketChannelBlock()throwsException{
finalSocketChannelchannel=SocketChannel.open(address);
ByteBufferoutput=ByteBuffer.allocate(5);
output.put((byte)1);
output.putInt(0);
output.flip();
channel.write(output);
logger.debug("writecomplete,startread");
ByteBufferinput=ByteBuffer.allocate(5);
intreadByte=channel.read(input);
logger.debug("readByte"+readByte);
input.flip();
if(readByte==-1){
logger.debug("readByte==-1,return!");
return;
}
for(inti=0;i<readByte;i++){
logger.debug("read["+i+"]:"+input.get());
}
}
log輸出:
23:24:34.684[main]DEBUGcom.dz.test.SocketTest-writecomplete,startread
23:24:34.901[main]DEBUGcom.dz.test.SocketTest-readByte5
23:24:34.901[main]DEBUGcom.dz.test.SocketTest-read[0]:1
23:24:34.901[main]DEBUGcom.dz.test.SocketTest-read[1]:0
23:24:34.901[main]DEBUGcom.dz.test.SocketTest-read[2]:0
23:24:34.901[main]DEBUGcom.dz.test.SocketTest-read[3]:0
23:24:34.901[main]DEBUGcom.dz.test.SocketTest-read[4]:0
從上面的。封裝優化主要體現在ByteBuffer,IntBuffer這一系列類的封裝——因為是網絡相關的,所以這里用到的主要是ByteBuffer。
ByteBuffer和byte[]最大的區別,就是ByteBuffer可以很方便的讀取int,long等數據類型,他提供了getInt(),getInt(intoffset)這樣的方法,這種方法主要用在識別頭部數據部分,因為頭部數據一般都是由多種數據類型組成,比方說表示數據格式的contentType:String,表示長度的length:int等等,這些就是getInt()這樣的方法主要的應用場景,而byte[]如果要取int,String相對來說就要復雜一些了,這是java.nio相比于java.io優勢的一點。
這里需要說明一個比較坑的點,就是ByteBuffer.flip()這個方法,這個方法的作用主要是重置索引,在write()之前和read()之后調用,否則會因為索引不對,導致你的數據寫不進去,讀不出來。
ByteBuffer是一個功能強大的類,因為本文主要是講Socket和SocketChannel,所以在這里就不做過多描述。具體ByteBuffer的詳細介紹,可以參考:JavaNIO系列教程(三)Buffer
而nio相比于io最大的優勢還是在于并發性能,因為nio里面的n代表的就是non-blocking的意思,上面那個讀取數據的代碼也相對老舊,一般我們如果要用SocketChannel,都是用non-blocking的方式來實現的,而如果要用non-blocking模式,首先要介紹的就是Selector。
Selector
我們知道,傳統io是阻塞的,也就是說,一個線程只能處理一個io流,也就是一個Socket。有了Selector之后,一個線程就能處理多個SocketChannel。
Selector的原
自學java感到學到自己的瓶頸期了,各種框架亂七八糟,感覺好亂。該怎么辦
下面是我的視頻里大概要介紹的內容:
如何看待框架知其然,知其所以然。不僅要學會使用框架,還需要學會框架的原理。最好的方法是自己動手模仿著做一下。一動手你就開始從框架設計者的角度考慮問題了。你思考問題的角度和高度就和以前不一樣了。
如何突破瓶頸,更上一層樓學習算法和設計模式。思考框架要解決的本質問題。評價這種方法的優缺點。如果是你,你有什么改進意見。可以參考我的動畫視頻,講解了很多分布式系統的設計原理。
推薦幾本好書,值得精讀很多遍的書大多數人的悟性是差不多的。多讀好書,可以從前輩大牛,甚至是世界級頂級專家那里得到指導和啟發。
下面這本書是MIT的本科教材,網上有作者的公開課。可以找了看看。
下面這本書是關于分布式系統應用設計中遇到的問題和通常的解決思路。比如hadoop,kafka,flink,zookeeper,raft他們都是用來解決什么問題的。
本人,@小馬過河Vizit,專注于分布式系統原理和實踐分享。希望利用動畫生動而又準確地演示抽象的原理。
關于我的名字。小馬過河Vizit,意為凡事像小馬過河一樣,需要自己親自嘗試、探索才能獲得樂趣和新知。Vizit是指Visualizeit的縮寫。一圖勝千言,希望可以利用動畫來可視化抽象的原理。
歡迎關注,點贊!謝謝支持。
socket建立連接的步驟
javasocket建立連接的過程如下:
1、首先調用Socket類的構造函數,以服務器的指定的IP地址或指定的主機名和指定的端口號為參數,創建一個Socket流,在創建Socket流的過程中包含了向服務器請求建立通訊連接的過程實現。
2、建立了客戶端通訊Socket后。就可以使用Socket的方法getInputStream()和getOutputStream()來創建輸入/輸出流。這樣,使用Socket類后,網絡輸入輸出也轉化為使用流對象的過程。
3、使用輸入輸出流對象的相應方法讀寫字節流數據,因為流連接著通訊所用的Socket,Socket又是和服務器端建立連接的一個端點,因此數據將通過連接從服務器得到或發向服務器。這時我們就可以對字節流數據按客戶端和服務器之間的協議進行處理,完成雙方的通訊任務。
4、待通訊任務完畢后,我們用流對象的close()方法來關閉用于網絡通訊的輸入輸出流,在用Socket對象的close()方法來關閉Socket。
socket雙向連接的建立過程
javasocket建立連接的過程如下:socket
1、首先調用Socket類的構造函數,以服務器的指定的IP地址或指定的主機名和指定的端口號為參數,創建一個Socket流,在創建Socket流的過程中包含了向服務器請求建立通訊連接的過程實現。
2、建立了客戶端通訊Socket后。就可以使用Socket的方法getInputStream()和getOutputStream()來創建輸入/輸出流。這樣,使用Socket類后,網絡輸入輸出也轉化為使用流對象的過程。
3、使用輸入輸出流對象的相應方法讀寫字節流數據,因為流連接著通訊所用的Socket,Socket又是和服務器端建立連接的一個端點,因此數據將通過連接從服務器得到或發向服務器。這時我們就可以對字節流數據按客戶端和服務器之間的協議進行處理,完成雙方的通訊任務。
4、待通訊任務完畢后,我們用流對象的close()方法來關閉用于網絡通訊的輸入輸出流,在用Socket對象的close()方法來關閉Socket。
OK,本文到此結束,希望對大家有所幫助。
本文鏈接:http://www.resource-tj.com/su/4163.html