java——基于TCP协议的Socket编程:基于Socket通信的C/S应用:TCP单、多线程通讯模型 BIO + UDP协议的Socket编程

IP地址:

java——基于TCP协议的Socket编程:基于Socket通信的C/S应用:TCP单、多线程通讯模型 BIO + UDP协议的Socket编程_第1张图片

InetAddress ip=InetAddress.getByName("127.0.0.1");

TCP

常见的tcp协议的软件 :
Netcat: nc yum install nc
Telnet:
java——基于TCP协议的Socket编程:基于Socket通信的C/S应用:TCP单、多线程通讯模型 BIO + UDP协议的Socket编程_第2张图片

TCP:用来实现双向安全连接网络通信
Socket通信模型:
进行网络通信时,Socket需要借助数据流来完成数据的传递工作

1.Socket 套接字 传输层协议编程

java——基于TCP协议的Socket编程:基于Socket通信的C/S应用:TCP单、多线程通讯模型 BIO + UDP协议的Socket编程_第3张图片
TCP:面向连接的网络通讯(在传输数据之前,需要提前建立连接通道)
java——基于TCP协议的Socket编程:基于Socket通信的C/S应用:TCP单、多线程通讯模型 BIO + UDP协议的Socket编程_第4张图片

java——基于TCP协议的Socket编程:基于Socket通信的C/S应用:TCP单、多线程通讯模型 BIO + UDP协议的Socket编程_第5张图片
java——基于TCP协议的Socket编程:基于Socket通信的C/S应用:TCP单、多线程通讯模型 BIO + UDP协议的Socket编程_第6张图片
`

2.BIO模式 :Block Input Output 阻塞式IO(单线程 )

一个客户端对应一个服务器端
服务器端:
java——基于TCP协议的Socket编程:基于Socket通信的C/S应用:TCP单、多线程通讯模型 BIO + UDP协议的Socket编程_第7张图片
客户端:
java——基于TCP协议的Socket编程:基于Socket通信的C/S应用:TCP单、多线程通讯模型 BIO + UDP协议的Socket编程_第8张图片
打成jar包,运行两个客户端对服务器进行传输数据,无法收到第二个的数据;
java——基于TCP协议的Socket编程:基于Socket通信的C/S应用:TCP单、多线程通讯模型 BIO + UDP协议的Socket编程_第9张图片

BIO+多线程(改良版)非阻塞式,实现多台客户端同时向服务器端发士消息

服务器端:

public class TCPServer {
    //多线程
    //姓名=》socket Map集合存储 key/value
    public static HashMap onlineUsers = new HashMap();
    public static void main(String[] args) {
        try {
             ServerSocket serverSocket=new ServerSocket(18888);//创建绑定到特定端口的服务器套接字。
             System.out.println("start!");
             while (true) {
                 Socket socket = serverSocket.accept();// 侦听并接受到此套接字的连接。socket接受serversocket的socket对象;一个socket对应一个客户端
                 Worker worker = new Worker(socket);
                 worker.start();
             }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}
class Worker extends Thread {
    private Socket socket;

    Worker(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        try {
            InputStream inputStream = socket.getInputStream();//返回此套接字的输入流。
            byte[] b = new byte[1024];
            while (true) {
                int p = inputStream.read(b);
                String info = new String(b, 0, p);
                if (!info.trim().equals(""))
                    System.out.println("数据:" + info);
                receive(info);//报文分析and发送返回信息
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void receive(String info) {
        try {
//            System.out.println(info);
//            OutputStream outputStream = socket.getOutputStream();
            String[] s = info.split("-");
            if (s[1].equals("login")) {
                TCPServer.onlineUsers.put(s[2], socket);
                sendMessage(s[2],"登录成功");
            } else if (s[1].equals("logout")) {
                sendMessage(s[2], "注消完毕");
                TCPServer.onlineUsers.remove(s[2]);
            } else if (s[1].equals("onlineusers")) {
                String names = "";
                for (Map.Entry entry : TCPServer.onlineUsers.entrySet()) {
                    names += entry.getKey() + "-";
                }
                sendMessage(s[2],("message-onlineusers-" + names));
            }
            if (s[0].equals("message")) {
                String s1=s[1]+":"+s[3];
                for (Map.Entry entry : TCPServer.onlineUsers.entrySet()){
                    if(entry.getKey().equals(s[2]))
                        sendMessage(s[2],s1);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //返回信息
    public void sendMessage(String name, String info){
        Socket socket = TCPServer.onlineUsers.get(name);
        try{
            OutputStream outputStream = socket.getOutputStream();
            outputStream.write(info.getBytes());
            outputStream.flush();

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

客户端:


public class TCPkehu {
    //多线程
    public static void main(String[] args) {
        try {
            Scanner scanner = new Scanner(System.in);
            Socket socket=new Socket("10.0.18.88",18888);
            //收消息
            Receice receice=new Receice(socket);
            receice.start();
            
            //发消息
            OutputStream outputStream = socket.getOutputStream();
            while(true) {
                System.out.println("发送:");
                outputStream.write(scanner.next().getBytes());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
class Receice extends Thread{
    Socket socket;
    public Receice(Socket socket){	//构造
        this.socket=socket;
    }
    @Override
    public void run() {
        while (true) {
            try {
                InputStream inputStream = socket.getInputStream();
                byte[] b = new byte[1024];
                int p = inputStream.read(b);
                String s = new String(b, 0, p);
                System.out.println("返回数据为:" + s);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

自定协议,通过发送报文互传消息,服务器端解析消息

通讯数据包,要符合自定义协议:

a)管理报文(服务器端接收):

management-login-姓名XX
management-logout-姓名XX
management-onlineusers

b)消息报文:

message-发送人-接收人-聊天内容

-》实现客户端的互发信息:处理报文: message-发送人-接收人-聊天内容

java——基于TCP协议的Socket编程:基于Socket通信的C/S应用:TCP单、多线程通讯模型 BIO + UDP协议的Socket编程_第10张图片
java——基于TCP协议的Socket编程:基于Socket通信的C/S应用:TCP单、多线程通讯模型 BIO + UDP协议的Socket编程_第11张图片

UDP互发消息

java——基于TCP协议的Socket编程:基于Socket通信的C/S应用:TCP单、多线程通讯模型 BIO + UDP协议的Socket编程_第12张图片

DatagramSocket类

DatagramSocket类 :此类表示用来发送和接收数据报包的套接字。

重要构造:

DatagramSocket(int port)
DatagramSocket(int port, InetAddress laddr)

重要方法:

void close()
关闭此数据报套接字。
void connect(InetAddress address, int port)
将套接字连接到此套接字的远程地址。
void disconnect()
断开套接字的连接。
boolean isClosed()
返回是否关闭了套接字。
boolean isConnected()
返回套接字的连接状态。
void receive(DatagramPacket p)
从此套接字接收数据报包。
void send(DatagramPacket p)
从此套接字发送数据报包。
·

DatagramPacket类

DatagramPacket 类 此类表示数据报包。

重要方法:

byte[] getData()
返回数据缓冲区。
int getLength()
返回将要发送或接收到的数据的长度。
void setData(byte[] buf)
为此包设置数据缓冲区。
void setData(byte[] buf, int offset, int length)
为此包设置数据缓冲区。
void setLength(int length)
为此包设置长度。
java——基于TCP协议的Socket编程:基于Socket通信的C/S应用:TCP单、多线程通讯模型 BIO + UDP协议的Socket编程_第13张图片
基本的UDP通讯java——基于TCP协议的Socket编程:基于Socket通信的C/S应用:TCP单、多线程通讯模型 BIO + UDP协议的Socket编程_第14张图片

客户端1:


public class UDPServer {
    public static void main(String[] args) throws Exception {
        Scanner scanner=new Scanner(System.in);
        DatagramSocket datagramSocket=new DatagramSocket(18889);
        while (true) {
            //接
            byte[] b = new byte[1024];
            DatagramPacket datagramPacket = new DatagramPacket(b, b.length);//构造一个 DatagramPacket用于接收length长度的数据包 。
            datagramSocket.receive(datagramPacket);//从此套接字接收数据报包。
            System.out.println("接收数据:");
            System.out.println(new String(b, 0, datagramPacket.getLength()));//length,返回要发送的数据的长度或接收到的数据的长度。
            //发
            System.out.print("请输入:");
            String s = scanner.next();
            DatagramPacket datagramPacket1 = new DatagramPacket(s.getBytes(), s.length(), InetAddress.getByName("127.0.0.1"), 18890);//构造用于发送长度的分组的数据报包 length指定主机上到指定的端口号。
            datagramSocket.send(datagramPacket1);//从此套接字发送数据报包
        }
    }
}

java——基于TCP协议的Socket编程:基于Socket通信的C/S应用:TCP单、多线程通讯模型 BIO + UDP协议的Socket编程_第15张图片

客户端2:

public class UDPkehu {
    public static void main(String[] args) throws Exception {
        Scanner scanner=new Scanner(System.in);
        DatagramSocket datagramSocket=new DatagramSocket(18890);
        while (true) {
            //发
            System.out.print("请输入:");
            String s = scanner.next();
            DatagramPacket datagramPacket1 = new DatagramPacket(s.getBytes(), s.length(), InetAddress.getByName("127.0.0.1"), 18889);//构造用于发送长度的分组的数据报包 length指定主机上到指定的端口号。
            datagramSocket.send(datagramPacket1);//从此套接字发送数据报包
            
            //接
            byte[] b = new byte[1024];
            DatagramPacket datagramPacket = new DatagramPacket(b, b.length);//构造一个 DatagramPacket用于接收length长度的数据包 。
            datagramSocket.receive(datagramPacket);//从此套接字接收数据报包。
            System.out.println("返回数据:");
            System.out.println(new String(b, 0, datagramPacket.getLength()));//返回要发送的数据的长度或接收到的数据的长度。
        }

    }
}

java——基于TCP协议的Socket编程:基于Socket通信的C/S应用:TCP单、多线程通讯模型 BIO + UDP协议的Socket编程_第16张图片
每个客户端占一个端口号

你可能感兴趣的:(java)