网络编程——TCP Socket编程

java.lang.Object
|——java.net.Socket

和Datagramdsocket并没有继承关系

1、面向连接

请求——响应
Request——Response

2、Socket编程

服务器和客户端之间的双向管道就叫Socket,
一个连接对应一个Socket,站在服务器还是客户端都是对应这一条Socket
不同连接建立不同的Socket

1、 服务端 ServerSocket

先启动服务器再连接

  1. 创建服务器 指定端口 ServerSocket(int port) <1024以下留给系统使用>
  2. 接受客户端的连接 阻塞式 accept()
  3. 发送数据 接收数据
    new BufferedWriter(new OutputStreamReader(< Socket >.getOutputStream(……)))

2、客户端 Socket

  1. 创建客户端 必须指定服务端+端口 自己的端口是系统自动分配的 Socket
  2. 接受数据 getInputStream

多个客户端_聊天室原理

为每一个连接建立一个线程

聊天室:中转站

  1. 客户端可以发送数据 接受数据
  2. 服务端为每一个客户端创建一个线程

……

阶段一:
服务端

public class Server {
    public static void main(String[] args) throws IOException {
        ServerSocket server = new ServerSocket(8888);
        //阻塞接收消息
        Socket socket = server.accept();
        System.out.println("already builded");

        String msg = "welcome to use";
        BufferedWriter bw = new BufferedWriter(
                new OutputStreamWriter(
                        socket.getOutputStream()));
        bw.write(msg);
        bw.newLine();
        bw.flush();
    }
}

客户端

public static void main(String[] args) throws UnknownHostException, IOException {
        Socket client = new Socket("localhost",8888);

        BufferedReader br = new BufferedReader(
                new InputStreamReader(
                        client.getInputStream()));
        String echo = br.readLine();
        System.out.println(echo);
    }

阶段二:返回控制台输入的字符

服务端

public static void main(String[] args) throws UnknownHostException, IOException {
    ServerSocket server = new ServerSocket(7777);
    Socket client = server.accept();



    DataInputStream dis = new DataInputStream(client.getInputStream());
    String msg = dis.readUTF();
    System.out.println(msg);

    DataOutputStream dos = new DataOutputStream(client.getOutputStream());
    dos.writeUTF("server-->"+msg);
    dos.flush();

    server.close();
}

客户端

public static void main(String[] args) throws UnknownHostException, IOException {
    Socket client = new Socket("localhost",7777);

    BufferedReader console = new BufferedReader(new InputStreamReader(System.in));
    String info = console.readLine();

    DataOutputStream dos = new DataOutputStream(client.getOutputStream());
    dos.writeUTF(info);
    dos.flush();

    DataInputStream dis = new DataInputStream(client.getInputStream());
    String msg = dis.readUTF();
    System.out.println(msg);

    client.close();
}

阶段三:引入线程

CloseAll.java

public class CloseUtil {
    public static void closeAll(Closeable... io) {
        for(Closeable temp:io) {
            try {
                if(null!=temp) {
                    temp.close();
                }
            } catch (IOException e) {

            }
        }
    }
}

Send.java

public class Send implements Runnable{
    //控制台输入流
    private BufferedReader console;
    //管道输出流
    private DataOutputStream dos;
    //运行的标识
    private boolean isRunning = true;

    public Send() {
        console = new BufferedReader(new InputStreamReader(System.in));
    }

    public Send(Socket client) {
        this();
        try {
            dos = new DataOutputStream(client.getOutputStream());
        } catch (IOException e) {
            isRunning=false;
            CloseUtil.closeAll(dos, console);
        }
    }

    private String getMsgFromConsole() {
        try {
            return console.readLine();
        } catch (IOException e) {

        }
        return "";
    }

    public void send() {
        String msg = getMsgFromConsole();
        try {
            if(null!=msg && !msg.equals("")) {
                dos.writeUTF(msg);
                dos.flush();
            }
        } catch (IOException e) {
            isRunning =false;
            CloseUtil.closeAll(dos, console);
        }
    }

