1. 程式人生 > >java 網路 socket TCP / UDP / catch 語句塊捕捉到異常後,繼續執行語句塊後面的程式碼

java 網路 socket TCP / UDP / catch 語句塊捕捉到異常後,繼續執行語句塊後面的程式碼

java 網路 socket TCP / server 端

package test.java.Net;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.*;
/**
 * 
 * @author jalo
 * 如果是客戶端和服務端互動讀寫的話,兩方必須,有一個先寫後讀,有一個先讀後寫
 */
public class TCPServer { //在網路應用程式的編寫中,server / client一塊寫。在啟動的時候,也是首先起server,再起client
	public static void main(String args[]) throws IOException  {
		System.out.println("server");
		ServerSocket ss = null;
		try {
			ss = new ServerSocket(6666);
		} catch (IOException e) {
			System.out.println("不能監聽埠" + e);
			System.exit(0);//如果寫的嚴謹一點,這裡應該系統退出,不繼續往下執行//catch 丟擲異常,直接執行後面catch 語句塊後面的語句
		} //server的應用程式往往是不間斷的在執行,他在等待著客戶端的連線。
							//客戶端一連上,他才會執行。這是阻塞式連線。這句話完成,這個埠已經監聽。這時我們寫client 端
		////////////////client 端已經申請連線我了,我server 是不是接收這個連線請求還是個問題
		while(true){//以下幾句如果不加while(true),那隻能接受一個連線。有了,則連一個我列印一個,然後再等待下一個。這才是真正的server,7*24*365
			Socket s = ss.accept();     //accept 這個方法是阻塞式的,到這就停止,如果沒有任何客戶端連上來,他就在那傻傻的不動
			//,socket 叫做和client 端的一個連線,accept是接受的意思。這個方法的作用:
			//作為一個伺服器端來說,他可以接收很多很多客戶端的連線,如圖1中server 端新建的紅色socket 。
			System.out.println("accept ");
			InputStream is = s.getInputStream();  //我這個s(socket) 就是連著客戶端的socket,所以我這裡拿著的輸入管道就是客戶端的輸出管道
												  //這是一個連線,所以是一根管道
			DataInputStream dis = new DataInputStream(is);
			//s.getInetAddress(),s.getPort() ,也就是返回的客戶端IP,port,Returns the address to which the socket is connected. 
			System.out.println("A client connect , it says "+dis.readUTF());//readUTF()也是阻塞式的(這裡也可以放.readLine()即也是阻塞式的),如果對方不寫
			dis.close();				//東西過來,我也在這傻傻等著,一直對方寫東西過來為止。這個方法阻塞住,不能再接收其他的client 連線請求
			s.close();					//這些都是同步式的,所以不好,但是java 已經推出了非同步式的網路程式設計,意思是我accept() 之後就相當於
									//註冊一下,然後我就走了,我該幹什麼幹什麼,什麼時候就客戶端連上,系統通知我,我再連上,這就叫非同步式。這才是效率最高的。
							//非同步IO,VC裡面,這種網路程式設計的模型巨多無比,有最底層的,有用windows 自己提供的API 介面的,有用同步式的 /非同步式的,還有一種最有效率的
							//叫做iocompletionport,(io 完成介面,)不僅是非同步式的,而且還有一個執行緒池在不停等待,只要cpu 多,那麼處理的吞吐量就會特別大
							//就是同時有好多人連線也沒什麼關係,java 1.6達打不到這個層次,但是既然java已經提供非同步式,那麼他就能處理很多很多的連線了。現在很多程式
				//都是用java 編寫的TCP 的server,比如tomcat,jboss,也已經證明大量的連線可以執行在java 寫的server 上面。但是這不是將來我們工作的重點。
			    //
		}
		///////////////一旦我們連上了,c 和 s 就通過管道來說話,通過流來說話
		
	}
}




java 網路 socket TCP / client 端

import java.io.DataOutputStream;
import java.io.OutputStream;
import java.net.*;

public class TCPClient {
	public static void main(String args[]) throws Exception{
		System.out.println("client");
		//client 端這邊的插座叫什麼了?socket.服務端的叫serversocket
		Socket s = new Socket("127.0.0.1",6666);//127.0.0.1 叫本機IP,指定到你要連線到哪個埠上,server 那個埠,那邊有人在監聽6666
									//這邊就連到6666 。這時候,client 這邊的埠,系統隨機選擇,沒必要我繫結在哪個埠上,再和你6666建立連線。
									//反正只要咱們倆建立起來連線,你這個埠就永遠歸我所用。你server 再發別的東西,很顯然你發不到別的地方去,你就
									//只能發到我client 端的這個埠上。
		//////////////client 這端往外說,就是輸出流,
		OutputStream os = s.getOutputStream();//通過這個可以看出,如圖1,連線建立起來後,相當於有連線裡面有兩根管道,一根輸入
											  //一根輸出
		DataOutputStream dos = new DataOutputStream(os);
		Thread.sleep(3000000);
		dos.writeUTF("hello server");
		dos.flush();
		dos.close();
		s.close();    //socket 也是一個連線,說完話,也自己關掉,清理好。
	}
}


