Socket 的基本概念
1、Socket,也就是俗稱的通訊端。
2、Sun Java中的定義:是運行在網路上的兩個程式間雙向通訊串連的末端,它提供用戶端和伺服器端的串連通道。Socket綁定於特定連接埠這樣TCP層就知道將資料提供給哪個應用程式。
3、字面上的理解,Socket的意思是"插座、孔",你還可以把它形象地理解為打電話用的電話機,你從耳機裡聽到對方聲音,同時將聲音通過話筒傳給對方。
Socket編程實現原理
從串連的建立到串連的結束,每個Socket應用都大致包含以下幾個基本步驟:
1、伺服器端socket綁定於特定連接埠,伺服器偵聽socket等待串連請求;
2、用戶端向伺服器和特定連接埠提交串連請求;
3、伺服器接受串連,產生一新的socket,綁定到另一連接埠,由此socket來處理和用戶端的互動,伺服器繼續偵聽原socket來接受其他用戶端的串連請求;
4、串連成功後用戶端也產生一socket,並通過它來與伺服器端通訊(注意:用戶端socket並不與特定連接埠綁定);
5、接下來,伺服器端和用戶端就通過讀取和寫入各自的socket來進行通訊。
Java中的Socket類
Java中提供兩個類(在java.net包中)――Socket和ServerSocket來分別實現用戶端和伺服器端Socket。但Socket的實際工作是由抽象類別SocketImpl的執行個體來完成的,這其實是設計模式中Abstract Factory模式的一個應用。
ServerSocket類的常用構造器和主要方法:
ServerSocket(int port) 在指定的連接埠號碼上產生一伺服器端socket
Socket accept()
偵聽socket,接受串連
Socket類的常見構造器和主要方法:
Socket(String host, int port) 產生一socket並串連至指定的主機和連接埠
InputStream getInputStream() 返回socket的輸入資料流
OutputStream getOuputStream() 返回socket的輸出資料流
一個客戶服務器執行個體
在這個例子中,我們模仿了一個Echo服務,它偵聽3333連接埠。用戶端接受使用者鍵盤輸入並向伺服器端發出串連請求,伺服器端接受用戶端串連,串連成功後建立會話,用戶端於是向伺服器端發送使用者輸入資訊,伺服器端接收此資訊並且簡單返回給用戶端。源碼如下:
(伺服器端)
/**
* <p>Title:EchoServer.java </p>
* <p>Description: EchoServer create a echo-like server at port 3333</p>
* @author Mac
* @version 2002/9/2
*/
import java.net.*;
import java.io.*;
public class EchoServer
{
public static void main (String[] args) throws IOException
{
ServerSocket echoServer = null;
try
{
echoServer = new ServerSocket(3333); //creat a server socket at port
3333(問題一)
}
catch(IOException e)
{
System.err.println("Couldn't listen on port:3333");
System.exit(-1);
}
Socket echoClient = null;
try
{
echoClient = echoServer.accept(); //accept a connection
}
catch(IOException e)
{
System.err.println("IO error:" + e.getMessage());
System.exit(-1);
}
PrintWriter out = new PrintWriter(echoClient.getOutputStream(),true);
//gets the socket's output stream and opens a PrintWriter on it
//if you remove the argument true,what will happen?(問題三)
BufferedReader in = new BufferedReader(
new InputStreamReader(echoClient.getInputStream()));
//gets the socket's input stream and opens a BufferedReader on it
String strFromClient;
while((strFromClient = in.readLine()) != null)
{
out.println("result is :" + strFromClient);
}
in.close();
out.close();
echoClient.close();
echoServer.close();
}
}
(用戶端)
/**
*<p>Title:EchoClient.java </p>
*<p>Description: EchoClient creates a socket thereby getting a connection to
echo-like server</p>
* @author Mac Wang
* @version 2002/8/30
*/
import java.net.*;
public class EchoClient
{
public static void main(String[] args)
{
try
{
Socket echoClient = new Socket("yourhostname",3333);
//creat a new socket connected to host and port 3333
PrintWriter out = new PrintWriter(echoClient.getOutputStream(),true);
BufferedReader in = new BufferedReader(
new InputStreamReader(echoClient.getInputStream()));
String fromServer,fromUser;
BufferedReader stdIn = new BufferedReader(
new InputStreamReader(System.in));
//gets the system input stream and opens a BufferedReader on it
while ((fromUser = stdIn.readLine()) != null)
{
if (fromUser.equals("bye")) break;
//when user types "bye" then end
System.out.println("input is:" + fromUser);
out.println(fromUser);
fromServer = in.readLine();
System.out.println(fromServer);
}
out.close();
in.close();
echoClient.close();
}
catch(UnknownHostException e)
{
System.err.println("Unknown host:yourhostname");
System.exit(1);
}
catch(IOException e)
{
System.err.println("I/0 error:" + e.getMessage());
System.exit(1);
}
}
}
思考以下幾個問題:
1、把連接埠號碼換成2222後看看程式運行效果?那麼89呢?是不是任何數字都可以呢?
2、如果不採用我們自己編寫的echo server,而是串連到系統本身提供的echo server(連接埠號碼為7),試試看會發生什麼情況,用戶端Socket是否需要改變呢?
3、去掉PrintWriter中的參數True,看看程式啟動並執行效果?
4、注意程式中是如何讀取和寫入Socket的?
5、試著多開啟幾個用戶端,看看效果如何?