Socket(套接字)
使用Socket編程實現數據的交互需要經歷以下幾個步驟:
1、創建Socket:
Socket socket = new Socket("host",port);
2、打開IO流
PrintWriter out = new PrintWriter(socket.getOutputStream(),true);//輸出流
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()))//輸入流
注: socket屬於服務器,那么socket的方法getOutputStream就是向客戶端輸出數據,getInputStream獲取客戶端傳過來的數據
3、進行數據的交互
out.print() in.read();
4、關閉Socket
socket.close();
服務端跟客戶端有所不同,客戶端只要創建socket並且請求服務器連接connect,服務器創建完socket使用ServerSocket.accept()方法
阻塞程序直到收到了來自客戶端的請求,接收到來自客戶端的socket繼續往下執行。
其中客戶端代碼如下:
import java.net.*;
import java.io.*;
public class Client
{
boolean flag = false;//當遇到客戶端輸入bye取消與服務端連接的標識
public Client(){
try{
Socket socket =new Socket("127.0.0.1",4800);//(host,port)
System.out.println("客戶端已經開啟----");
new Thread(new Output(socket)).start();
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));//獲取來自服務端的信息
String str = in.readLine();//讀取信息
while(!str.equals("bye")) {
System.out.println("服務端:"+str);
str = in.readLine();//當in每次調用readLine方法就會往下讀取一行,慎用
}
in.close();
if (flag==true){
socket.close();
}
}
catch(Exception e){
e.printStackTrace();
}
}
//當客戶端沒有寫入信息的時候需要寫一個線程來實現寫操作,不然程序就會被卡在readLine一直獲取鍵盤信息
class Output implements Runnable{
Socket socket;
public Output(Socket socket){
this.socket = socket;
}
public void run(){
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
try {
PrintWriter out = new PrintWriter(socket.getOutputStream(),true);
String str = br.readLine();
while(!str.equals("bye")) {
System.out.println("客戶端:"+str);
out.print(str+"\n");//從鍵盤沒有獲取到回車按鍵,需要加\n判斷一次輸入為一行
out.flush();
str = br.readLine();
if (str.equals("bye")) {
flag = true;
}
}
br.close();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args)
{
new Client();
}
}
服務端代碼如下:
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
boolean flag = false;
public Server(){
try {
ServerSocket serverSocket = new ServerSocket(4800);
System.out.println("服務端正在等待客戶端請求......");
Socket socket = serverSocket.accept();//一直等待客戶端的請求
System.out.println("connect success");
new Thread(new Output(socket)).start();
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
/* int i = 0;
while ((i = in.read()) != 0){
System.out.println(i);
}*/
String str = in.readLine();
while(!str.equals("bye")) {
System.out.println("客戶端:" + str);
str = in.readLine();
}
in.close();
if (flag==true) {
socket.close();
serverSocket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
class Output implements Runnable{
Socket socket;
public Output(Socket socket){
this.socket = socket;
}
public void run(){
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
try {
PrintWriter out = new PrintWriter(socket.getOutputStream(),true);
String str = br.readLine();
while(!str.equals("bye")) {
System.out.println("服務端:"+str);
out.print(str+"\n");
out.flush();
str = br.readLine();
if (str.equals("bye")) {
flag = true;
}
}
br.close();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
new Server();
}
}
總結
今天使用socket來實現客戶端與服務端的通信功能,遇到了很多問題,其中一個比較嚴重的就是沒有將寫操作放入線程中進行,導致程序沒有輸出信息,第二個問題是當獲取到從客戶端/服務端來的信息時候,我是一行行的進行讀取,但是沒有讀取到回車按鍵,無法區分一行的信息,導致客戶端輸入的信息,服務端無法接收,在朋友的debug下,使用了以下這個方法調試是否有數據傳到另一邊:
int i = 0;
while ((i = in.read()) != 0){
System.out.println(i);
使用BufferReader的read方法返回的ASCII碼,強轉為int 可以直接獲取原來的值(在ASCII范圍內的值)。
