Java 網絡編程

1.1、TCP,同步版本的Server:

package com.socket;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * TCP的網絡編程,服務器
 * @author Feng
 *
 */
public class TCPTestServer{
	public static void main(String[] args) throws IOException, InterruptedException{
		//服務器開始監聽6666號端口
		//從啓動上說,必須要先啓動服務器端程序
		ServerSocket ss = new ServerSocket(6666);
		//因爲服務器需要不斷等待連接,所以死循環等待
		while(true){
			System.out.println("等待連接申請中···");
			//接受鏈接申請,這樣寫只接受一個連接,這個方法是阻塞式的,如果沒有任何連接申請就會一直等待
			Socket s = ss.accept();
			if(s.isConnected()){
				System.out.println("OK!!!!!");
				//使用輸入流接受客戶端傳入的信息
				InputStream stream = s.getInputStream();
				BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
				//注意,像這種輸入流的方式屬於同步輸入,連接成功後如果客戶端不傳送東西,這裏的輸入流會一直等待,導致其他連接申請被擱置
				System.out.println(reader.readLine());
			}else{
				System.out.println("NO!!");
			}
		}
	}
}

1.2、TCP,同步版本的Client:

package com.socket;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;

/**
 * TCP網絡編程,客戶端
 * @author Feng
 *
 */
public class TCPTestClient {
	public static void main(String[] args) throws UnknownHostException, IOException, InterruptedException{
		//客戶端申請連接到 127.0.0.1:6666
		//客戶端會給這邊的socket隨機分配端口號,具體是多少並不重要
		Socket s = new Socket("127.0.0.1", 6666);
		//連接成功之後,可以通過管道來進行通話,使用輸出管道
		//這裏的等待模擬:線連接,但是遲遲不發送信息,這個時候這個鏈接會被該客戶端獨佔
		Thread.sleep(10000);
		OutputStream stream = s.getOutputStream();
		BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stream));
		writer.write("SHTI!!!!你妹!!!!!");
		writer.flush();
		writer.close();
		s.close();
	}
}


2、TCP,多線程的圖片接收服務器

package com.socket;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class TCPJpgGetter {
	public static void main(String[] args) throws IOException{
		ServerSocket ss = new ServerSocket(6666);
		
		while(true){
			Socket s = ss.accept();
			new Thread(new Getter(s)).start();
		}
	}
}

/**
 * 多線程的圖片接收類
 * 服務器端開啓多個線程用於接收傳送過來的圖片
 */
class Getter implements Runnable{
	private Socket s = null;
	
