日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > java >内容正文

java

循序渐进Java Socket网络编程(多客户端、信息共享、文件传输)

發(fā)布時(shí)間:2025/3/21 java 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 循序渐进Java Socket网络编程(多客户端、信息共享、文件传输) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

目錄[-]

  • 一、TCP/IP協(xié)議
  • 二、TCP與UDP
  • 三、Socket是什么
  • 四、Java中的Socket
  • 五、基本的Client/Server程序
  • 六、多客戶端連接服務(wù)器
  • 七、信息共享
  • 八、文件傳輸
  • 推薦閱讀:

前言:在最近一個(gè)即將結(jié)束的項(xiàng)目中使用到了Socket編程,用于調(diào)用另一系統(tǒng)進(jìn)行處理并返回?cái)?shù)據(jù)。故把Socket的基礎(chǔ)知識(shí)總結(jié)梳理一遍。

一、TCP/IP協(xié)議

  既然是網(wǎng)絡(luò)編程,涉及幾個(gè)系統(tǒng)之間的交互,那么首先要考慮的是如何準(zhǔn)確的定位到網(wǎng)絡(luò)上的一臺(tái)或幾臺(tái)主機(jī),另一個(gè)是如何進(jìn)行可靠高效的數(shù)據(jù)傳輸。這里就要使用到TCP/IP協(xié)議。

  TCP/IP協(xié)議(傳輸控制協(xié)議)由網(wǎng)絡(luò)層的IP協(xié)議和傳輸層的TCP協(xié)議組成。IP層負(fù)責(zé)網(wǎng)絡(luò)主機(jī)的定位,數(shù)據(jù)傳輸?shù)穆酚?#xff0c;由IP地址可以唯一的確定Internet上的一臺(tái)主機(jī)。TCP層負(fù)責(zé)面向應(yīng)用的可靠的或非可靠的數(shù)據(jù)傳輸機(jī)制,這是網(wǎng)絡(luò)編程的主要對(duì)象。

二、TCP與UDP

  TCP是一種面向連接的保證可靠傳輸?shù)膮f(xié)議。通過TCP協(xié)議傳輸,得到的是一個(gè)順序的無(wú)差錯(cuò)的數(shù)據(jù)流。發(fā)送方和接收方的成對(duì)的兩個(gè)socket之間必須建立連接,以便在TCP協(xié)議的基礎(chǔ)上進(jìn)行通信,當(dāng)一個(gè)socket(通常都是server socket)等待建立連接時(shí),另一個(gè)socket可以要求進(jìn)行連接,一旦這兩個(gè)socket連接起來(lái),它們就可以進(jìn)行雙向數(shù)據(jù)傳輸,雙方都可以進(jìn)行發(fā)送或接收操作。

  UDP是一種面向無(wú)連接的協(xié)議,每個(gè)數(shù)據(jù)報(bào)都是一個(gè)獨(dú)立的信息,包括完整的源地址或目的地址,它在網(wǎng)絡(luò)上以任何可能的路徑傳往目的地,因此能否到達(dá)目的地,到達(dá)目的地的時(shí)間以及內(nèi)容的正確性都是不能被保證的。

TCP與UDP區(qū)別:

TCP特點(diǎn):

  1、TCP是面向連接的協(xié)議,通過三次握手建立連接,通訊完成時(shí)要拆除連接,由于TCP是面向連接協(xié)議,所以只能用于點(diǎn)對(duì)點(diǎn)的通訊。而且建立連接也需要消耗時(shí)間和開銷。

  2、TCP傳輸數(shù)據(jù)無(wú)大小限制,進(jìn)行大數(shù)據(jù)傳輸。

  3、TCP是一個(gè)可靠的協(xié)議,它能保證接收方能夠完整正確地接收到發(fā)送方發(fā)送的全部數(shù)據(jù)。

UDP特點(diǎn):

  1、UDP是面向無(wú)連接的通訊協(xié)議,UDP數(shù)據(jù)包括目的端口號(hào)和源端口號(hào)信息,由于通訊不需要連接,所以可以實(shí)現(xiàn)廣播發(fā)送。

  2、UDP傳輸數(shù)據(jù)時(shí)有大小限制,每個(gè)被傳輸?shù)臄?shù)據(jù)報(bào)必須限定在64KB之內(nèi)。

  3、UDP是一個(gè)不可靠的協(xié)議,發(fā)送方所發(fā)送的數(shù)據(jù)報(bào)并不一定以相同的次序到達(dá)接收方。

