1.什麼是socket
所謂socket通常也稱作"套接字",用於描述IP地址和端口,是一個通信鏈的句柄。應用程序通常通過"套接字"向網絡發出請求或者應答網絡請求。
以J2SDK-1.3爲例,Socket和ServerSocket類庫位於java.net包中。ServerSocket用於服務器
端,Socket是建立網絡連接時使用的。在連接成功時,應用程序兩端都會產生一個Socket實例,操作這個實例,完成所需的會話。對於一個網絡連接來
說,套接字是平等的,並沒有差別,不因爲在服務器端或在客戶端而產生不同級別。不管是Socket還是ServerSocket它們的工作都是通過
SocketImpl類及其子類完成的。
重要的Socket API:
java.net.Socket繼承於java.lang.Object,有八個構造器,其方法並不多,下面介紹使用最頻繁的三個方法,其它方法大家可以見JDK-1.3文檔。
. Accept方法用於產生"阻塞",直到接受到一個連接,並且返回一個客戶端的Socket對象實例。"阻塞"是一個術語,它使程序運行暫時"停留"在這個地方,直到一個會話產生,然後程序繼續;通常"阻塞"是由循環產生的。
. getInputStream方法獲得網絡連接輸入,同時返回一個IutputStream對象實例,。
. getOutputStream方法連接的另一端將得到輸入,同時返回一個OutputStream對象實例。
注意:其中getInputStream和getOutputStream方法均會產生一個IOException,它必須被捕獲,因爲它們返回的流對象,通常都會被另一個流對象使用。
2.如何開發一個Server-Client模型的程序
開發原理:
服務器,使用ServerSocket監聽指定的端口,端口可以隨意指定(由於1024以下的端口通常屬於保留端口,在一些操作系統中不可以隨意使用,所以建議使用大於1024的端口),等待客戶連接請求,客戶連接後,會話產生;在完成會話後,關閉連接。
客戶端,使用Socket對網絡上某一個服務器的某一個端口發出連接請求,一旦連接成功,打開會話;會話完成後,關閉Socket。客戶端不需要指定打開的端口,通常臨時的、動態的分配一個1024以上的端口。
多個客戶同時連接:
主程序監聽一端口,等待客戶接入;同時構造一個線程類,準備接管會話。當一個Socket會話產生後,將這個會話交給線程處理,然後主程序繼續監聽。運用Thread類或Runnable接口來實現是不錯的辦法。
現在實現服務器端編程:(基於TCP方式)
MyServer .java
---------------------------------------------------
package server;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;
//這個簡單的socket服務器端主要是說句Hello XXX,採用多線程實現
public class MyServer extends Thread {
private Socket s;
public static void main(String[] args) {
MyServer.server();//main入口,一運行機器,就開通server服務。
}
public MyServer(Socket s) {
this.s = s;
}
public void run() {
try {
OutputStream os = s.getOutputStream();
InputStream is=s.getInputStream();
byte[] bu=new byte[20];
int len=is.read(bu);//從客戶端讀取消息
String userName=new String(bu,0,len);
Date d=new Date();
System.out.println(userName+" is coming here at "+d.toLocaleString());//寫在服務器端控制檯的日誌顯示
String welcome="hello,"+userName+"!";
//System.out.println(welcome);
os.write(welcome.getBytes());//返回給客戶端的歡迎信息
os.close();
is.close();
s.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void server() {
try {
ServerSocket ss = new ServerSocket(9527); //服務器的套接字,端口爲9527
while (true) {
Socket s = ss.accept();
new MyServer(s).start(); //用戶一進來就運行一個線程
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
客戶端編程:
MyClient .java
---------------------------------
package client;
import java.io.*;
import java.net.*;
public class MyClient {
public static void main(String[] args) {
//這裏先強迫用戶輸入用戶名,調用client(str)方法。
String str = "";
try {
while (str.length() < 1) {
System.out.println("請輸入您的名字");
str = new DataInputStream(new BufferedInputStream(System.in))
.readLine();
}
} catch (Exception e) {
e.printStackTrace();
}
MyClient.client(str);
}
public static void client(String userName) {
try {
Socket s = new Socket(InetAddress.getByName("127.0.0.1"), 9527);//套接字的IP地址和端口號
OutputStream os = s.getOutputStream();
InputStream is = s.getInputStream();
byte[] Name = userName.getBytes("ISO-8859-1"); //這個是爲了中文亂碼問題
os.write(Name);//向服務器發送消息
byte[] serverSay = new byte[100];
int len = is.read(serverSay);//接受服務器消息
System.out.println(new String(serverSay, 0, len));//客戶端控制檯顯示服務器返回的信息
is.close();
os.close();
s.close();//記住一定要關閉這些輸入,輸出流和套接字
} catch (Exception e) {
e.printStackTrace();
}
}
}