	public Getter(Socket s){
		this.s = s;
	}
	@Override
	public void run() {
		try {
			String info = s.getInetAddress().toString();
			
			//從socket讀取數據的輸入流
			InputStream getter = s.getInputStream();

			//回傳數據的輸出流
			OutputStream sender = s.getOutputStream();
			
			//爲了避免文件名重複的覆蓋,使用編號
			int count = 1;
			File temp = new File("D:/" + info + "(" + count + ").jpg");
			while(temp.exists()){
				//這裏的處理不是很嚴謹,還是有可能會導致文件覆蓋
				temp = new File("D:/" + info + "(" + (++count) + ").jpg");
			}
			
			System.out.println("接收到來自:" + info + "的傳送請求,存儲名爲:" + temp.getName());
			//創建文件並寫入到磁盤的輸出流
			FileOutputStream fileWriter = new FileOutputStream(temp);
			
			byte[] buf = new byte[1024];
			int len;
			
			while((len=getter.read(buf)) != -1){
				//寫文件的時候要注意寫的長度
				fileWriter.write(buf, 0, len);
			}
			
			sender.write("上傳成功".getBytes("UTF-8"));
			
			fileWriter.close();
			s.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}



3.1、UDP,同步版本的“Server”:

package com.socket;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

/**
 * UDP的“服務器”,事實上UDP並沒有明確地服務器和客戶端的分類,因爲是不安全連接,要做的就是確定目標IP和端口號,然後直接發送就好了
 * @author Feng
 *
 */
public class UDPTestServer {
	public static void main(String[] args) throws IOException{
		byte buf[] = new byte[1024];
		//DatagramPacket用來存放需要發送或者要接收的數據
		DatagramPacket dp = new DatagramPacket(buf, buf.length);
		//DatagramSocket就是UDP方式的socket,爲服務器指定端口號6666
		DatagramSocket ds = new DatagramSocket(6666);
		while(true){
			//receive方法是阻塞式方法,等待接收數據
			ds.receive(dp);
			//獲取發送源的IP地址和端口號,在發送端由於沒有指定端口號,這裏看到的端口是系統隨機分配的端口
			System.out.println("收取到來自 " + dp.getAddress() + ":" + dp.getPort() + " 的信息:");
			//以字符串的形式獲取數據並打印
			System.out.println("字符串:" + new String(buf, 0, dp.getLength()));
			
			//接受傳送過來的信息,信息已經存儲在buf之中
			ByteArrayInputStream in = new ByteArrayInputStream(buf);
			DataInputStream din = new DataInputStream(in);
			System.out.println("數字:" + din.readLong());
			
			System.out.println();
 		}
	}
}


3.2、UDP,同步版本的“Client”:

package com.socket;

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

public class UDPTestClient {
	public static void main(String[] args) throws IOException{
		byte[] buf = new String("你好!~~").getBytes();
		
		//將一個long類型數據轉換成byte[];
		long num = 123412341234L;
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		DataOutputStream dout = new DataOutputStream(out);
		dout.writeLong(num);
		byte[] buf2 = out.toByteArray();
		System.out.println(buf2.length);
		
		//新建socket的時候如果不指定端口號,那系統將爲其默認指定一個地址,作爲發送方,這個socket不需要指定端口
		DatagramSocket ds = new DatagramSocket();
		DatagramPacket dp = null;
		
		//DatagramPacket是UDP模式下傳輸信息的媒介
		//指定目的地址爲127.0.0.1:6666
		dp = new DatagramPacket(buf, buf.length, 
				new InetSocketAddress("127.0.0.1", 6666));
		ds.send(dp);
		
		dp = new DatagramPacket(buf2, buf2.length, 
				new InetSocketAddress("127.0.0.1", 6666));
		ds.send(dp);
		
		ds.close();
	}
}


4、UDP聊天小程序

package com.socket;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.net.UnknownHostException;

/**
 * 兩個線程,定義一個接受和一個發送端
 * 寫入目標機器的IP地址和端口號即可通信
 * 中文問題:我的MyEclipse默認編碼是UTF-8,運行的時候要在Run-Run Configuration-Common-指定GBK,否則會出現中文亂碼問題
 * @author Feng
 */
public class UDPTalker {
	
	public static void main(String[] args) throws IOException{
		InetAddress myAdd = InetAddress.getLocalHost();
		System.out.println("本機地址:" + myAdd);
		
		BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
		System.out.println("請輸入目標機器IP地址:");
		String ipAdd = reader.readLine();
		
		System.out.println("請輸入目標機器端口號:");
		int port = Integer.parseInt(reader.readLine());
		
		DatagramSocket sender = new DatagramSocket();
		DatagramSocket listener = new DatagramSocket(6666);
		
		//消息發送目的地
		InetSocketAddress address = new InetSocketAddress(ipAdd, port);
		
		new Thread(new Send(sender, address)).start();
		new Thread(new Listen(listener)).start();
	}
}

/**
 * 發送線程,接受鍵盤輸入,並將消息發往指定的地址
 * @author Feng
 *
 */
class Send implements Runnable{
	private DatagramSocket ds = null;
	private InetSocketAddress address = null;
	
	public Send(DatagramSocket ds, InetSocketAddress address){
		this.ds = ds;
		this.address = address;
	}
	
	@Override
	public void run() {
		BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
		String line = null;
		
		try {
			while((line=reader.readLine()) != null){
				byte[] temp = line.getBytes("UTF-8");
				//發送數據包,指定了發送的內容以及目的地
				DatagramPacket dp = new DatagramPacket(temp, temp.length, address);
				ds.send(dp);
				
				if("exit".equals(line)){
					break;
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

/**
 * 接收線程,等待接收消息並顯示
 * @author Feng
 *
 */
class Listen implements Runnable{
	private DatagramSocket ds = null;
	
	public Listen(DatagramSocket ds){
		this.ds = ds;
	}
	
	@Override
	public void run() {
		
		try {
			while(true){
				byte[] temp = new byte[1024];
				//接收數據包,緩存大小爲1K
				DatagramPacket dp = new DatagramPacket(temp, temp.length);
				ds.receive(dp);
				
				String address = dp.getAddress().getHostAddress() + "-" + dp.getPort();
				String data = new String(dp.getData(), 0, dp.getLength(), "UTF-8");
				
				System.out.println(address + ": " + data);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章