java 網路 socket UDP / server 端。嚴格意義上講,UDP 沒有server 和 client 的概念,因為他不區分客戶端的socket 和server 的socket

對於UDP來說,他的socket 也是插座,但是無線連線,不像TCP,需要連起來一個通道,才能發資料

udp server

package test.java.Net;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
/**
 * 
 * @author jalo
 * 如果接收的是long 型,有兩種方式,第一種是寫出端直接藉助ByteArrayOutputStream和DataOutputStream
 * 接收端直接用這個byte[]陣列去初始化ByteArrayInputStream,再包上一層DataInputStream,去readLong
 * 第二種是用本例中的byteArrayToLong(byte[])去轉化成long 型別
 *
 */
public class udpserver {
	public static long byteArrayToLong(byte[] buf) {  //long型別的前
		ByteBuffer buffer = ByteBuffer.allocate(8);
		buffer.put(buf, 0, 8);  
	    buffer.flip();//need flip   
	    return buffer.getLong();  
	}
	
	public static void main(String[] args) throws IOException {
		// udpserver
		InetSocketAddress isa = new InetSocketAddress("127.0.0.1", 40000);//注意這個是udp 的埠,udp 和tcp 不公用埠,他們都有40000埠
		DatagramSocket ds = new DatagramSocket(isa);
		byte []buf = new byte[1024]; // 1024長度的byte陣列這個是1KB
		DatagramPacket packet = new DatagramPacket(buf, 1024);
		while(true){
			ds.receive(packet);//也是阻塞式的方法。注意tcp是直接拿到流(因為有連線),在流上面包DataInputStream 即可實現各種型別的讀寫(readLong等)
							   //UDP不行,UDP只能拿資料包,然後分析裡面的內容,如果是long,還得去轉化(通過ByteArrayInputStream(byte[]))
			String info = new String(buf,0,packet.getLength());//此時這裡是亂碼,因為傳過來的是long 型別,你給解析成string型別了
			byte bufIn[] = new byte[1024];
			ByteArrayInputStream bais = new ByteArrayInputStream(buf);// 可以用buf 直接
			DataInputStream dis = new DataInputStream(bais);
			//long receiveLongVar = byteArrayToLong(buf);
			long receiveLongVar = dis.readLong();
			System.out.println("receive is "+receiveLongVar+""+"接收位元組的長度為:"+packet.getLength()
					+"client 的埠是"+ds.getPort());//1024是資料包的大小,接收長度不是1024,
		}
	}
}


udp client
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;

public class udpclient {

	public static void main(String[] args) throws IOException {
		InetSocketAddress isa = new InetSocketAddress("127.0.0.1", 40000);
		DatagramSocket ds = new DatagramSocket(); //這個可以給引數,傳埠號,表示我 udp client 端的埠
		//byte buf[] = "我是客戶端".getBytes();
		/////////以下是傳送long 型別的方法,轉化成記憶體中的byte 陣列,其他型別也這樣操作即可,即藉助ByteArrayOutputStream,DataOutputStream
		long l = 1132234599919232343L;			//ByteArrayOutputStream此類實現了一個輸出流,其中的資料被寫入一個 byte 陣列。無論你寫什麼,最後都轉化成位元組陣列存在記憶體裡,這樣省空間
		ByteArrayOutputStream baos = new ByteArrayOutputStream();// 這個是記憶體,是位元組陣列,但是具體大小不用管,直接往裡寫就寫
		DataOutputStream dos = new DataOutputStream(baos);  
		dos.writeLong(l);//此時這個long 型別數已經被寫到位元組數組裡
		byte buf1[] = baos.toByteArray();		//拿到記憶體中的byte 陣列,buf1.length是你有多少資料,length就多長
		/////////
		//System.out.println(String.valueOf(l).getBytes().length);//string 轉化成long型別,這是19位元組。如果按照long直接轉byte 陣列,則才8位元組(因為long本身是8位元組)
		ds.send(new DatagramPacket(buf1, buf1.length,isa)); // 第二個引數是接收長度,注意第三個引數是InetSocketAddress
					//為什麼TCP的時候,傳東西不需要ip + 埠,因為udp 無連線,你包給路由器,路由器總得知道,你這個包要到哪去。TCP有連線
					//
		
	}
}