java 網(wǎng)絡編程荚孵,Socket編程

Java的網(wǎng)絡編程主要涉及到的內容是Socket編程,那么什么是Socket呢纬朝?簡單地說收叶,Socket,套接字共苛,就是兩臺主機之間邏輯連接的端點判没。TPC/IP協(xié)議是傳輸層協(xié)議蜓萄,主要解決數(shù)據(jù)如何在網(wǎng)絡中傳輸,而HTTP是應用層協(xié)議澄峰,主要解決如何包裝數(shù)據(jù)嫉沽。Socket,本質上就是一組接口俏竞,是對TCP/IP協(xié)議的封裝和應用(程序員層面上)绸硕。

套接字使用TCP提供了兩臺計算機之間的通信機制。 客戶端程序創(chuàng)建一個套接字胞此,并嘗試連接服務器的套接字臣咖。

當連接建立時跃捣,服務器會創(chuàng)建一個 Socket 對象漱牵。客戶端和服務器現(xiàn)在可以通過對 Socket 對象的寫入和讀取來進行通信疚漆。

java.net.Socket 類代表一個套接字酣胀,并且 java.net.ServerSocket 類為服務器程序提供了一種來監(jiān)聽客戶端,并與他們建立連接的機制娶聘。

以下步驟在兩臺計算機之間使用套接字建立TCP連接時會出現(xiàn):

服務器實例化一個 ServerSocket 對象闻镶,表示通過服務器上的端口通信。

服務器調用 ServerSocket 類的 accept() 方法丸升,該方法將一直等待铆农,直到客戶端連接到服務器上給定的端口。

服務器正在等待時狡耻,一個客戶端實例化一個 Socket 對象墩剖,指定服務器名稱和端口號來請求連接。

Socket 類的構造函數(shù)試圖將客戶端連接到指定的服務器和端口號夷狰。如果通信被建立岭皂,則在客戶端創(chuàng)建一個 Socket 對象能夠與服務器進行通信。

在服務器端沼头,accept() 方法返回服務器上一個新的 socket 引用爷绘,該 socket 連接到客戶端的 socket。

連接建立后进倍,通過使用 I/O 流在進行通信土至,每一個socket都有一個輸出流和一個輸入流,客戶端的輸出流連接到服務器端的輸入流猾昆,而客戶端的輸入流連接到服務器端的輸出流陶因。

TCP 是一個雙向的通信協(xié)議,因此數(shù)據(jù)可以通過兩個數(shù)據(jù)流在同一時間發(fā)送.以下是一些類提供的一套完整的有用的方法來實現(xiàn) socket毡庆。

整體流程

Socket編程主要涉及到客戶端和服務器端兩個方面坑赡,首先是在服務器端創(chuàng)建一個服務器套接字(ServerSocket)烙如,并把它附加到一個端口上,服務器從這個端口監(jiān)聽連接毅否。端口號的范圍是0到65536亚铁,但是0到1024是為特權服務保留的端口號,我們可以選擇任意一個當前沒有被其他進程使用的端口螟加。

客戶端請求與服務器進行連接的時候徘溢,根據(jù)服務器的域名或者IP地址,加上端口號捆探,打開一個套接字然爆。當服務器接受連接后,服務器和客戶端之間的通信就像輸入輸出流一樣進行操作黍图。

實例

下面是一個客戶端和服務器端進行數(shù)據(jù)交互的簡單例子曾雕,客戶端輸入正方形的邊長,服務器端接收到后計算面積并返回給客戶端助被,通過這個例子可以初步對Socket編程有個把握剖张。

服務器端

public class SocketServer {


??? public static void main(String[] args) throws IOException {

??????? // 端口號

??????? int port = 7000;

??????? // 在端口上創(chuàng)建一個服務器套接字

??????? ServerSocket serverSocket = new ServerSocket(port);

??????? // 監(jiān)聽來自客戶端的連接

??????? Socket socket = serverSocket.accept();

??????? DataInputStream dis = new DataInputStream(

??????????????? new BufferedInputStream(socket.getInputStream()));


??????? DataOutputStream dos = new DataOutputStream(

??????????????? new BufferedOutputStream(socket.getOutputStream()));

??????? do {

??????????? double length = dis.readDouble();

??????????? System.out.println("服務器端收到的邊長數(shù)據(jù)為:" + length);

??????????? double result = length * length;

??????????? dos.writeDouble(result);

??????????? dos.flush();

??????? } while (dis.readInt() != 0);

??????? socket.close();

??????? serverSocket.close();

??? }

}

客戶端

public class SocketClient {

??? public static void main(String[] args) throws UnknownHostException, IOException {

? ? ? ?int port = 7000;

??????? String host = "localhost";

??????? // 創(chuàng)建一個套接字并將其連接到指定端口號

??????? Socket socket = new Socket(host, port);

??????? DataInputStream dis = new DataInputStream(

??????????????? new BufferedInputStream(socket.getInputStream()));

??????? DataOutputStream dos = new DataOutputStream(

??????????????? new BufferedOutputStream(socket.getOutputStream()));

??????? Scanner sc = new Scanner(System.in);

??????? boolean flag = false;

??????? while (!flag) {

??????????? System.out.println("請輸入正方形的邊長:");

??????????? double length = sc.nextDouble();

??????????? dos.writeDouble(length);

??????????? dos.flush();

??????????? double area = dis.readDouble();

??????????? System.out.println("服務器返回的計算面積為:" + area);

??????????? while (true) {

??????????????? System.out.println("繼續(xù)計算?(Y/N)");

??????????????? String str = sc.next();

??????????????? if (str.equalsIgnoreCase("N")) {

??????????????????? dos.writeInt(0);

??????????????????? dos.flush();

??????????????????? flag = true;

??????????????????? break;

??????????????? } else if (str.equalsIgnoreCase("Y")) {

??????????????????? dos.writeInt(1);

??????????????????? dos.flush();

??????????????????? break;

??????????????? }

??????????? }

??????? }


??????? socket.close();

??? }

}