TCP與UDP應(yīng)用:

  1、TCP在網(wǎng)絡(luò)通信上有極強(qiáng)的生命力,例如遠(yuǎn)程連接(Telnet)和文件傳輸(FTP)都需要不定長(zhǎng)度的數(shù)據(jù)被可靠地傳輸。但是可靠的傳輸是要付出代價(jià)的,對(duì)數(shù)據(jù)內(nèi)容正確性的檢驗(yàn)必然占用計(jì)算機(jī)的處理時(shí)間和網(wǎng)絡(luò)的帶寬,因此TCP傳輸?shù)男什蝗鏤DP高。

  2,UDP操作簡(jiǎn)單,而且僅需要較少的監(jiān)護(hù),因此通常用于局域網(wǎng)高可靠性的分散系統(tǒng)中client/server應(yīng)用程序。例如視頻會(huì)議系統(tǒng),并不要求音頻視頻數(shù)據(jù)絕對(duì)的正確,只要保證連貫性就可以了,這種情況下顯然使用UDP會(huì)更合理一些。

三、Socket是什么

  Socket通常也稱作"套接字",用于描述IP地址和端口,是一個(gè)通信鏈的句柄。網(wǎng)絡(luò)上的兩個(gè)程序通過一個(gè)雙向的通訊連接實(shí)現(xiàn)數(shù)據(jù)的交換,這個(gè)雙向鏈路的一端稱為一個(gè)Socket,一個(gè)Socket由一個(gè)IP地址和一個(gè)端口號(hào)唯一確定。應(yīng)用程序通常通過"套接字"向網(wǎng)絡(luò)發(fā)出請(qǐng)求或者應(yīng)答網(wǎng)絡(luò)請(qǐng)求。?Socket是TCP/IP協(xié)議的一個(gè)十分流行的編程界面,但是,Socket所支持的協(xié)議種類也不光TCP/IP一種,因此兩者之間是沒有必然聯(lián)系的。在Java環(huán)境下,Socket編程主要是指基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程。

  Socket通訊過程:服務(wù)端監(jiān)聽某個(gè)端口是否有連接請(qǐng)求,客戶端向服務(wù)端發(fā)送連接請(qǐng)求,服務(wù)端收到連接請(qǐng)求向客戶端發(fā)出接收消息,這樣一個(gè)連接就建立起來(lái)了。客戶端和服務(wù)端都可以相互發(fā)送消息與對(duì)方進(jìn)行通訊。

  Socket的基本工作過程包含以下四個(gè)步驟:

  1、創(chuàng)建Socket;

  2、打開連接到Socket的輸入輸出流;

  3、按照一定的協(xié)議對(duì)Socket進(jìn)行讀寫操作;

  4、關(guān)閉Socket。

四、Java中的Socket

  在java.net包下有兩個(gè)類:Socket和ServerSocket。ServerSocket用于服務(wù)器端,Socket是建立網(wǎng)絡(luò)連接時(shí)使用的。在連接成功時(shí),應(yīng)用程序兩端都會(huì)產(chǎn)生一個(gè)Socket實(shí)例,操作這個(gè)實(shí)例,完成所需的會(huì)話。對(duì)于一個(gè)網(wǎng)絡(luò)連接來(lái)說,套接字是平等的,并沒有差別,不因?yàn)樵诜?wù)器端或在客戶端而產(chǎn)生不同級(jí)別。不管是Socket還是ServerSocket它們的工作都是通過SocketImpl類及其子類完成的。

列出幾個(gè)常用的構(gòu)造方法:

?
1 2 3 4 5 6 7 8 9 Socket(InetAddress address,int?port);//創(chuàng)建一個(gè)流套接字并將其連接到指定 IP 地址的指定端口號(hào) Socket(String host,int?port);//創(chuàng)建一個(gè)流套接字并將其連接到指定主機(jī)上的指定端口號(hào) Socket(InetAddress address,int?port, InetAddress localAddr,int?localPort);//創(chuàng)建一個(gè)套接字并將其連接到指定遠(yuǎn)程地址上的指定遠(yuǎn)程端口 Socket(String host,int?port, InetAddress localAddr,int?localPort);//創(chuàng)建一個(gè)套接字并將其連接到指定遠(yuǎn)程主機(jī)上的指定遠(yuǎn)程端口 Socket(SocketImpl impl);//使用用戶指定的 SocketImpl 創(chuàng)建一個(gè)未連接 Socket ServerSocket(int?port);//創(chuàng)建綁定到特定端口的服務(wù)器套接字 ServerSocket(int?port,int?backlog);//利用指定的 backlog 創(chuàng)建服務(wù)器套接字并將其綁定到指定的本地端口號(hào) ServerSocket(int?port,int?backlog, InetAddress bindAddr);//使用指定的端口、偵聽 backlog 和要綁定到的本地 IP地址創(chuàng)建服務(wù)器

  構(gòu)造方法的參數(shù)中,address、host和port分別是雙向連接中另一方的IP地址、主機(jī)名和端?口號(hào),stream指明socket是流socket還是數(shù)據(jù)報(bào)socket,localPort表示本地主機(jī)的端口號(hào),localAddr和bindAddr是本地機(jī)器的地址(ServerSocket的主機(jī)地址),impl是socket的父類,既可以用來(lái)創(chuàng)建serverSocket又可以用來(lái)創(chuàng)建Socket。count則表示服務(wù)端所能支持的最大連接數(shù)。

