一、工作方式
1.服務器應用程序對特定端口創建出ServerSocket
ServerSocket serverSock = new ServerSocket(4242);//這回讓服務器應用程序開始監聽來自4242端口客戶端的請求
2.客戶端對服務器應用程序建立Socket連接
Socket sock = new Socket("190.168.1.1",4242)//客戶端得知道IP地址與端口號
3.服務器創建出與客戶端通信的新Socket
Socket sock = serverSock.accept();//accept()方法會在等待用戶的Socket連接時閒置着。監聽並接受到此套接字的連接。此方法在連接傳入之前一直阻塞。當用戶連上來時,此方法返回一個Socket(在不同的端口上)以便於客戶端通信。Socket與ServerSocket的端口號不相同,因此ServerSocket可以空出來等待其他的用戶。
二、
下面是一個簡單的通信過程,服務端Myserver,當一次通話連接上時產生一個新的線程,與客戶端進行通話,這裏面便通過多線程實現了通話的同步,可以有多個客戶端連上服務端,基本上上可以同時實現通信。
public class Myserver {
public static ServerSocket myserver;
public static void main(String[] args) {
try {
myserver = new ServerSocket(2222);
while (true) {
Socket socket = myserver.accept();
Thread t = new Thread(new ThreadSocket(socket));
t.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
服務端線程:
public class ThreadSocket implements Runnable {
private Socket socket;
ThreadSocket(Socket socket) {
this.socket = socket;
}
public void run() {
try {
// 取得連接socket上低層輸入串流的inputStreamReader,並用BufferedReader讀取
BufferedReader in = new BufferedReader(new InputStreamReader(socket
.getInputStream()));
// 向串口輸出流
PrintWriter out = new PrintWriter(socket.getOutputStream());
while (true) {
String str = in.readLine();
System.out.println("your input is :" + str);
out.println("has receive...");
out.flush();
if (str.equals("end"))
break;
}
in.close();
out.close();
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
服務端接收客服端的輸出,收到後打印出,然後發送"has receive..."回客戶端。若從客戶端接收到“end”,關閉輸入輸出流與通話。
public class Myclient {
public Myclient() throws UnknownHostException, IOException {
Socket client = new Socket(InetAddress.getLocalHost(), 2222);
PrintWriter out = new PrintWriter(client.getOutputStream());
// 客戶端從鍵盤輸入信息
BufferedReader in1 = new BufferedReader(
new InputStreamReader(System.in));
// 客戶端建立輸入流並進行封裝
BufferedReader in2 = new BufferedReader(new InputStreamReader(client
.getInputStream()));
while (true) {
String str1 = in1.readLine();
out.write(str1+"\r\n");
out.flush();
if(str1.equals("end"))
break;
System.out.println(str1);
String str2 = in2.readLine();
System.out.println("str2:"+str2);
}
in1.close();
in2.close();
out.close();
client.close();
}
public static void main(String[] args) throws UnknownHostException,
IOException {
new Myclient();
}
}
注意客戶端有2個輸入端,一口監聽鍵盤輸入,一口監聽socket輸入(即服務端的輸出),將鍵盤輸入發送出去,同時若鍵盤輸入"end",同樣,關閉各流及連接。
注意:out.write(str1+"\r\n");在發送字符後加上"\r\n",因爲我們讀取的時候常用,readLine(),即從緩衝區中讀取字符,知道遇到"\r"或"\n"爲止,不加上的話接收方不能很好的讀到,可能就會卡住。當然out.write(str1+"\r\n")也可以寫作out.println(str1).
輸出:
當我們在鍵盤上輸入:Forza inter!
客戶端控制檯:
Forza Inter!
str2:has receive...
服務端控制檯:
your input is :Forza Inter!
三、
現在通過多線程可以實現多人同時通話,不斷的連接,不斷的產生新的通話,新的線程。如果是一個大型的或者要求較高的實現可能會要求我們控制同時連接的通話數量。那樣的話我們就可以通過建立線程池的方法來自動管理。