Socket编程实现客户端与服务器一对一聊天

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+"
");//从键盘没有获取到回车按键,需要加
判断一次输入为一行
                    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+"
");
                   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范围内的值)。

原文地址:https://www.cnblogs.com/shigeng/p/8076263.html