1. 程式人生 > >Socket編程實現客戶端與服務器一對一聊天

Socket編程實現客戶端與服務器一對一聊天

bug servers sys 編程 獲取 post edr class 一個

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範圍內的值)。

Socket編程實現客戶端與服務器一對一聊天