客户端与服务器2

package socket;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Arrays;
import java.util.Scanner;

/**

  • Copyright: Copyright © 2019

  • @ClassName: Servlet.java

  • @Description: 聊天室服务端

  • @Version: v1.0.0

  • @Author: Abelard

  • @Date: 2019年7月4日 下午2:05:28
    /
    public class Servlet {
    /

    • 运行在服务端的ServerSocket 主要有两个作用: 1.向系统申请服务端口,客户端就是通过这个端口与服务端建立链接
    • 2.监听该端口,这样客户端建立连接时,ServerSocket就会自动实例化一个socket 用于与该客户端进行数据交互

    /
    private ServerSocket server;
    /
    *

    • 用来存放所有客户端输出流的共享数组

    • 内部类可以访问外部类的属性,因此在Server上定义这样一个数组

    • 可以保存所有ClientHandler需要互访的输出流,做到他们之间共享数据使用
      /
      private PrintWriter[] allOut = {};
      /

    • 构造方法用于初始化服务端
      /
      public Servlet() {
      try {
      /

      * 实例化ServerSocket时传入打开的服务端口 如果该端口被其他程序使用,则实例化时会抛出异常
      */
      System.out.println(“正在启动服务器…”);
      server = new ServerSocket(8088);
      System.out.println(“服务器启动完毕”);

      } catch (Exception e) {
      e.printStackTrace();
      }
      }

    /*

    • 服务器开始工作
      */
      public void start() {

      try {
      /*
      * ServerSocket提供方法 Socket accept() 该方法是一个阻塞方法,调用后开始等待客户端
      * 连接,当一个客户端连接后该方法返回一个Socket实例 通过这个Socket实例可以与客户端交互
      *
      * 多次调用accept方法可以接收多个客户端连接
      */
      Socket socket;
      while (true) {
      System.out.println(“等待客户端连接…”);
      socket = server.accept();
      System.out.println(“客户端连接”);
      //启动一个线程来处理该用户端交互
      ClientHandler clientHandler = new ClientHandler(socket);
      Thread thread = new Thread(clientHandler);
      thread.start();
      }
      } catch (Exception e) {

       e.printStackTrace();
      

      }
      }

    public static void main(String[] args) {
    Servlet servlet = new Servlet();
    servlet.start();
    }
    //创建线程任务
    private class ClientHandler implements Runnable{
    private Socket socket;
    //获取远端计算机地址
    private String host;

     public ClientHandler(Socket socket) {
     	this.socket = socket;
     	InetAddress address = socket.getInetAddress();
     	host = address.getHostAddress();
     }
     
     @Override
     public void run() {
     	/*
     	 * 通过该输入流来读取到内容是远端计算机发送过来的数据
     	 */
     	try {
     		InputStream is = socket.getInputStream();
     		InputStreamReader isr = new InputStreamReader(is, "utf-8");
     		BufferedReader br = new BufferedReader(isr);
     		/**
     		 * 通过Socket获取输出流,用于将消息发送给当前的客户端
     		 * 
     		 */
     		OutputStream out = socket.getOutputStream();
     		OutputStreamWriter ow = new OutputStreamWriter(out);
     		BufferedWriter bw = new BufferedWriter(ow);
     		PrintWriter pw = new PrintWriter(bw,true);
     		/*
     		 * 将对应客户端的输出流存入到共享数组中以便于其他的clienthandler可以访问到
     		 * 
     		 */
     		
     		//1.对allout扩容
     		allOut = Arrays.copyOf(allOut, allOut.length+1);
     		
     			allOut[allOut.length-1] = pw;
     		
     		
     		
     		String line = null;
     		while ((line = br.readLine())!=null) {
     			/*
     			 * 接收客户端
     			 */
     			System.out.println(host+":" + line);
     			//将消息返回给所有客户端
     			for(int i=0;i<allOut.length;i++) {
     				allOut[i].println(line);
     			}
     			if(line.equals("exit")) {
     				System.out.println("程序结束");
     				break;
     			}	
     		}
     	}catch (IOException e) {
     		e.printStackTrace();
     	}
     }
    

    }
    }

客户端
package socket;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Scanner;

/**

  • Copyright: Copyright © 2019

  • @ClassName: Client.java

  • @Description: 聊天室客户端

  • @Version: v1.0.0

  • @Author: Abelard

  • @Date: 2019年7月4日 下午2:05:17
    /
    public class Client {
    /
    *

    • java.net.Socket套接字 封装了tcp协议的通讯细节,使得我们利用TCP通讯 以流的读写操作形式完成
    • 套接字:源IP地址和目的IP地址以及源端口号和目的端口号的组合称为套接字
      */
      private Socket socket;

    private String host;
    /*

    • 构造方法,用于初始化客户端
      /
      public Client() {
      try {
      /

      * 实例化Socket时需要传入两个参数: 1.服务端的地址 2.服务端打开的端口号
      * 这里实例化Socket的过程就是通过给定 地址链接服务端的过程,若链接不成功 构造方法会抛出异常 通过IP地址我们可以找到网络上服务端
      * 所在的机器,通过端口就可以找到运行在 服务端计算机上的服务端应用程序
      */
      System.out.println(“正在链接服务器…”);
      socket = new Socket(“localhost”, 8088);
      System.out.println(“已连接服务端”);

      } catch (Exception e) {
      e.printStackTrace();
      }
      }

    /*

    • 客户端开始工作方法
      */
      public void start() {
      try {
      InetAddress address = socket.getInetAddress();
      host = address.getHostAddress();

       OutputStream out = socket.getOutputStream();
       OutputStreamWriter osw = new OutputStreamWriter(out, "utf-8");
       BufferedWriter bw = new BufferedWriter(osw);
       PrintWriter pWriter = new PrintWriter(bw, true);
       Scanner scanner = new Scanner(System.in);
       /**
        * 通过socket流获取输入流,读取客户端发送过来的消息
        */
       InputStream is = socket.getInputStream();
       InputStreamReader isr = new InputStreamReader(is, "utf-8");
       BufferedReader br = new BufferedReader(isr);
       String line = null;
       while (true) {
       	/*
       	 * 跟服务端对话
       	 */
       	System.out.println("请输入你要对服务端说的话");
       	String seke = scanner.next();
       	pWriter.println(seke);
       	
       	line = br.readLine();
       	System.out.println(host+"说:"+line);
       }
      

      }catch (IOException e) {
      e.printStackTrace();
      }

    }

    public static void main(String[] args) {
    Client client = new Client();
    client.start();
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值