既然是網絡編程,涉及幾個系統之間的交互,那麼首先要考慮的是如何準確的定位到網絡上的一臺或幾臺主機,另外一個是如何進行可靠高效的數據傳輸。這裏就要使用到TCP/IP協議。html
TCP/IP協議(傳輸控制協議)由網絡層的IP協議和傳輸層的TCP協議組成。IP層負責網絡主機的定位,數據傳輸的路由,由IP地址能夠惟一的肯定Internet上的一臺主機。TCP層負責面向應用的可靠的或非可靠的數據傳輸機制,這是網絡編程的主要對象。java
TCP是一種面向鏈接的保證可靠傳輸的協議。經過TCP協議傳輸,獲得的是一個順序的無差錯的數據流。發送方和接收方的成對的兩個socket之間必須創建鏈接,以便在TCP協議的基礎上進行通訊,當一個socket(一般都是server socket)等待創建鏈接時,另外一個socket能夠要求進行鏈接,一旦這兩個socket鏈接起來,它們就能夠進行雙向數據傳輸,雙方均可以進行發送或接收操做。編程
UDP是一種面向無鏈接的協議,每一個數據報都是一個獨立的信息,包括完整的源地址或目的地址,它在網絡上以任何可能的路徑傳往目的地,所以可否到達目的地,到達目的地的時間以及內容的正確性都是不能被保證的。緩存
TCP與UDP區別:服務器
TCP特色:網絡
一、TCP是面向鏈接的協議,經過三次握手創建鏈接,通信完成時要拆除鏈接,因爲TCP是面向鏈接協議,因此只能用於點對點的通信。並且創建鏈接也須要消耗時間和開銷。socket
二、TCP傳輸數據無大小限制,進行大數據傳輸。ide
三、TCP是一個可靠的協議,它能保證接收方可以完整正確地接收到發送方發送的所有數據。測試
UDP特色:大數據
一、UDP是面向無鏈接的通信協議,UDP數據包括目的端口號和源端口號信息,因爲通信不須要鏈接,因此能夠實現廣播發送。
二、UDP傳輸數據時有大小限制,每一個被傳輸的數據報必須限定在64KB以內。
三、UDP是一個不可靠的協議,發送方所發送的數據報並不必定以相同的次序到達接收方。
TCP與UDP應用:
一、TCP在網絡通訊上有極強的生命力,例如遠程鏈接(Telnet)和文件傳輸(FTP)都須要不定長度的數據被可靠地傳輸。可是可靠的傳輸是要付出代價的,對數據內容正確性的檢驗必然佔用計算機的處理時間和網絡的帶寬,所以TCP傳輸的效率不如UDP高。
2,UDP操做簡單,並且僅須要較少的監護,所以一般用於局域網高可靠性的分散系統中client/server應用程序。例如視頻會議系統,並不要求音頻視頻數據絕對的正確,只要保證連貫性就能夠了,這種狀況下顯然使用UDP會更合理一些。
Socket一般也稱做"套接字",用於描述IP地址和端口,是一個通訊鏈的句柄。網絡上的兩個程序經過一個雙向的通信鏈接實現數據的交換,這個雙向鏈路的一端稱爲一個Socket,一個Socket由一個IP地址和一個端口號惟一肯定。應用程序一般經過"套接字"向網絡發出請求或者應答網絡請求。 Socket是TCP/IP協議的一個十分流行的編程界面,可是,Socket所支持的協議種類也不光TCP/IP一種,所以二者之間是沒有必然聯繫的。在Java環境下,Socket編程主要是指基於TCP/IP協議的網絡編程。
Socket通信過程:服務端監聽某個端口是否有鏈接請求,客戶端向服務端發送鏈接請求,服務端收到鏈接請求向客戶端發出接收消息,這樣一個鏈接就創建起來了。客戶端和服務端均可以相互發送消息與對方進行通信。
Socket的基本工做過程包含如下四個步驟:
一、建立Socket;
二、打開鏈接到Socket的輸入輸出流;
三、按照必定的協議對Socket進行讀寫操做;
四、關閉Socket。
在java.net包下有兩個類:Socket和ServerSocket。ServerSocket 用於服務器端,Socket是創建網絡鏈接時使用的。在鏈接成功時,應用程序兩端都會產生一個Socket實例,操做這個實例,完成所需的會話。對於一個 網絡鏈接來講,套接字是平等的,並無差異,不由於在服務器端或在客戶端而產生不一樣級別。不論是Socket仍是ServerSocket它們的工做都是 經過SocketImpl類及其子類完成的。
列出幾個經常使用的構造方法:
1
2
3
4
5
6
7
8
9
|
Socket(InetAddress address,int port);//建立一個流套接字並將其鏈接到指定 IP 地址的指定端口號
Socket(String host,int port);//建立一個流套接字並將其鏈接到指定主機上的指定端口號
Socket(InetAddress address,int port, InetAddress localAddr,int localPort);//建立一個套接字並將其鏈接到指定遠程地址上的指定遠程端口
Socket(String host,int port, InetAddress localAddr,int localPort);//建立一個套接字並將其鏈接到指定遠程主機上的指定遠程端口
Socket(SocketImpl impl);//使用用戶指定的 SocketImpl 建立一個未鏈接 Socket
ServerSocket(int port);//建立綁定到特定端口的服務器套接字
ServerSocket(int port,int backlog);//利用指定的 backlog 建立服務器套接字並將其綁定到指定的本地端口號
ServerSocket(int port,int backlog, InetAddress bindAddr);//使用指定的端口、偵聽 backlog 和要綁定到的本地 IP地址建立服務器
|
構造方法的參數中,address、host和port分別是雙向鏈接中另外一方的IP地址、主機名和端 口號,stream指明socket是流socket仍是數據報socket,localPort表示本地主機的端口號,localAddr和bindAddr是本地機器的地址(ServerSocket的主機地址),impl是socket的父類,既能夠用來建立serverSocket又能夠用來建立Socket。count則表示服務端所能支持的最大鏈接數。
注意:必須當心選擇端口號。每個端口提供一種特定的服務,只有給出正確的端口,才 能得到相應的服務。0~1023的端口號爲系統所保留,例如http服務的端口號爲80,telnet服務的端口號爲21,ftp服務的端口號爲23, 因此咱們在選擇端口號時,最好選擇一個大於1023的數以防止發生衝突。
幾個重要的Socke方法:
1
2
3
|
public InputStream getInputStream();//方法得到網絡鏈接輸入,同時返回一個IutputStream對象實例
public OutputStream getOutputStream();//方法鏈接的另外一端將獲得輸入,同時返回一個OutputStream對象實例
public Socket accept();//用於產生"阻塞",直到接受到一個鏈接,而且返回一個客戶端的Socket對象實例。
|
"阻塞"是一個術語,它使程序運行暫時"停留"在這個地方,直到一個會話產生,而後程序繼續;一般"阻塞"是由循環產生的。
注意:其中getInputStream和getOutputStream方法均會產生一個IOException,它必須被捕獲,由於它們返回的流對象,一般都會被另外一個流對象使用。
如下是一個基本的客戶端/服務器端程序代碼。主要實現了服務器端一直監聽某個端口,等待客戶端鏈接請求。客戶端根據IP地址和端口號鏈接服務器端,從鍵盤上輸入一行信息,發送到服務器端,而後接收服務器端返回的信息,最後結束會話。這個程序一次只能接受一個客戶鏈接。
ps:這個小例子寫好後,服務端一直接收不到消息,調試了好長時間,才發現誤使用了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
{
/** 建立Socket*/
// 建立一個流套接字並將其鏈接到指定 IP 地址的指定端口號(本處是本機)
Socket socket =
new
Socket(
"127.0.0.1"
,
2013
);
// 60s超時
socket.setSoTimeout(
60000
);
/** 發送客戶端準備傳輸的信息 */
// 由Socket對象獲得輸出流,並構造PrintWriter對象
PrintWriter printWriter =
new
PrintWriter(socket.getOutputStream(),
true
);
// 將輸入讀入的字符串輸出到Server
BufferedReader sysBuff =
new
BufferedReader(
new
InputStreamReader(System.in));
printWriter.println(sysBuff.readLine());
// 刷新輸出流,使Server立刻收到該字符串
printWriter.flush();
/** 用於獲取服務端傳輸來的信息 */
// 由Socket對象獲得輸入流,並構造相應的BufferedReader對象
BufferedReader bufferedReader =
new
BufferedReader(
new
InputStreamReader(socket.getInputStream()));
// 輸入讀入一字符串
String result = bufferedReader.readLine();
System.out.println(
"Server say : "
+ result);
/** 關閉Socket*/
printWriter.close();
bufferedReader.close();
socket.close();
}
catch
(Exception e) {
System.out.println(
"Exception:"
+ e);
}
}
}
|
服務器端程序:
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
{
/** 建立ServerSocket*/
// 建立一個ServerSocket在端口2013監聽客戶請求
ServerSocket serverSocket =
new
ServerSocket(
2013
);
while
(
true
) {
// 偵聽並接受到此Socket的鏈接,請求到來則產生一個Socket對象,並繼續執行
Socket socket = serverSocket.accept();
/** 獲取客戶端傳來的信息 */
// 由Socket對象獲得輸入流,並構造相應的BufferedReader對象
BufferedReader bufferedReader =
new
BufferedReader(
new
InputStreamReader(socket.getInputStream()));
// 獲取從客戶端讀入的字符串
String result = bufferedReader.readLine();
System.out.println(
"Client say : "
+ result);
/** 發送服務端準備傳輸的 */
// 由Socket對象獲得輸出流,並構造PrintWriter對象
PrintWriter printWriter =
new
PrintWriter(socket.getOutputStream());
printWriter.print(
"hello Client, I am Server!"
);
printWriter.flush();
/** 關閉Socket*/
printWriter.close();
bufferedReader.close();
socket.close();
}
}
catch
(Exception e) {
System.out.println(
"Exception:"
+ e);
}
finally
{
// serverSocket.close();
}
}
}
|
上面的服務器端程序一次只能鏈接一個客戶端,這在實際應用中顯然是不可能的。一般的網絡環境是多個客戶端鏈接到某個主機進行通信,因此咱們要對上面的程序進行改造。
設計思路:服務器端主程序監聽某一個端口,客戶端發起鏈接請求,服務器端主程序接收請求,同時構造一個線程類,用於接管會話。當一個Socket會話產生後,這個會話就會交給線程進行處理,主程序繼續進行監聽。
下面的實現程序流程是:客戶端和服務器創建鏈接,客戶端發送消息,服務端根據消息進行處理並返回消息,若客戶端申請關閉,則服務器關閉此鏈接,雙方通信結束。
客戶端程序:
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);
}
}
}
|
服務器端程序:
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);
//當有請求時,啓一個線程處理
}
}
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();
}
}
|
以上雖然實現了多個客戶端和服務器鏈接,可是仍然是消息在一個客戶端和服務器之間相互傳播。如今咱們要實現信息共享,即服務器能夠向多個客戶端發送廣播消息,客戶端也能夠向其餘客戶端發送消息。相似於聊天室的那種功能,實現信息能在多個客戶端之間共享。
設計思路:客戶端循環能夠不停輸入向服務器發送消息,而且啓一個線程,專門用來監聽服務器端發來的消息並打印輸出。服務器端啓動時,啓動一個監聽什麼時候須要 向客戶端發送消息的線程。每次接受客戶端鏈接請求,都啓一個線程進行處理,而且將客戶端信息存放到公共集合中。當客戶端發送消息時,服務器端將消息順序存 入隊列中,當須要輸出時,從隊列中取出廣播到各客戶端處。客戶端輸入showuser命令能夠查看在線用戶列表,輸入bye向服務器端申請退出鏈接。
PS:如下代碼在測試時發現了一箇中文亂碼小問題,當文件設置UTF-8編碼時,不管怎樣在代碼中設置輸入流編碼都不起做用,輸入中文仍然會亂碼。把文件設置爲GBK編碼後,不用在代碼中設置輸入流編碼都能正常顯示傳輸中文。
客戶端代碼:
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;
/**
* 與服務器鏈接,並輸入發送消息
*/
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);
}
}
/**
* 用於監聽服務器端向客戶端發送消息線程類
*/
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)){
//客戶端申請退出,服務端返回確認退出
break
;
}
else
{
//輸出服務端發送消息
System.out.println(result);
}
}
in.close();
out.close();
client.close();
}
catch
(Exception e) {
}
}
}
public
static
void
main(String[] args) {
try
{
new
SocketClient();
//啓動客戶端
}
catch
(Exception e) {
}
}
}
|
服務器端代碼:
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
;
//是否輸出消息標誌
private
static
List user_list =
new
ArrayList();
//登陸用戶集合
private
static
List<ServerThread> thread_list =
new
ArrayList<ServerThread>();
//服務器已啓用線程集合
private
static
LinkedList<String> message_list =
new
LinkedList<String>();
//存放消息隊列
/**
* 建立服務端Socket,建立向客戶端發送消息線程,監聽客戶端請求並處理
*/
public
Server()
throws
IOException{
super
(SERVER_PORT);
//建立ServerSocket
new
PrintOutThread();
//建立向客戶端發送消息線程
try
{
while
(
true
){
//監聽客戶端請求,啓個線程處理
Socket socket = accept();
new
ServerThread(socket);
}
}
catch
(Exception e) {
}
finally
{
close();
}
}
/**
* 監聽是否有輸出消息請求線程類,向客戶端發送消息
*/
class
PrintOutThread
extends
Thread{
public
PrintOutThread(){
start();
}
@Override
public
void
run() {
while
(
true
){
if
(isPrint){
//將緩存在隊列中的消息按順序發送到各客戶端,並從隊列中清除。
String message = message_list.getFirst();
for
(ServerThread thread : thread_list) {
thread.sendMessage(message);
}
message_list.removeFirst();
isPrint = message_list.size() >
0
?
true
:
false
;
}
}
}
}
/**
* 服務器線程類
*/
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(
"成功連上聊天室,請輸入你的名字:"
);
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();
}
//第一次進入,保存名字
if
(flag++ ==
0
){
name = line;
user_list.add(name);
thread_list.add(
this
);
out.println(name +
"你好,能夠開始聊天了..."
);
this
.pushMessage(
"Client<"
+ name +
">進入聊天室..."
);
}
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 +
">退出了聊天室"
);
}
}
//放入消息隊列末尾,準備發送給客戶端
private
void
pushMessage(String msg){
message_list.addLast(msg);
isPrint =
true
;
}
//向客戶端發送一條消息
private
void
sendMessage(String msg){
out.println(msg);
}
//統計在線用戶列表
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();
//啓動服務端
}
}
|
客戶端向服務器端傳送文件,服務端可獲取文件名用於保存,獲取文件大小計算傳輸進度,比較簡單,直接貼代碼。
客戶端代碼:
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);
//向服務端傳送文件
File file =
new
File(
"c:/test.doc"
);
fis =
new
FileInputStream(file);
dos =
new
DataOutputStream(client.getOutputStream());
//文件名和長度
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();
}
}
|
服務器端代碼:
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;
/**
* 服務器
*/
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());
//文件名和長度
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(
"接收文件進度"
+
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();
}
}
|