三步搭建伺服器
搭建一個聊天伺服器其實 很簡單,在這裡我將其分為三步:
第一步,建立一個伺服器,及例項化一個ServerSocket物件server,在這一部中要注意的就是在例項化ServerSocket物件的時候要有個埠引數,是一個0~65535的整型資料,此時要注意異常的處理。
第二步,等待客戶端連線,即建立一個Socket物件,使用語句Socket client = server。accept();此時程式會進入“待機”狀態,直到有客戶機連線。
第三步,傳送訊息,當一個客戶機連上伺服器後就要面臨收發訊息這個問題,我們透過對輸入輸出流物件的處理來解決這一問題。首先例項化輸入輸出流物件,使用語句InputStream ins = client。getInputStream();OutputStream ous = client。getOutputStream();當我們獲得輸入輸出流物件後,我們只要透過read()和write()函式來讀和寫就可以了。在這裡要注意的一個問題就是,其實我們每次傳送訊息時,傳送的都是字串所對應的字串陣列。因此,我們要先用getBytes()方法得到字串所對應的字串陣列,然後用write()方法進行寫。
到此,一個簡單的伺服器就搭建好了,當然,在這個伺服器中還存在非常多的漏洞,下面讓我們再來對這個簡單的伺服器再升級一下。
首先,我們當然不希望我們的伺服器只能連線一次客戶機,然後就關閉,就像我們不允許我們的手機每次再接到一個來電後就關機,這是一個讓人頭疼的問題。那麼,我們就要讓伺服器不斷地進入等待,因此,我們可以將等待客戶機連線這一步放入一個死迴圈中,這樣,在一個客戶機脫離連結後,伺服器將不會出現“關機”現象。
其次,我們當然也希望我們的伺服器可以被多個客戶同時連線,這個想法是可行的,就像我們好幾個人可以同時撥打10086進行通話一樣。那麼我們怎樣才能讓我們的伺服器能同時連上幾個客戶機呢,我們想到了執行緒。我們用執行緒去處理客戶機的連結。每當有客戶機來連線伺服器時,我們就開闢一個執行緒去處理它。
在這裡,我們先用windows系統自帶的原始客戶端進行測試,只需在控制面版中輸入cmd開啟命令視窗,然後輸入“telnet localhost + 埠號 ”就可以連上自己搭建的伺服器了,要想連線另外一臺電腦的伺服器,輸入“telnet + 對方的IP地址+伺服器埠號”。
到這一步,我們已經能做到好幾個客戶機同時連上伺服器了,那麼,我們又要想了,這麼多個客戶機之間怎麼樣才“溝通”呢。我們下一篇接著分享。
package
socket1014
;
import
java。io。IOException
;
/**
* 用執行緒去處理客戶機的連結,實現多個客戶機與伺服器的通訊
* @author Sam
*
*/
public
class
SocketThread
extends
Thread
{
private
java
。
net
。
Socket
client
;
private
java
。
io
。
OutputStream
ous
;
private
java
。
io
。
InputStream
ins
;
//str表示伺服器向客戶機發送的字串,inputSting表示要讀寫的輸入字串,user表示使用者名稱,password表示密碼
private
String
str
,
inputString
,
user
,
password
;
private
byte
[]
data
;
//建構函式,傳入一個client
public
SocketThread
(
java
。
net
。
Socket
client
){
this
。
client
=
client
;
}
//傳送資訊的方法
public
void
sendMessage
(
String
message
)
throws
IOException
{
data
=
message
。
getBytes
();
ous
。
write
(
data
);
ous
。
flush
();
}
//重寫執行緒中的run方法,用執行緒去處理客戶機的連結
public
void
run
(){
try
{
handlC
(
this
。
client
);
}
catch
(
IOException
e
)
{
e
。
printStackTrace
();
}
}
public
void
handlC
(
java
。
net
。
Socket
client
)
throws
IOException
{
ous
=
client
。
getOutputStream
();
ins
=
client
。
getInputStream
();
str
=
“歡迎來到小波哥建立的伺服器\n”
;
//每當有一個客戶機連線時,就顯示出歡迎語
data
=
str
。
getBytes
();
ous
。
write
(
data
);
ous
。
flush
();
//強制輸出
do
{
str
=
“請輸入使用者名稱:”
;
data
=
str
。
getBytes
();
ous
。
write
(
data
);
ous
。
flush
();
//
user
=
readInput
(
this
。
client
);
}
while
(!
user
。
equals
(
“poe”
));
do
{
str
=
“請輸入密碼:”
;
data
=
str
。
getBytes
();
ous
。
write
(
data
);
ous
。
flush
();
//
password
=
readInput
(
this
。
client
);
}
while
(!
password
。
equals
(
“123”
));
//輸對使用者名稱和密碼後才能進行下面的工作
str
=
“歡迎poe進入,您現在可以進行聊天了”
;
data
=
str
。
getBytes
();
ous
。
write
(
data
);
ous
。
flush
();
inputString
=
readInput
(
this
。
client
);
System
。
out
。
println
(
“客戶機:”
+
inputString
);
while
(!
inputString
。
equals
(
“bye”
)){
data
=
(
“伺服器收到:”
+
inputString
)。
getBytes
();
ous
。
write
(
data
);
ous
。
flush
();
inputString
=
readInput
(
this
。
client
);
}
System
。
out
。
println
(
“客戶機:bye”
);
str
=
“bye,歡迎下次再來”
;
data
=
str
。
getBytes
();
ous
。
write
(
data
);
ous
。
flush
();
ous
。
close
();
}
public
String
readInput
(
java
。
net
。
Socket
client
)
throws
IOException
{
//先例項化一個字串緩衝區
StringBuffer
sb
=
new
StringBuffer
();
char
c
=
0
;
while
(
c
!=
13
){
int
i
=
ins
。
read
();
c
=
(
char
)
i
;
sb
。
append
(
c
);
}
inputString
=
sb
。
toString
()。
trim
();
return
inputString
;
}
public
void
startSock
(
int
port
){
try
{
java
。
net
。
ServerSocket
ss
=
new
java
。
net
。
ServerSocket
(
port
);
System
。
out
。
println
(
“成功建立伺服器:”
+
port
);
while
(
true
){
client
=
ss
。
accept
();
SocketThread
t
=
new
SocketThread
(
client
);
t
。
start
();
System
。
out
。
println
(
“已經啟動一個執行緒去處理客戶機的連結”
);
}
}
catch
(
IOException
e
)
{
e
。
printStackTrace
();
}
}
public
static
void
main
(
String
[]
args
){
SocketThread
st
=
new
SocketThread
(
null
);
st
。
startSock
(
6060
);
}
}