Java網絡編程之Socket的使用

使用Java進行網絡編程,通常會用到TCP,UDP協議。TCP是面向連接的,是可靠的傳輸層協議;UDP是無連接的,但是效率更高。下面是一個簡單的使用Socket寫的一個小例子用來實現TCP協議通信。

Server.java

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * @description:服務器端
 * @date:(2015-9-13 下午8:41:06)
 * @author Administrator
 * @version v1.0
 * @since v1.0
 *
 * Modified history
 *
 *    Modified date:  
 *    Modifier user:     
 *    description: 
 *
 * */
public class Server {
	
	public static void main(String[] args) throws IOException, InterruptedException {
		
		//監聽端口
		int port=8090;
		//服務器端監聽8090端口
		ServerSocket serverSocket=new ServerSocket(port);
		//服務器端監聽客戶端的連接請求,accept方法是阻塞式的
		Socket socket=serverSocket.accept();
		/**
		 * 服務端從Socket的InputStream中讀
		 * 取數據的操作也是阻塞式的,如果從輸入
		 * 流中沒有讀取到數據程序會一直在那
		 * 裏不動,直到客戶端往Socket的輸出流中寫入了數據,或關閉了Socket的輸出流。
		 * 客戶端的Socket也是同樣如此
		 * */
		BufferedReader reader=new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-8"));
		StringBuffer sb=new StringBuffer();
		String temp=null;
		int index;
		while((temp=reader.readLine())!=null){
			//不設置結束符,可能輸入流會
            if ((index = temp.indexOf("eof")) != -1) {//遇到eof時就結束接收  
            	sb.append(temp.substring(0, index));  
                break;  
            }
            sb.append(temp);
		}
		System.out.println("receive from client:"+sb.toString());
		//輸出信息到客戶端
		BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(),"UTF-8"));
		//讀取控制檯輸入
		BufferedReader bufReader=new BufferedReader(new InputStreamReader(System.in));
		System.out.println("server say:");
		writer.write(bufReader.readLine());
		writer.write("hello client");
		/**
		 * BufferedReader的readLine方法是一次讀一行的,
		 * 這個方法是阻塞的,直到它讀到了一行數據爲止程序纔會繼續往下執行,
		 * 那麼readLine什麼時候纔會讀到一行呢?直到程序遇到了換行符或者是對應流的
		 * 結束符readLine方法纔會認爲讀到了一行,纔會結束其阻塞,讓程序繼續往下執行。
		 * 所以我們在使用BufferedReader的readLine讀取數據的時候一定要記得在對應的輸出流裏面一定要寫入換行符
		 * */
		writer.write("eof\n");//設置結束符
		writer.flush();
		writer.close();
		bufReader.close();
		reader.close();
		socket.close();
		serverSocket.close();
		
	}

}

Client.java

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;

/**
 * @description:客戶端
 * @date:(2015-9-13 下午8:48:49)
 * @author Administrator
 * @version v1.0
 * @since v1.0
 *
 * Modified history
 *
 *    Modified date:  
 *    Modifier user:     
 *    description: 
 *
 * */
public class Client {
	
	public static void main(String[] args) throws IOException {
		//要連接的服務器IP地址
		String host="127.0.0.1";
		//要連接的服務器監聽端口
		int port=8090;
		//與服務器端簡歷連接
		Socket client=new Socket(host,port);
		//設置超時間爲20秒 ,
	    client.setSoTimeout(20*1000);  
		//往服務端寫數據
		BufferedWriter writer=new BufferedWriter(new OutputStreamWriter(client.getOutputStream(),"UTF-8"));
		//讀取控制檯
		BufferedReader bufReader=new BufferedReader(new InputStreamReader(System.in));
		System.out.println("client say:");
		writer.write(bufReader.readLine());
		writer.write("hello server");
		writer.write("eof\n");//設置結束符
		writer.flush();
		
		//接收服務端響應,socket從輸入流中讀取數據是一個阻塞式操作,讀取不到數據會一直阻塞
		BufferedReader reader=new BufferedReader(new InputStreamReader(client.getInputStream(),"UTF-8"));
		StringBuffer sb=new StringBuffer();
		String tmp=null;
		int index;
		while((tmp=reader.readLine())!=null){
            if ((index = tmp.indexOf("eof")) != -1) {//遇到eof時就結束接收 
            	sb.append(tmp.substring(0, index));  
                break;  
            } 
            sb.append(tmp);
		}
		System.out.println("receive from server:"+sb.toString());
		
		reader.close();
		writer.close();
		//Test
		bufReader.close();
		//Test
		client.close();
	}

}
說明:

1、服務器的ServerSocket的accept方法是用來監聽端口,當監聽到客戶端的socket連接請求是就會創建一個Socket;accept方法是阻塞式的,如果一直沒有監聽到客戶端Socket連接請求,它會一直阻塞下去。

2、Socket的getInputStream()方法也是阻塞式的,客戶端的Socket向服務端寫入數據後,假如調用getInputStream()方法想要獲取服務器端的輸出,它會一直阻塞,知道服務器端寫入數據或者流關閉。

3、寫入”eof“,用來作爲結束符,防止流一直阻塞。另外,BufferedReader的readerLine方法也是阻塞式的,知道讀取到一行位置,所以寫入的時候記得寫入換行符。

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