java Socket開發(fā)
- 資格考試
- 2024-06-12 12:59:41
java中什么是socket編程
網(wǎng)絡(luò)上的兩個(gè)程序通過(guò)一個(gè)雙向的通訊連接實(shí)現(xiàn)數(shù)據(jù)的交換,這個(gè)雙向鏈路的一端稱為一個(gè)Socket。Socket通常用來(lái)實(shí)現(xiàn)客戶方和服務(wù)方的連接。Socket是TCP/IP協(xié)議的一個(gè)十分流行的編程界面,一個(gè)Socket由一個(gè)IP地址和一個(gè)端口號(hào)唯一確定。 但是,Socket所支持的協(xié)議種類也不光TCP/IP一種,因此兩者之間是沒(méi)有必然聯(lián)系的。在Java環(huán)境下,Socket編程主要是指基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程。java編程中,Socket通信是怎么實(shí)現(xiàn)的?
java編程對(duì)于Socket之間的通信過(guò)程如下:
服務(wù)端往Socket的輸出流里面寫東西,客戶端就可以通過(guò)Socket的輸入流讀取對(duì)應(yīng)的內(nèi)容。Socket與Socket之間是雙向連通的,所以客戶端也可以往對(duì)應(yīng)的Socket輸出流里面寫東西,然后服務(wù)端對(duì)應(yīng)的Socket的輸入流就可以讀出對(duì)應(yīng)的內(nèi)容。下面來(lái)看一些服務(wù)端與客戶端通信的例子:
publicclassServer{
publicstaticvoidmain(Stringargs[])throwsIOException{
//為了簡(jiǎn)單起見,所有的異常信息都往外拋
intport=8899;
//定義一個(gè)ServerSocket監(jiān)聽在端口8899上
ServerSocketserver=newServerSocket(port);
//server嘗試接收其他Socket的連接請(qǐng)求,server的accept方法是阻塞式的
Socketsocket=server.accept();
//跟客戶端建立好連接之后,我們就可以獲取socket的InputStream,并從中讀取客戶端發(fā)過(guò)來(lái)的信息了。
Readerreader=newInputStreamReader(socket.getInputStream());
charchars[]=newchar[64];
intlen;
StringBuildersb=newStringBuilder();
while((len=reader.read(chars))!=-1){
sb.append(newString(chars,0,len));
}
System.out.println("fromclient:"+sb);
reader.close();
socket.close();
server.close();
}
}
客戶端代碼
Java代碼publicclassClient{
publicstaticvoidmain(Stringargs[])throwsException{
//為了簡(jiǎn)單起見,所有的異常都直接往外拋
Stringhost="127.0.0.1";//要連接的服務(wù)端IP地址
intport=8899;//要連接的服務(wù)端對(duì)應(yīng)的監(jiān)聽端口
//與服務(wù)端建立連接
Socketclient=newSocket(host,port);
//建立連接后就可以往服務(wù)端寫數(shù)據(jù)了
Writerwriter=newOutputStreamWriter(client.getOutputStream());
writer.write("HelloServer.");
writer.flush();//寫完后要記得flush
writer.close();
client.close();
}
}
java中socket編程
import java.io.*; import java.net.*; class UDPClient{ public static void main(String args[]) throws Exception{ DatagramSocket clientSocket = new DatagramSocket(); InetAddress IPAddress = InetAddress.getByName("localhost"); byte[] sendData = "F6".getBytes(); byte[] receiveData = new byte[64]; Datagra用java做socket開發(fā)應(yīng)用執(zhí)行效率怎么樣
一般這種情況用HTTP比較多,類似soap。 jsp,或者asp,php,python等都可以直接發(fā)http get或post的,接口靈活。 如果是純粹的網(wǎng)絡(luò)程序,java的socket通信比起c/c++還是稍弱了一些,畢竟,中間要經(jīng)過(guò)java虛擬機(jī)。還有,如果做圖像處理,視頻等對(duì)內(nèi)存要求比較大的時(shí)候,JAVA也有麻煩。Java Socket開發(fā) 關(guān)于報(bào)文傳遞和接收
看 Oracle 官方教程,同步式的 Socket 就是傳統(tǒng)的一問(wèn)一答方式,它就是你需要的。
客戶端先 socket.getOutputStream().write(...); 之后到 socket.getInputStream().read(byte[]) 在循環(huán)中讀取直到 read 方法返回 -1 或你期望的字節(jié)數(shù)已經(jīng)全部收到了就停下來(lái),如果不嘗試停下來(lái),后面的 read 將會(huì)阻塞等待。
http://docs.oracle.com/javase/tutorial/networking/sockets/index.html
基于性能改進(jìn),一般我們需要使用 NIO 異步的 socket,只需要一個(gè)線程負(fù)責(zé)通信,每個(gè)線程都有自己的出站消息隊(duì)列和入站消息隊(duì)列,以線程為 key 區(qū)分開,通信線程只負(fù)責(zé)把各自的消息從出站隊(duì)列中發(fā)送去并把收到的消息放入入站隊(duì)列中,應(yīng)用程序線程就去各自的消息隊(duì)列中取消息就可以了。因?yàn)槊總€(gè)應(yīng)用線程有各自的消息隊(duì)列,我們把消息放入出站隊(duì)列之后就到入站隊(duì)列上用同步鎖等待的方法阻塞到有消息回答時(shí)為止。
關(guān)于 NIO non-blocking 非阻塞式 socket,下面有一個(gè) NBTimeServer 例子,它講的是服務(wù)端。客戶端與此類似,
http://docs.oracle.com/javase/7/docs/technotes/guides/io/example/index.html
NIO 通信線程樣例。
publicvoidrun()
{
inttip=0;
try
{
selector=Selector.open();
SelectionKeyk=channel.register(selector,getInterestOptions());
k.attach(thread);//把當(dāng)前線程綁定到附件中。
this.running=true;
statusChanged(Status.CONNECTED);
while(this.isRunning())
{
//select()isablockingoperation.
inteventCount=selector.select();
debug("[MC.Debug]PollingTCPevents..."+eventCount);
if(eventCount>0&&channel.isOpen()&&this.isRunning())
{
Setkeys=selector.selectedKeys();
for(Iteratoriter=keys.iterator();iter.hasNext();iter.remove())
{
SelectionKeykey=(SelectionKey)iter.next();
Threadthread=(Thread)key.attachment();
if(!key.isValid())
{//channelisclosing.
break;
}
process(key);//處理讀取消息并把消息放入thread對(duì)應(yīng)的隊(duì)列。//寫出消息類似的,不過(guò)在register時(shí)需要注冊(cè)寫出允許的事件,
}
}
}
}