注意:必須小心選擇端口號(hào)。每一個(gè)端口提供一種特定的服務(wù),只有給出正確的端口,才?能獲得相應(yīng)的服務(wù)。0~1023的端口號(hào)為系統(tǒng)所保留,例如http服務(wù)的端口號(hào)為80,telnet服務(wù)的端口號(hào)為21,ftp服務(wù)的端口號(hào)為23,?所以我們?cè)谶x擇端口號(hào)時(shí),最好選擇一個(gè)大于1023的數(shù)以防止發(fā)生沖突。

幾個(gè)重要的Socke方法:

?
1 2 3 public?InputStream getInputStream();//方法獲得網(wǎng)絡(luò)連接輸入,同時(shí)返回一個(gè)IutputStream對(duì)象實(shí)例 public?OutputStream getOutputStream();//方法連接的另一端將得到輸入,同時(shí)返回一個(gè)OutputStream對(duì)象實(shí)例 public?Socket accept();//用于產(chǎn)生"阻塞",直到接受到一個(gè)連接,并且返回一個(gè)客戶端的Socket對(duì)象實(shí)例。

"阻塞"是一個(gè)術(shù)語(yǔ),它使程序運(yùn)行暫時(shí)"停留"在這個(gè)地方,直到一個(gè)會(huì)話產(chǎn)生,然后程序繼續(xù);通常"阻塞"是由循環(huán)產(chǎn)生的。

注意:其中g(shù)etInputStream和getOutputStream方法均會(huì)產(chǎn)生一個(gè)IOException,它必須被捕獲,因?yàn)樗鼈兎祷氐牧鲗?duì)象,通常都會(huì)被另一個(gè)流對(duì)象使用。

五、基本的Client/Server程序

以下是一個(gè)基本的客戶端/服務(wù)器端程序代碼。主要實(shí)現(xiàn)了服務(wù)器端一直監(jiān)聽某個(gè)端口,等待客戶端連接請(qǐng)求。客戶端根據(jù)IP地址和端口號(hào)連接服務(wù)器端,從鍵盤上輸入一行信息,發(fā)送到服務(wù)器端,然后接收服務(wù)器端返回的信息,最后結(jié)束會(huì)話。這個(gè)程序一次只能接受一個(gè)客戶連接。

ps:這個(gè)小例子寫好后,服務(wù)端一直接收不到消息,調(diào)試了好長(zhǎng)時(shí)間,才發(fā)現(xiàn)誤使用了PrintWriter的print()方法,而BufferedReader的readLine()方法一直沒有遇到換行,所以一直等待讀取。我暈死~~@_@