實例二

可以看到上面的服務器端程序和客戶端程序是一對一的關系揩环,為了能讓一個服務器端程序能同時為多個客戶提供服務搔弄,可以使用多線程機制,每個客戶端的請求都由一個獨立的線程進行處理丰滑。下面是改寫后的服務器端程序顾犹。

public class SocketServerM {


??? public static void main(String[] args) throws IOException {


??????? int port = 7000;

??????? int clientNo = 1;


??????? ServerSocket serverSocket = new ServerSocket(port);


??????? // 創(chuàng)建線程池

??????? ExecutorService exec = Executors.newCachedThreadPool();


??????? try {


??????????? while (true) {

??????????????? Socket socket = serverSocket.accept();

??????????????? exec.execute(new SingleServer(socket, clientNo));

??????????????? clientNo++;

??????????? }


??????? } finally {

??????????? serverSocket.close();

??????? }


??? }

}


class SingleServer implements Runnable {


??? private Socket socket;

??? private int clientNo;


??? public SingleServer(Socket socket, int clientNo) {

??????? this.socket = socket;

??????? this.clientNo = clientNo;

??? }


??? @Override

??? public void run() {


??????? try {


??????????? DataInputStream dis = new DataInputStream(

??????????????????? new BufferedInputStream(socket.getInputStream()));


??????????? DataOutputStream dos = new DataOutputStream(

??????????????????? new BufferedOutputStream(socket.getOutputStream()));


??????????? do {


??????????????? double length = dis.readDouble();

??????????????? System.out.println("從客戶端" + clientNo + "接收到的邊長數(shù)據(jù)為:" + length);

??????????????? double result = length * length;

??????????????? dos.writeDouble(result);

??????????????? dos.flush();


??????????? } while (dis.readInt() != 0);


??????? } catch (IOException e) {

??????????? e.printStackTrace();

??????? } finally {

??????????? System.out.println("與客戶端" + clientNo + "通信結束");

??????????? try {

??????????????? socket.close();

??????????? } catch (IOException e) {

??????????????? e.printStackTrace();

??????????? }

??????? }

??? }

}

上面改進后的服務器端代碼可以支持不斷地并發(fā)響應網(wǎng)絡中的客戶請求。關鍵的地方在于多線程機制的運用褒墨,同時利用線程池可以改善服務器程序的性能炫刷。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市貌亭,隨后出現(xiàn)的幾起案子柬唯,更是在濱河造成了極大的恐慌,老刑警劉巖圃庭,帶你破解...
    沈念sama閱讀 211,817評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件锄奢,死亡現(xiàn)場離奇詭異,居然都是意外死亡剧腻,警方通過查閱死者的電腦和手機拘央,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來书在,“玉大人灰伟,你說我怎么就攤上這事。” “怎么了栏账?”我有些...
    開封第一講書人閱讀 157,354評論 0 348
  • 文/不壞的土叔 我叫張陵帖族,是天一觀的道長。 經(jīng)常有香客問我挡爵,道長竖般,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,498評論 1 284
  • 正文 為了忘掉前任茶鹃,我火速辦了婚禮涣雕,結果婚禮上,老公的妹妹穿的比我還像新娘闭翩。我一直安慰自己挣郭,他們只是感情好,可當我...
    茶點故事閱讀 65,600評論 6 386
  • 文/花漫 我一把揭開白布疗韵。 她就那樣靜靜地躺著兑障,像睡著了一般。 火紅的嫁衣襯著肌膚如雪伶棒。 梳的紋絲不亂的頭發(fā)上旺垒,一...
    開封第一講書人閱讀 49,829評論 1 290
  • 那天彩库,我揣著相機與錄音肤无,去河邊找鬼。 笑死骇钦,一個胖子當著我的面吹牛宛渐,可吹牛的內容都是我干的。 我是一名探鬼主播眯搭,決...
    沈念sama閱讀 38,979評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼窥翩,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了鳞仙?” 一聲冷哼從身側響起寇蚊,我...
    開封第一講書人閱讀 37,722評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎棍好,沒想到半個月后仗岸,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,189評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡借笙,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,519評論 2 327
  • 正文 我和宋清朗相戀三年扒怖,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片业稼。...
    茶點故事閱讀 38,654評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡盗痒,死狀恐怖,靈堂內的尸體忽然破棺而出低散,到底是詐尸還是另有隱情俯邓,我是刑警寧澤骡楼,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站稽鞭,受9級特大地震影響君编,放射性物質發(fā)生泄漏。R本人自食惡果不足惜川慌,卻給世界環(huán)境...
    茶點故事閱讀 39,940評論 3 313
  • 文/蒙蒙 一吃嘿、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧梦重,春花似錦兑燥、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蚓胸,卻和暖如春挣饥,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背沛膳。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評論 1 266
  • 我被黑心中介騙來泰國打工扔枫, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人锹安。 一個月前我還...
    沈念sama閱讀 46,382評論 2 360
  • 正文 我出身青樓短荐,卻偏偏與公主長得像,于是被迫代替她去往敵國和親叹哭。 傳聞我的和親對象是個殘疾皇子忍宋,可洞房花燭夜當晚...
    茶點故事閱讀 43,543評論 2 349

推薦閱讀更多精彩內容