本文介紹一種用Java的Socket和ServerSocket實現服務器和客戶機通訊的的方法。原理是在服務器端建立ServerSocket端口並監聽,接收到客戶端的連接請求時建立Socket,得到Socket的輸入輸出流。在客戶端新建Socket並獲得輸入輸出流。服務器和客戶端的輸入輸出流建立後使用writeLine()和println()方法彼此發送和接收數據。為提高代碼效率,建立兩個類clIEntAgent和serverAgent。
一、 客戶端圖形界面
本例中客戶端的圖形界面用Swing實現,服務器端不使用圖形界面
public class JavaClIEnt extends JFrame implements ActionListener//以JFrame為基類,實現ActionListener接口
{
JButton sendButton; //"發送"按鈕
JTextField inputFIEld; // 輸入框
JTextArea outputAera; // 服務器返回框
public JavaClIEnt() //在建構函數中完成圖形界面的初始化
{
inputField=new JTextFIEld("這裡輸入..."); //供客戶端輸入的文本框
outputArea=new JTextArea("服務器返回"); //顯示服務器返回數據的文本域
sendButton=new JButton("發送");
JPanel panel=new JPanel(); //新建面板
panel.setLayout(new BorderLayout()); //設置面板風格為BorderLayout
panel.add(inputFIEld,BorderLayout.NORTH); //放置控件
panel.add(outputArea,BorderLayout.CENTER);
setTitle("Java通訊客戶端");
setContentPane(panel);
}
}
二、 客戶端通訊類clIEntAgent
新建一個自定義包clientAgent,包含類clIEntAgent,該類用來執行和服務器端的交互,將界面和通訊類分開可以使程序的調試和維護更為容易。clIEntAgent類的作用包括:
1、在建構函數中建立和服務器的連接。
2、sendRequest()方法向服務器發送數據。
3、getResponse()方法從服務器端獲得回應
1、 成員變量
clIEntAgent類的成員變量包括:
PrintStream ops; //輸出流(指向服務器)
DataInputStream ips;//輸入流(來自服務器)
String cltRequest;//客戶端請求
String svrResponse;//服務器端回應
2、 建構函數clIEntAgent(String serverName,int port)包含兩個參數,接收從JavaClIEnt的main()函數中傳遞來的服務器名稱和端口號
public clIEntAgent(String serverName,int port)
{
try
{
Socket clIEntSocket=new Socket(serverName,port ); //根據服務器名和端口號建立Socket
ops=new PrintStream(clIEntSocket.getOutputStream());//獲得Socket的輸出流
ips=new DataInputStream(clIEntSocket.getInputStream());//獲得Socket的輸入流
}
catch(Exception e)
{
System.out.println("無法連接服務器!");
}
}
3、 sendRequest()方法
public void sendRequest(String request)
{
ops.println(request); //向Socket的輸出流寫入字符串
}
4、 getRespone()方法
public String getResponse()
{
String str=new String();
try
{
str=ips.readLine(); //從Socket的輸入流讀入字符串
}
catch(IOException e){} //必須捕獲錯誤
return str;
}
三、 客戶端JavaClIEnt類的main()函數和事件處理
1、 main()函數
有了上面的鋪墊,main()函數變得非常簡潔
public static void main(String[] args)
{
javaClIEnt frame=new JavaClIEnt();
frame.pack();//注意JavaClIEnt是JFrame的派生類,調用基類方法
frame.setVisible(true);
ca=new clIEntAgent("127.0.0.1",1001); //傳遞服務器名稱和端口號
}
2、 捕獲並處理單擊"發送"按鈕的事件
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==sendButton) //判斷事件源控件是否是"發送"按鈕
{
ca.sendRequest(inputFIEld.getText()); //發送文本框中的文本
outputArea.append("\n"+ca.getResponse()); //接收服務器回應並寫入文本域
}
}
四、 服務器端
1、 serverAgent類
1) 成員變量
ServerSocket svrSkt=null;
Socket cltSkt=null;
DataInputStream input=null; //輸入流,來自客戶端
PrintStream output=null; //輸出流,指向客戶端
2) serverAgent()建構函數
public serverAgent(int port) //main()函數傳遞監聽端口號
{
System.out.println("服務器代理正在監聽,端口:"+port);
try
{
svrSkt=new ServerSocket(port); //開始監聽
}catch(IOException e){System.out.println("監聽端口"+port+"失敗");}
try
{
cltSkt=svrSkt.accept(); //接收連接請求
}
catch(IOException e){System.out.println("連接失敗");}
try
{
input=new DataInputStream(cltSkt.getInputStream()); //獲得輸入流
output=new PrintStream(cltSkt.getOutputStream()); //獲得輸出流
}
catch(IOException e){}
output.println("歡迎......");
}
3) getRequest()方法讀取客戶端發送的數據
public String getRequest()
{
String frmClt=null;
try
{
frmClt=input.readLine();
}
catch(Exception e){
System.out.println("無法讀取端口.....");
System.exit(0);
}
return frmClt;
}
4) sendResponse()方法向客戶端發送數據
public void sendResponse(String response)
{
try
{
output.println(response);
}
catch(Exception e){
System.out.println("寫端口失敗......");
System.exit(0);
}
}
2、main()函數
在main()函數中對客戶端發送的不同請求進行不同的處理,本例只是介紹原理,因此服務器端只是簡單地將客戶端發送來的數據發送回去:
public static void main(String[] args) throws IOException
{
serverAgent sa=new serverAgent(1001);
while(true)
{
sa.sendResponse(sa.getRequest());
}
}