客戶端程序:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 package sock; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; ?? public class SocketClient { ????public static void main(String[] args) { ????????try { ????????????/** 創(chuàng)建Socket*/ ????????????// 創(chuàng)建一個(gè)流套接字并將其連接到指定 IP 地址的指定端口號(hào)(本處是本機(jī)) ????????????Socket socket =new Socket("127.0.0.1",2013); ????????????// 60s超時(shí) ????????????socket.setSoTimeout(60000); ?? ????????????/** 發(fā)送客戶端準(zhǔn)備傳輸?shù)男畔?*/ ????????????// 由Socket對(duì)象得到輸出流,并構(gòu)造PrintWriter對(duì)象 ????????????PrintWriter printWriter =new PrintWriter(socket.getOutputStream(),true); ????????????// 將輸入讀入的字符串輸出到Server ????????????BufferedReader sysBuff =new BufferedReader(new InputStreamReader(System.in)); ????????????printWriter.println(sysBuff.readLine()); ????????????// 刷新輸出流,使Server馬上收到該字符串 ????????????printWriter.flush(); ?? ????????????/** 用于獲取服務(wù)端傳輸來(lái)的信息 */ ????????????// 由Socket對(duì)象得到輸入流,并構(gòu)造相應(yīng)的BufferedReader對(duì)象 ????????????BufferedReader bufferedReader =new BufferedReader(new InputStreamReader(socket.getInputStream())); ????????????// 輸入讀入一字符串 ????????????String result = bufferedReader.readLine(); ????????????System.out.println("Server say : " + result); ?? ????????????/** 關(guān)閉Socket*/ ????????????printWriter.close(); ????????????bufferedReader.close(); ????????????socket.close(); ????????}catch (Exception e) { ????????????System.out.println("Exception:" + e); ????????} ????} }

服務(wù)器端程序:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 package sock; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; ?? public class SocketServer { ????public static void main(String[] args) { ????????try { ????????????/** 創(chuàng)建ServerSocket*/ ????????????// 創(chuàng)建一個(gè)ServerSocket在端口2013監(jiān)聽客戶請(qǐng)求 ????????????ServerSocket serverSocket =new ServerSocket(2013); ????????????while (true) { ????????????????// 偵聽并接受到此Socket的連接,請(qǐng)求到來(lái)則產(chǎn)生一個(gè)Socket對(duì)象,并繼續(xù)執(zhí)行 ????????????????Socket socket = serverSocket.accept(); ?? ????????????????/** 獲取客戶端傳來(lái)的信息 */ ????????????????// 由Socket對(duì)象得到輸入流,并構(gòu)造相應(yīng)的BufferedReader對(duì)象 ????????????????BufferedReader bufferedReader =new BufferedReader(new InputStreamReader(socket.getInputStream())); ????????????????// 獲取從客戶端讀入的字符串 ????????????????String result = bufferedReader.readLine(); ????????????????System.out.println("Client say : " + result); ?? ????????????????/** 發(fā)送服務(wù)端準(zhǔn)備傳輸?shù)?*/ ????????????????// 由Socket對(duì)象得到輸出流,并構(gòu)造PrintWriter對(duì)象 ????????????????PrintWriter printWriter =new PrintWriter(socket.getOutputStream()); ????????????????printWriter.print("hello Client, I am Server!"); ????????????????printWriter.flush(); ?? ????????????????/** 關(guān)閉Socket*/ ????????????????printWriter.close(); ????????????????bufferedReader.close(); ????????????????socket.close(); ????????????} ????????}catch (Exception e) { ????????????System.out.println("Exception:" + e); ????????}finally{ //????????? serverSocket.close(); ????????} ????} }

六、多客戶端連接服務(wù)器

上面的服務(wù)器端程序一次只能連接一個(gè)客戶端,這在實(shí)際應(yīng)用中顯然是不可能的。通常的網(wǎng)絡(luò)環(huán)境是多個(gè)客戶端連接到某個(gè)主機(jī)進(jìn)行通訊,所以我們要對(duì)上面的程序進(jìn)行改造。

設(shè)計(jì)思路:服務(wù)器端主程序監(jiān)聽某一個(gè)端口,客戶端發(fā)起連接請(qǐng)求,服務(wù)器端主程序接收請(qǐng)求,同時(shí)構(gòu)造一個(gè)線程類,用于接管會(huì)話。當(dāng)一個(gè)Socket會(huì)話產(chǎn)生后,這個(gè)會(huì)話就會(huì)交給線程進(jìn)行處理,主程序繼續(xù)進(jìn)行監(jiān)聽。

下面的實(shí)現(xiàn)程序流程是:客戶端和服務(wù)器建立連接,客戶端發(fā)送消息,服務(wù)端根據(jù)消息進(jìn)行處理并返回消息,若客戶端申請(qǐng)關(guān)閉,則服務(wù)器關(guān)閉此連接,雙方通訊結(jié)束。

客戶端程序:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 package sock; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; ?? public class SocketClient { ????public static void main(String[] args) { ????????try { ????????????Socket socket =new Socket("127.0.0.1",2013); ????????????socket.setSoTimeout(60000); ?? ????????????PrintWriter printWriter =new PrintWriter(socket.getOutputStream(),true); ????????????BufferedReader bufferedReader =new BufferedReader(new InputStreamReader(socket.getInputStream())); ?????????????? ????????????String result =""; ????????????while(result.indexOf("bye") == -1){ ????????????????BufferedReader sysBuff =new BufferedReader(new InputStreamReader(System.in)); ????????????????printWriter.println(sysBuff.readLine()); ????????????????printWriter.flush(); ?????????????????? ????????????????result = bufferedReader.readLine(); ????????????????System.out.println("Server say : " + result); ????????????} ?? ????????????printWriter.close(); ????????????bufferedReader.close(); ????????????socket.close(); ????????}catch (Exception e) { ????????????System.out.println("Exception:" + e); ????????} ????} }

服務(wù)器端程序:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 package sock; import java.io.*; import java.net.*; ?? public class Server extends ServerSocket { ????private static final int SERVER_PORT =2013; ?? ????public Server()throws IOException { ????????super(SERVER_PORT); ?? ????????try { ????????????while (true) { ????????????????Socket socket = accept(); ????????????????new CreateServerThread(socket);//當(dāng)有請(qǐng)求時(shí),啟一個(gè)線程處理 ????????????} ????????}catch (IOException e) { ????????}finally { ????????????close(); ????????} ????} ?? ????//線程類 ????class CreateServerThread extends Thread { ????????private Socket client; ????????private BufferedReader bufferedReader; ????????private PrintWriter printWriter; ?? ????????public CreateServerThread(Socket s)throws IOException { ????????????client = s; ?? ????????????bufferedReader =new BufferedReader(new InputStreamReader(client.getInputStream())); ?????????????? ????????????printWriter =new PrintWriter(client.getOutputStream(),true); ????????????System.out.println("Client(" + getName() +") come in..."); ?????????????? ????????????start(); ????????} ?? ????????public void run() { ????????????try { ????????????????String line = bufferedReader.readLine(); ?? ????????????????while (!line.equals("bye")) { ????????????????????printWriter.println("continue, Client(" + getName() +")!"); ????????????????????line = bufferedReader.readLine(); ????????????????????System.out.println("Client(" + getName() +") say: " + line); ????????????????} ????????????????printWriter.println("bye, Client(" + getName() +")!"); ?????????????????? ????????????????System.out.println("Client(" + getName() +") exit!"); ????????????????printWriter.close(); ????????????????bufferedReader.close(); ????????????????client.close(); ????????????}catch (IOException e) { ????????????} ????????} ????} ?? ????public static void main(String[] args)throws IOException { ????????new Server(); ????} }

七、信息共享

以上雖然實(shí)現(xiàn)了多個(gè)客戶端和服務(wù)器連接,但是仍然是消息在一個(gè)客戶端和服務(wù)器之間相互傳播。現(xiàn)在我們要實(shí)現(xiàn)信息共享,即服務(wù)器可以向多個(gè)客戶端發(fā)送廣播消息,客戶端也可以向其他客戶端發(fā)送消息。類似于聊天室的那種功能,實(shí)現(xiàn)信息能在多個(gè)客戶端之間共享。

設(shè)計(jì)思路:客戶端循環(huán)可以不停輸入向服務(wù)器發(fā)送消息,并且啟一個(gè)線程,專門用來(lái)監(jiān)聽服務(wù)器端發(fā)來(lái)的消息并打印輸出。服務(wù)器端啟動(dòng)時(shí),啟動(dòng)一個(gè)監(jiān)聽何時(shí)需要向客戶端發(fā)送消息的線程。每次接受客戶端連接請(qǐng)求,都啟一個(gè)線程進(jìn)行處理,并且將客戶端信息存放到公共集合中。當(dāng)客戶端發(fā)送消息時(shí),服務(wù)器端將消息順序存入隊(duì)列中,當(dāng)需要輸出時(shí),從隊(duì)列中取出廣播到各客戶端處。客戶端輸入showuser命令可以查看在線用戶列表,輸入bye向服務(wù)器端申請(qǐng)退出連接。

PS:以下代碼在測(cè)試時(shí)發(fā)現(xiàn)了一個(gè)中文亂碼小問題,當(dāng)文件設(shè)置UTF-8編碼時(shí),無(wú)論怎樣在代碼中設(shè)置輸入流編碼都不起作用,輸入中文仍然會(huì)亂碼。把文件設(shè)置為GBK編碼后,不用在代碼中設(shè)置輸入流編碼都能正常顯示傳輸中文。

客戶端代碼:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 package sock; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; ?? public class SocketClient extends Socket{ ?? ????private static final String SERVER_IP ="127.0.0.1"; ????private static final int SERVER_PORT =2013; ?????? ????private Socket client; ????private PrintWriter out; ????private BufferedReader in; ?????? ????/** ?????* 與服務(wù)器連接,并輸入發(fā)送消息 ?????*/ ????public SocketClient()throws Exception{ ????????super(SERVER_IP, SERVER_PORT); ????????client =this; ????????out =new PrintWriter(this.getOutputStream(),true); ????????in =new BufferedReader(new InputStreamReader(this.getInputStream())); ????????new readLineThread(); ?????????? ????????while(true){ ????????????in =new BufferedReader(new InputStreamReader(System.in)); ????????????String input = in.readLine(); ????????????out.println(input); ????????} ????} ?????? ????/** ?????* 用于監(jiān)聽服務(wù)器端向客戶端發(fā)送消息線程類 ?????*/ ????class readLineThread extends Thread{ ?????????? ????????private BufferedReader buff; ????????public readLineThread(){ ????????????try { ????????????????buff =new BufferedReader(new InputStreamReader(client.getInputStream())); ????????????????start(); ????????????}catch (Exception e) { ????????????} ????????} ?????????? ????????@Override ????????public void run() { ????????????try { ????????????????while(true){ ????????????????????String result = buff.readLine(); ????????????????????if("byeClient".equals(result)){//客戶端申請(qǐng)退出,服務(wù)端返回確認(rèn)退出 ????????????????????????break; ????????????????????}else{//輸出服務(wù)端發(fā)送消息 ????????????????????????System.out.println(result); ????????????????????} ????????????????} ????????????????in.close(); ????????????????out.close(); ????????????????client.close(); ????????????}catch (Exception e) { ????????????} ????????} ????} ?????? ????public static void main(String[] args) { ????????try { ????????????new SocketClient();//啟動(dòng)客戶端 ????????}catch (Exception e) { ????????} ????} }

服務(wù)器端代碼:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 package sock; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; ?? ?? public class Server extends ServerSocket{ ?????? ????private static final int SERVER_PORT =2013; ?????? ????private static boolean isPrint =false;//是否輸出消息標(biāo)志 ????private static List user_list =new ArrayList();//登錄用戶集合 ????private static List<ServerThread> thread_list =new ArrayList<ServerThread>();//服務(wù)器已啟用線程集合 ????private static LinkedList<String> message_list =new LinkedList<String>();//存放消息隊(duì)列 ?????? ????/** ?????* 創(chuàng)建服務(wù)端Socket,創(chuàng)建向客戶端發(fā)送消息線程,監(jiān)聽客戶端請(qǐng)求并處理 ?????*/ ????public Server()throws IOException{ ????????super(SERVER_PORT);//創(chuàng)建ServerSocket ????????new PrintOutThread();//創(chuàng)建向客戶端發(fā)送消息線程 ?????????? ????????try { ????????????while(true){//監(jiān)聽客戶端請(qǐng)求,啟個(gè)線程處理 ????????????????Socket socket = accept(); ????????????????new ServerThread(socket); ????????????} ????????}catch (Exception e) { ????????}finally{ ????????????close(); ????????} ????} ?????? ????/** ?????* 監(jiān)聽是否有輸出消息請(qǐng)求線程類,向客戶端發(fā)送消息 ?????*/ ????class PrintOutThread extends Thread{ ?????????? ????????public PrintOutThread(){ ????????????start(); ????????} ?????????? ????????@Override ????????public void run() { ????????????while(true){ ????????????????if(isPrint){//將緩存在隊(duì)列中的消息按順序發(fā)送到各客戶端,并從隊(duì)列中清除。 ????????????????????String message = message_list.getFirst(); ????????????????????for (ServerThread thread : thread_list) { ????????????????????????thread.sendMessage(message); ????????????????????} ????????????????????message_list.removeFirst(); ????????????????????isPrint = message_list.size() >0 ?true :false; ????????????????} ????????????} ????????} ????} ?????? ????/** ?????* 服務(wù)器線程類 ?????*/ ????class ServerThread extends Thread{ ????????private Socket client; ????????private PrintWriter out; ????????private BufferedReader in; ????????private String name; ?????????? ????????public ServerThread(Socket s)throws IOException{ ????????????client = s; ????????????out =new PrintWriter(client.getOutputStream(),true); ????????????in =new BufferedReader(new InputStreamReader(client.getInputStream())); ????????????in.readLine(); ????????????out.println("成功連上聊天室,請(qǐng)輸入你的名字:"); ????????????start(); ????????} ?????????? ????????@Override ????????public void run() { ????????????try { ????????????????int flag =0; ????????????????String line = in.readLine(); ????????????????while(!"bye".equals(line)){ ????????????????????//查看在線用戶列表 ????????????????????if ("showuser".equals(line)) { ????????????????????????out.println(this.listOnlineUsers()); ????????????????????????line = in.readLine(); ????????????????????} ????????????????????//第一次進(jìn)入,保存名字 ????????????????????if(flag++ ==0){ ????????????????????????name = line; ????????????????????????user_list.add(name); ????????????????????????thread_list.add(this); ????????????????????????out.println(name +"你好,可以開始聊天了..."); ????????????????????????this.pushMessage("Client<" + name +">進(jìn)入聊天室..."); ????????????????????}else{ ????????????????????????this.pushMessage("Client<" + name +"> say : " + line); ????????????????????} ????????????????????line = in.readLine(); ????????????????} ????????????????out.println("byeClient"); ????????????}catch (Exception e) { ????????????????e.printStackTrace(); ????????????}finally{//用戶退出聊天室 ????????????????try { ????????????????????client.close(); ????????????????}catch (IOException e) { ????????????????????e.printStackTrace(); ????????????????} ????????????????thread_list.remove(this); ????????????????user_list.remove(name); ????????????????pushMessage("Client<" + name +">退出了聊天室"); ????????????} ????????} ?????????? ????????//放入消息隊(duì)列末尾,準(zhǔn)備發(fā)送給客戶端 ????????private void pushMessage(String msg){ ????????????message_list.addLast(msg); ????????????isPrint =true; ????????} ?????????? ????????//向客戶端發(fā)送一條消息 ????????private void sendMessage(String msg){ ????????????out.println(msg); ????????} ?????????? ????????//統(tǒng)計(jì)在線用戶列表 ????????private String listOnlineUsers() { ????????????String s ="--- 在線用戶列表 ---\015\012"; ????????????for (int i =0; i < user_list.size(); i++) { ????????????????s +="[" + user_list.get(i) +"]\015\012"; ????????????} ????????????s +="--------------------"; ????????????return s; ????????} ????} ?????? ????public static void main(String[] args)throws IOException { ????????new Server();//啟動(dòng)服務(wù)端 ????} }

八、文件傳輸

客戶端向服務(wù)器端傳送文件,服務(wù)端可獲取文件名用于保存,獲取文件大小計(jì)算傳輸進(jìn)度,比較簡(jiǎn)單,直接貼代碼。

客戶端代碼:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 package sock; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.net.Socket; ?? /** ?* 客戶端 ?*/ public class Client extends Socket{ ?????? ????private static final String SERVER_IP ="127.0.0.1"; ????private static final int SERVER_PORT =2013; ?????? ????private Socket client; ????private FileInputStream fis; ????private DataOutputStream dos; ?????? ????public Client(){ ????????try { ????????????try { ????????????????client =new Socket(SERVER_IP, SERVER_PORT); ????????????????//向服務(wù)端傳送文件 ????????????????File file =new File("c:/test.doc"); ????????????????fis =new FileInputStream(file); ????????????????dos =new DataOutputStream(client.getOutputStream()); ?????????????????? ????????????????//文件名和長(zhǎng)度 ????????????????dos.writeUTF(file.getName()); ????????????????dos.flush(); ????????????????dos.writeLong(file.length()); ????????????????dos.flush(); ?????????????????? ????????????????//傳輸文件 ????????????????byte[] sendBytes =new byte[1024]; ????????????????int length =0; ????????????????while((length = fis.read(sendBytes,0, sendBytes.length)) >0){ ????????????????????dos.write(sendBytes,0, length); ????????????????????dos.flush(); ????????????????} ????????????}catch (Exception e) { ????????????????e.printStackTrace(); ????????????}finally{ ????????????????if(fis !=null) ????????????????????fis.close(); ????????????????if(dos !=null) ????????????????????dos.close(); ????????????????client.close(); ????????????} ????????}catch (Exception e) { ????????????e.printStackTrace(); ????????} ????} ?????? ????public static void main(String[] args)throws Exception { ????????new Client(); ????} }

服務(wù)器端代碼:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 package sock; import java.io.DataInputStream; import java.io.File; import java.io.FileOutputStream; import java.net.ServerSocket; import java.net.Socket; ?? /** ?* 服務(wù)器 ?*/ public class Server extends ServerSocket{ ?? ????private static final int PORT =2013; ?????? ????private ServerSocket server; ????private Socket client; ????private DataInputStream dis; ????private FileOutputStream fos; ?????? ????public Server()throws Exception{ ????????try { ????????????try { ????????????????server =new ServerSocket(PORT); ?????????????????? ????????????????while(true){ ????????????????????client = server.accept(); ?????????????????????? ????????????????????dis =new DataInputStream(client.getInputStream()); ????????????????????//文件名和長(zhǎng)度 ????????????????????String fileName = dis.readUTF(); ????????????????????long fileLength = dis.readLong(); ????????????????????fos =new FileOutputStream(new File("d:/" + fileName)); ?????????????????????? ????????????????????byte[] sendBytes =new byte[1024]; ????????????????????int transLen =0; ????????????????????System.out.println("----開始接收文件<" + fileName +">,文件大小為<" + fileLength +">----"); ????????????????????while(true){ ????????????????????????int read =0; ????????????????????????read = dis.read(sendBytes); ????????????????????????if(read == -1) ????????????????????????????break; ????????????????????????transLen += read; ????????????????????????System.out.println("接收文件進(jìn)度" +100 * transLen/fileLength +"%..."); ????????????????????????fos.write(sendBytes,0, read); ????????????????????????fos.flush(); ????????????????????} ????????????????????System.out.println("----接收文件<" + fileName +">成功-------"); ????????????????????client.close(); ????????????????} ????????????}catch (Exception e) { ????????????????e.printStackTrace(); ????????????}finally { ????????????????if(dis !=null) ????????????????????dis.close(); ????????????????if(fos !=null) ????????????????????fos.close(); ????????????????server.close(); ????????????} ????????}catch (Exception e) { ????????????e.printStackTrace(); ????????} ????} ?????? ????public static void main(String[] args)throws Exception { ????????new Server(); ????} }

轉(zhuǎn)載于:https://www.cnblogs.com/huangwentian/p/7810532.html

總結(jié)

以上是生活随笔為你收集整理的循序渐进Java Socket网络编程(多客户端、信息共享、文件传输)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产精品日韩精品 | 天天躁日日摸久久久精品 | 777中文字幕 | 毛片无遮挡高清免费观看 | 国产精品一区二区在线观看 | 成人在线不卡视频 | 久久精品无码一区二区三区 | 欧美精品一区三区 | 伊人视频 | 国产91精品久久久久久久 | 少妇精品一区 | 亚洲国产欧美在线观看 | 欧美精品1区 | 成人午夜视频在线 | 国产一区二区视频在线 | av在线收看 | 亚洲国产福利 | 野花成人免费视频 | 午夜影视大全 | 国产婷婷色一区二区三区 | 蜜桃视频成人在线观看 | 日韩亚洲欧美一区 | 日本少妇吞精囗交 | 福利视频在线播放 | 午夜少妇视频 | 日本高清xxxx| 高清av一区二区三区 | 九九热最新视频 | 免费看美女被靠到爽的视频 | 欧美影院在线观看 | 国产乱子伦精品无码专区 | 夜夜嗨aⅴ一区二区三区 | 日韩欧美一区二区免费 | 久久久久逼 | 亚洲精品影院 | 嫩草网站 | 狠色综合 | 亚洲精品国产视频 | 香蕉久久夜色精品 | 日韩欧美一区二区在线观看 | 九九天堂网 | 成人福利小视频 | 国产毛片基地 | 亚洲视频在线一区二区 | 成年人看片网站 | 视频二区在线观看 | 波多野结衣在线免费视频 | 日韩欧美色 | 国产中文字幕亚洲 | 中文国产在线观看 | 美日韩中文字幕 | 男生操女生在线观看 | 免费观看一级黄色片 | 欧美精品久久久久久久 | julia一区 | 日本xxxx在线观看 | 自拍视频在线观看 | 日韩精品一区二区三区久久 | 日韩国产91| 黄色网页在线观看 | 国产精彩视频在线观看 | 亚色91 | 羞羞漫画在线播放 | 宅男午夜在线 | www.色欧美 | 国产精品系列在线播放 | 91在线精品一区二区三区 | 99午夜视频| 亚洲色欲色欲www在线观看 | 亚洲精品成人片在线观看精品字幕 | aaaaa一级片| 国产视频精品自拍 | 三级a做爰全过程 | 久久久视频在线观看 | 自拍偷拍第一页 | 国内三级在线 | 91肉色超薄丝袜脚交一区二区 | 久久一区二区三区四区五区 | 国产亚洲第一页 | 欧美不卡视频 | 高清乱码免费看污 | 国产女人和拘做受视频免费 | 中文字幕日产乱码中 | 中文字幕乱轮 | 久久综合干| 色播视频在线观看 | 精品久久久久久久久中文字幕 | 国语av在线 | 亚洲第一黄色网 | 伊人国产在线 | 视频在线国产 | 高清视频一区二区 | 又黄又色又爽的视频 | 久草老司机| 久久精品99国产国产精 | caoprom97| 久久好色 | 欧美日韩国产精品一区二区 | 理论片一级 |