    @Override
    public void run() {
        //线程体
        while(isRunning) {
            send();
        }
    }
}

Receive.java

public class Receive implements Runnable{
    private DataInputStream dis;
    private boolean isRunning = true;
    public Receive() {

    }

    public Receive(Socket client) {
        try {
            dis= new DataInputStream(client.getInputStream());
        } catch (IOException e) {
            isRunning =false;
            CloseUtil.closeAll(dis);
        }
    }

    public String receive() {
        String msg="";
        try {
            msg = dis.readUTF();
        } catch (IOException e) {
            isRunning =false;
            CloseUtil.closeAll(dis);
        }
        return msg;
    }
    @Override
    public void run() {
        //线程体
        while(isRunning) {
            System.out.println(receive());
        }
    }
}

Client.java

public class Client {
    public static void main(String[] args) throws UnknownHostException, IOException {
        Socket client = new Socket("localhost",7777);

        new Thread(new Send(client)).start();
        new Thread(new Receive(client)).start();
    }
}

Server.java

public class Server {
    public static void main(String[] args) throws UnknownHostException, IOException {
        ServerSocket server = new ServerSocket(7777);
        Socket client = server.accept();
        DataInputStream dis = new DataInputStream(client.getInputStream());
        DataOutputStream dos = new DataOutputStream(client.getOutputStream());

        System.out.println("i get");

        while(true) {
            String msg = dis.readUTF();
            System.out.println(msg);

            dos.writeUTF("server-->"+msg);
            dos.flush();
        }
    }
}

阶段四:群聊

Server

public class Server {
       private List<MyChannel> all = new ArrayList<MyChannel>();
       /**
        * @param args
        * @throws IOException 
        */
       public static void main(String[] args) throws IOException {
              new Server().start();   

       }

       public void start() throws IOException{
              ServerSocket server =new ServerSocket(9999);
              while(true){
                     Socket client =server.accept();         
                     MyChannel channel = new MyChannel(client);
                     all.add(channel);//统一管理
                     new Thread(channel).start(); //一条道路
              }
       }


       /**
        * 一个客户端 一条道路
        * 1、输入流
        * 2、输出流
        * 3、接收数据
        * 4、发送数据
        * @author Administrator
        *
        */
       private class MyChannel implements Runnable{
              private DataInputStream dis ;
              private DataOutputStream dos ;
              private boolean isRunning =true;
              public MyChannel(Socket client ) {
                     try {
                            dis = new DataInputStream(client.getInputStream());
                            dos = new DataOutputStream(client.getOutputStream());
                     } catch (IOException e) {
                            //e.printStackTrace();
                            CloseUtil.closeAll(dis,dos);
                            isRunning =false;
                     }
              }
              /**
               * 读取数据
               * @return
               */
              private String receive(){
                     String msg ="";
                     try {
                            msg=dis.readUTF();
                     } catch (IOException e) {
                            //e.printStackTrace();
                            CloseUtil.closeAll(dis);
                            isRunning =false;
                            all.remove(this); //移除自身
                     }
                     return msg;
              }

              /**
               * 发送数据
               */
              private void send(String msg){
                     if(null==msg ||msg.equals("")){
                            return ;
                     }
                     try {
                            dos.writeUTF(msg);
                            dos.flush();
                     } catch (IOException e) {
                            //e.printStackTrace();
                            CloseUtil.closeAll(dos);
                            isRunning =false;
                            all.remove(this); //移除自身
                     }
              }

              /**
               * 发送给其他客户端
               */
              private void sendOthers(){
                     String msg = this.receive();
                     //遍历容器
                     for(MyChannel other:all){
                            if(other ==this){
                                   continue;
                            }
                            //发送其他客户端
                            other.send(msg);
                     }
              }


              @Override
              public void run() {
                     while(isRunning){
                            sendOthers();
                     }
              }
       }


}

猜你喜欢

转载自blog.csdn.net/jh_zhai/article/details/80253925