java中Socket编程

TCP

  1. 面向连接 和打电话一样,必须要建立通信。
  2. 可靠性 不会丢失文件。
  3. 顺序,无差错。

Socket

套接字
网络上的两个程序通过一个双向的通讯连接实现数据的交换,这个双向链路的一端称为一个

Socket

一个Socket由一个IP地址和一个端口号唯一确定。
cmd netstat -ano

IP

确定唯一的一台电脑地址

端口

确定电脑上唯一的应用程序
0~1023被系统保留。
1024-65535 每个端口只允许一个程序访问。

代码步骤

1. 服务端 创建ServerSocketServerSocket只用来等待客户端连接,不能通过他进行交互。
2. 等待客户端链接
Socket socket = ServerSocket.accept();等待客户端连接,返回一个Socket实例
3. 客户端通过Sockek进行连接Socket socket = new Socket(host,port);
4. 通过两边的socket获取流进行输入输出。
注意
1. 程序开过一次后,会占用端口,注意关闭程序,否则不能运行第二次。
2. 每个阻塞式方法都必须存在一条新线程中,否则阻塞后其他方法无法执行,如等待客
户端连接 accept() , 键盘输入 input.next() ,读数据while((len=is.read(buf))!=-1) 等操作都会阻塞。
3. 启动新线程一般放在最上面,不能放在阻塞式方法的后面,否则执行不了,或者出现问题

//服务端
public class Server2 extends Thread {

    // 能同时连接多台电脑
    ServerSocket server;
    List list = new ArrayList<>();

    public Server2() {
        try {
            server = new ServerSocket(8888);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        super.run();
        while (true) {
            try {
                // 每次循环到这里 都会再次等待客户端连接
                Socket socket = server.accept();
                // 添加所有链接的用户
                System.out.println(socket.getInetAddress().getHostAddress()
                        + "连上了");
                sendMessageToAllPC(socket.getInetAddress().getHostAddress()
                        + "上线了");
                list.add(socket);
                new ReaderThread(socket).start();
                // 开个线程
            } catch (IOException e) {
            }
        }

    }

    // 写的方法
    public void sendMessageToAllPC(String msg) {
        for (Socket socket : list) {
            if (socket != null && socket.isConnected()) {
                OutputStream os;
                try {
                    os = socket.getOutputStream();
                    os.write(msg.getBytes());
                    os.flush();
                    // 千万不要关
                } catch (IOException e) {
                }
            }
        }
    }

    // 专用读的线程
    class ReaderThread extends Thread {
        InputStream is;

        public ReaderThread(Socket socket) {
            try {
                is = socket.getInputStream();
            } catch (IOException e) {
            }
        }

        // 只做读操作
        @Override
        public void run() {
            // 读了你的消息,转发给其他所有用户
            byte[] buf = new byte[1024];
            int len = 0;
            try {
                while ((len = is.read(buf)) != -1) {
                    sendMessageToAllPC(new String(buf, 0, len));
                }
            } catch (IOException e) {
            }
        }
    }
}



//客户端

public class Client2 extends Thread {

    Socket socket;
    String name;

    public Client2(String name) {
        this.name = name;
        try {
            socket = new Socket("192.168.18.250", 8888);
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    @Override
    public void run() {
        // 读线程
        new ReaderThread().start();
        // 写操作
        try {
            Scanner input = new Scanner(System.in);
            String speak = null;
            // 写的流
            OutputStream os = socket.getOutputStream();
            do {
                speak = input.next();
                os.write((name + ":" + speak).getBytes());
                os.flush();
            } while (!speak.equals("bye"));
            input.close();

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

    class ReaderThread extends Thread {
        @Override
        public void run() {
            try {
                InputStream is = socket.getInputStream();
                int len = 0;
                byte[] buf = new byte[1024];
                while ((len = is.read(buf)) != -1) {
                    System.out.println(new String(buf, 0, len));
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }

    }

}


UDP

  1. 面向无连接,没有服务端与客户端,和发短信一样,分为发送方和接收方。
  2. UDP有大小限制,每个数据报只有64KB大小,报文。
  3. 不可靠协议,数据不一定会到达,也不一定是按顺序到达。

广播

广播地址是192.168.*.255
发送步骤

 // 1.建立发送的主机地址
SocketAddress address = new InetSocketAddress(host, port);
// 2.建立数据报
// 长度一定要注意 转字节获取长度
 DatagramPacket dp = new DatagramPacket(msg.getBytes(),
msg.getBytes().length, address);
 // 2. 发送数据报
 socket.send(dp);
public class UDPUtils extends Thread {

    // 收发数据
    // 端口号
    DatagramSocket socket;

    public UDPUtils(int port) {
        // 我在本机器上,监听该端口
        try {
            socket = new DatagramSocket(port);
        } catch (SocketException e) {
            e.printStackTrace();
        }
    }

    // 发送数据报
    // 1. 对方端口
    // 2. 对方ip地址
    // 3. 数据
    public void sendMessage(String host, int port, String msg)
            throws IOException {
        // 1.建立发送的主机地址
        SocketAddress address = new InetSocketAddress(host, port);
        // 2.建立数据报
        // 长度一定要注意 转字节获取长度
        DatagramPacket dp = new DatagramPacket(msg.getBytes(),
                msg.getBytes().length, address);
        // 2. 发送数据报
        socket.send(dp);
    }

    // 收报
    @Override
    public void run() {
        // 一个包 如果缓冲区不够,就丢失了
        byte[] buf = new byte[65535];
        DatagramPacket packet = new DatagramPacket(buf, buf.length);
        while (true) {
            try {
                // 阻塞式
                socket.receive(packet);
                // 收到了数据报
                // 拆包
                String msg = new String(packet.getData(), 0, packet.getLength());
                System.out.println(msg);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}


//mian方法类

public class Test {

    /**
     * TCP 协议 Socket 用来连接 ServerSocket 服务端 用来监听客户端连接 accept() 阻塞并等待客户端的链接
     * 
     * 通过Socket的getInputStream和getOutputStream来获取流进行通信
     * 
     * 
     * Tcp特点 保持连接状态 不会丢失数据 并且数据顺序到达
     * 
     * 
     * @param args
     */

    public static void main(String[] args) {
        UDPUtils utils = new UDPUtils(7777);
        utils.start();
        Scanner input = new Scanner(System.in);
        int index = 0;
        while (index++ < 5) {
            String msg = input.next();
            // 发送给谁
            try {
                utils.sendMessage("192.168.18.255", 7777, msg);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        input.close();
    }

}

你可能感兴趣的:(基础编程,java函数,java语言)