?? java語言的socket編程.txt
字號:
Java語言的Socket編程
(加入日期:2001-8-23 點擊數(shù):1586)
【對此文發(fā)表評論】 【編程愛好者論壇】 【保存文章至硬盤】 【打印文章】
徐迎曉 (上海大學(xué)計算中心25#) xyx@yc.shu.edu.cn
摘 要:本文介紹了Java語言的Socket編程,包括服務(wù)端和客戶端的編程方法,并提供了若干實例。
關(guān)鍵詞:Java, Socket, Server, Client, Internet
一、什么是Socket
Socket 接口是訪問 Internet 使用得最廣泛的方法。 如果你有一臺剛配好TCP/IP協(xié)議的主機,其IP地址是202.120.127.201, 此時在另一臺主機或同一臺主機上執(zhí)行ftp 202.120.127.201,顯然無法建立連接。因為“202.120.127.201”
這臺主機沒有運行FTP服務(wù)軟件。同樣, 在另一臺或同一臺主機上運行瀏覽軟件如Netscape,輸入“http://202.120.127.201”,也無法建立連接。現(xiàn)在,如果在這臺主機上運行一個FTP服務(wù)軟件(該軟件將打開一個Socket,并將其綁定到21端口),再在這臺主機上運行一個Web 服務(wù)軟件(該軟件將打開另一個Socket,并將其綁定到80端口)。這樣,在另一臺主機或同一臺主機上執(zhí)行ftp 202.120.127.201,F(xiàn)TP客戶軟件將通過21端口來呼叫主機上由FTP 服務(wù)軟件提供的Socket,與其建立連接并對話。而在netscape中輸入“http://202.120.127.201”時,將通過80端口來呼叫主機上由Web服務(wù)軟件提供的Socket,與其建立連接并對話。
在Internet上有很多這樣的主機,這些主機一般運行了多個服務(wù)軟件,同時提供幾種服務(wù)。每種服務(wù)都打開一個Socket,并綁定到一個端口上,不同的端口對應(yīng)于不同的服務(wù)。Socket正如其英文原意那樣,象一個多孔插座。一臺主機猶如布滿各種插座的房間,每個插座有一個編號,有的插座提供220伏交流電, 有的提供110伏交流電,有的則提供有線電視節(jié)目。 客戶軟件將插頭插到不同編號的插座,就可以得到不同的服務(wù)。
在Java語言中,提供了相應(yīng)的Socket編程方法。用Java既可以編寫服務(wù)端的程序,又可以編寫客戶端的程序。
二、編寫服務(wù)端的程序
Java中的ServerSocket類提供了服務(wù)端的Socket接口。為了使大家對編寫服務(wù)端程序有一個感性的認(rèn)識,這里提供一個模擬FTP服務(wù)器的服務(wù)軟件。 為了簡潔起見,該程序只提供了最簡單的建立FTP連接的功能。
該程序如下:
import java.io.*;
import java.net.*;
public class ftpserver{
public static void main(String args[])
{ try{ ServerSocket ftpserver = new ServerSocket(21);
Socket fs=ftpserver.accept();
PrintStream fs_out=new PrintStream(fs.getOutputStream());
DataInputStream fs_in=new DataInputStream(fs.getInputStream());
fs_out.println("Welcome to the test server");
System.out.println("got follow infor from client:"+fs_in.readLine());
fs_out.println("331 Please send Password");
System.out.println("got follow infor from client:"+fs_in.readLine());
fs_out.println("230 Login OK");
System.out.println("got follow infor from client:"+fs_in.readLine());
}
catch(Exception e)
{ System.out.println(e);
}
}
}
為了測試該程序,可以在一臺安裝了Windows 95并配置了TCP/IP協(xié)議的微機上進(jìn)行(不一定要連入Internet)。在該微機上安裝Java編譯軟件如JDK1.01 或JDK1.02(可在ftp://ftp.javasoft.com/pub/JDK-102-win32-x86.exe 下載),將上述程序存入文件ftpserver.java,執(zhí)行“javac ftpserver.java”將其編譯為字節(jié)碼文件ftpserver.class。這樣,只要在該微機上執(zhí)行“java ftpserver.class”以運行該Java程序,該微機便成為一個模擬的FTP服務(wù)器。
測試該模擬FTP服務(wù)器,既可以在另一臺聯(lián)網(wǎng)的微機上進(jìn)行, 也可以直接在該模擬FTP服務(wù)器上另開一個DOS窗口進(jìn)行。運行命令行形式的FTP客戶軟件, 如在Windows 95的DOS窗口執(zhí)行:ftp 202.120.127.201(如果你的Windows 95中配置TCP/IP協(xié)議時用的IP地址是其他值,需將這里的“202.120.127.201 ”改為相應(yīng)的值),便可以進(jìn)行對話。下圖是對話過程,其中帶下劃線的部分為用戶的輸入。
客戶端
C:\xyx\java\sock\bak\ftp>ftp 202.120.127.201
Connected to 202.120.127.201.
Welcome to the test server
User (202.120.127.201:(none)): anonymous
331 Please send Password
Password:xyx@yc.shu.edu.cn
230 Login OK
ftp> bye
模擬FTP服務(wù)器
C:\xyx\java\sock\bak\ftp>java ftpserver
got follow infor from client:USER anonymous
got follow infor from client:PASS xyx@yc.shu.edu.cn
got follow infor from client:QUIT
下面我們來看一看該模擬FTP服務(wù)器的編程方法。在上面的程序中, 關(guān)鍵部分是下面四句:
1. ServerSocket ftpserver = new ServerSocket(21);
2. Socket fs=ftpserver.accept();
3. PrintStream fs_out=new PrintStream(fs.getOutputStream());
4. DataInputStream fs_in=new DataInputStream(fs.getInputStream());
其中,第一句創(chuàng)建了一個服務(wù)端的Socket,并將其綁定到21端口。這樣,服務(wù)端的Socket將一直等待客戶端建立連接。這里的21端口是FTP服務(wù)慣用的端口,你也可以使用其他端口來提供自己的服務(wù)。第二句利用Java提供的方法accept()接收客戶端的連接。第三句和第四句則為分別建立的連接打開一個輸出和輸入流。這四句可以作為編寫服務(wù)端程序的一個范式,接下去的操作就是按照約定的協(xié)議對輸出和輸入流進(jìn)行讀寫操作了。
在上面的程序中,對輸出流fs_out用方法println("...")向客戶端發(fā)送字符串,對輸入流fs_in用方法readLine()獲得客戶端向服務(wù)端發(fā)送的字符串, 并用System.out.println("...")在服務(wù)器上顯示出來。
向客戶端發(fā)送信息和讀取客戶端發(fā)送來的信息必須按協(xié)議約定進(jìn)行,這樣,服務(wù)端和客戶端之間才能順利通訊。在上面的程序中,信息發(fā)送順序是這樣的:
1. 客戶端連接后,服務(wù)端向客戶端發(fā)送歡迎信息。這由程序中如下一行完成:
fs_out.println("Welcome to the test server");
2. 客戶端顯示服務(wù)端發(fā)送的信息,并提示用戶輸入帳號, 發(fā)送給服務(wù)端。在本例中,這由FTP客戶軟件完成。
3. 服務(wù)端接收客戶端提供的帳號,向客戶端發(fā)送結(jié)果碼331,并提示需要口令。這由程序中如下兩行完成::
System.out.println("got follow infor from client:"+fs_in.readLine());
fs_out.println("331 Please send Password");
4. 客戶端提示用戶輸入口令,并將口令發(fā)送給服務(wù)端。在本例中,這由FTP客戶軟件完成。
5. 服務(wù)端接收客戶端提供的口令,向客戶端發(fā)送結(jié)果碼230,并提示注冊成功。讀取客戶端發(fā)送命令。這由程序中如下兩行完成:
fs_out.println("230 Login OK");
System.out.println("got follow infor from client:"+fs_in.readLine());
從以上我們可以看出客戶端和服務(wù)端對話的簡單過程,在這里,我們省略了服務(wù)端對用戶及口令的檢驗以及根據(jù)客戶端輸入的不同命令執(zhí)行各種操作。事實上,在上面的例子中既可以看到服務(wù)端如何向客戶端發(fā)送信息,又可以看到服務(wù)端如何接收客戶端的信息。因此,只要搞清楚雙方對話的協(xié)議,便不難作出相應(yīng)的編程。
三、編寫客戶端的程序
在上面的程序中,我們借用了Windows 95本身提供的FTP 客戶軟件來測試我們的模擬FTP服務(wù)程序。現(xiàn)在,我們要自己編寫一個客戶端的程序。 我們先編寫一個簡單的服務(wù)端程序和客戶端程序,以理解服務(wù)端與客戶端的通訊及其編程。
為簡明起見, 我們使用一個自己定義的簡單協(xié)議:服務(wù)器使用一個空閑的端口8886,客戶端連接后:1. 服務(wù)端向客戶端發(fā)送一個信息;2. 客戶端讀取服務(wù)端的信息并顯示,再向服務(wù)端發(fā)送一個反饋信息;3.服務(wù)端讀取客戶端的反饋信息并顯示。
對應(yīng)于此協(xié)議,服務(wù)端的程序可如下:
import java.io.*;
import java.net.*;
public class server{
public static void main(String args[])
{ try { Server Socket server_1 = new Server Socket(8886);
Socket socket_s=server_1.accept();
Print Stream server_out=new Print Stream(socket_s.get Output Stream());
Data Input Stream server_in=new Data Input Stream(socket_s. getInputStream());
server_out.println("This is infor sent by server \r");
String s1=server_in.readLine();
System.out.println("Got follow infor from client:"+s1);
}
catch(Exception e)
{ System.out.println(e);
}
}
}
該例子與前面的模擬FTP服務(wù)器類似,不同的只是服務(wù)提供方使用的是 8886端口,此外由于使用的協(xié)議不同,對輸入和輸出流的操作不同。相應(yīng)的客戶端程序可如下:
import java.io.*;
import java.net.*;
public class client {
public static void main(String args[])
{ try
{ Socket sock_1 = new Socket("202.120.127.201", 8886);
DataInputStream client_in = new DataInputStream(sock_1.getInputStream());
DataOutputStream cl_out= new DataOutputStream(sock_1.getOutputStream());
PrintStream client_out=new PrintStream(cl_out);
String s1=client_in.readLine();
System.out.println("Got follow infor from server:"+s1);
client_out.println("This is infor sent by client \r");
}
catch(Exception e)
{ System.out.println(e);
}
}
}
這是一個簡單的客戶端程序的例子,其關(guān)鍵部分是下面四句:
1. Socket sock_1 = new Socket("202.120.127.201", 8886);
2. DataInputStream client_in = new DataInputStream(sock_1.getInputStream());
3. DataOutputStream cl_out= new DataOutputStream(sock_1.getOutputStream());
4. PrintStream client_out=new PrintStream(cl_out);
其中,第一句創(chuàng)建了一個客戶端的Socket,從而與202.120.127.201主機建立一個連接。其中的8886為端口號,與服務(wù)端的Socket所綁定到的端口號相對應(yīng)。第二至四句為Socket創(chuàng)建輸入和輸出流。這四句可以作為編寫客戶端程序的一個范式。接下去的操作同樣是按照約定的協(xié)議對輸出和輸入流進(jìn)行操作。上一程序中同樣對輸入流client_in用方法readLine()讀取服務(wù)端發(fā)送的字符串,對輸出流client_out用方法println("...")向服務(wù)端發(fā)送字符串。
上面兩個程序編譯后執(zhí)行效果如下:
客戶端
C:\xyx\java\sock\bak\c-both-s>java client
Got follow infor from server:This is infor sent by server
服務(wù)端
C:\xyx\java\sock\bak\c-both-s>java server
Got follow infor from client:This is infor sent by client
測試時既可以在同一臺微機上開兩個DOS窗口,也可以在兩臺聯(lián)網(wǎng)的微機上進(jìn)行。在上面的程序基礎(chǔ)上,我們可以為前面的模擬FTP服務(wù)程序編寫一個客戶端程序:
import java.io.*;
import java.net.*;
public class ftpc {
public static void main(String[] args)
{ try {
Socket sock_1 = new Socket("202.120.127.201", 21);
DataInputStream client_in = new DataInputStream(sock_1.getInputStream());
DataOutputStream cl_out= new DataOutputStream(sock_1.getOutputStream());
PrintStream client_out=new PrintStream(cl_out);
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -