Java网络编程

Java网络编程


1.网络编程相关类的使用:
1.1 InetAddress类
Java提供了InetAddress类来代表ip地址,是对ip地址的抽取和封装,
有两个子类:Inet4Address,Inet6Address,分别表示IPv4和IPv6
public class Demo01 {
    public static void main(String[] args) throws UnknownHostException {
        //创建IP地址对象
        //获取本地IP地址
        System.out.println("-------本地IP--------");
        InetAddress ia1 = InetAddress.getByName("xxxx.xxxx.xxxx.xxxx"); //本机IP
        InetAddress ia2 = InetAddress.getByName("localhost");
        InetAddress ia3 = InetAddress.getByName("127.0.0.1");
        InetAddress ia4 = InetAddress.getLocalHost();
        InetAddress ia5 = InetAddress.getByName("LAPTOP-xxxxxxx");//主机名称

        System.out.println("主机地址:"+ia1.getHostAddress()+"主机名:"+ia1.getHostName());
        System.out.println("主机地址:"+ia2.getHostAddress()+"主机名:"+ia2.getHostName());
        System.out.println("主机地址:"+ia3.getHostAddress()+"主机名:"+ia3.getHostName());
        System.out.println("主机地址:"+ia4.getHostAddress()+"主机名:"+ia4.getHostName());
        System.out.println("主机地址:"+ia5.getHostAddress()+"主机名:"+ia5.getHostName());

        //获取局域网ip
        System.out.println("-------局域网ip-------");
        InetAddress ia6 = InetAddress.getByName("xxxx.xxxx.xxxx.xxxx");
        System.out.println("主机地址:"+ia6.getHostAddress()+"主机名:"+ia6.getHostName());

        //获取internet
        System.out.println("--------internet---------");
        InetAddress ia7 = InetAddress.getByName("www.csdn.com");
        System.out.println("主机地址:"+ia7.getHostAddress()+"主机名:"+ia7.getHostName());
        InetAddress[] allByName = InetAddress.getAllByName("www.csdn.com");
        for (InetAddress inetAddress : allByName) {
            System.out.println(inetAddress.getHostAddress());
        }
    }
}
1.2 URLEncoder类和URLDecoder类

​ URLEncoder类和URLDecoder类用于完成普通字符串和application/x-www-form-urlencoded MIME字符串之间的转换

public class Demo02 {
    public static void main(String[] args) {
        String say = "好久不见";
        //注意:编码和解码需要采用相同的字符集
        try {
            //URL编码 URLEncoder:编码,将普通字符串转换为特殊字符串
            String encode = URLEncoder.encode(say,"utf-8" );
            System.out.println(encode);
            //URL解码 URLDecoder:解码,将特殊中文字符串转换为普通字符串
            String say2 = URLDecoder.decode(encode, "utf-8");
            System.out.println(say2);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }
}
2.基于TCP的网络编程
TCP客户端编码步骤:
1.创建客户端套接字,并指定服务器的地址和端口号
2.获取输入|输出流
3.发送数据
4.关闭
TCP服务器端编码步骤:
1.创建ServerSocket(服务器套接字对象)
2.侦听或监听,返回Socket(客户端套接字),阻塞方法
3.获取输入|输出流
4.处理数据
5.关闭资源
2.1 客户端发送消息,服务端接收消息
/**
 * TCP服务器端
 */
public class TCPServer {
    public static void main(String[] args) throws Exception{
        //创建ServerSocket(服务器套接字对象)
        ServerSocket listener = new ServerSocket(10086);
        //侦听或监听,返回Socket(客户端套接字),阻塞方法
        System.out.println("服务器已启动");
        Socket socket = listener.accept();
        //获取输入或输出流
        InputStream is = socket.getInputStream();
        //处理数据
        InputStreamReader isr = new InputStreamReader(is);
        BufferedReader br =  new BufferedReader(isr);
        String data = br.readLine();
        System.out.println("客户端说:"+data);
        //关闭资源
        br.close();
        socket.close();
        listener.close();
    }
}



/**
 * TCP客户端
 */
public class TCPClient {
    public static void main(String[] args) throws Exception {
        //创建客户端套接字Socket,并指定服务器的ip和端口号
        Socket socket = new Socket("xxxx.xxxx.xxxx.xxxx", 10086);
        //获取输入,输出流
        OutputStream os = socket.getOutputStream();
        //发送数据
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
        bw.write("好久不见");
        //关闭
        bw.close();
        socket.close();
    }
}
2.2 客户端发送消息,服务端回复消息
/**
 * TCP服务器端
 */
public class TCPServer {
    public static void main(String[] args) throws Exception{
        ServerSocket listener = new ServerSocket(10010);

        System.out.println("服务器启动了");

        Socket socket = listener.accept();

        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

        String data = br.readLine();//读取到换行符,返回结果
        System.out.println("客户端说"+data);
        bw.write("你走开");
        bw.newLine();

        bw.close();
        br.close();
        socket.close();
        listener.close();
    }
}



/**
 * TCP客户端
 */
 public class TCPClient {
    public static void main(String[] args) throws Exception {
        Socket socket = new Socket("xxxx.xxxx.xxxx.xxxx",10010 );

        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

        bw.write("好久不见");
        bw.newLine();//换行符
        bw.flush();//刷新缓冲
        String reply = br.readLine();
        System.out.println("服务器回复"+reply);

        bw.close();
        br.close();
        socket.close();
    }

2.3 客户端上传文件到服务端【以图片为例】
/**
 * TCP服务器端
 */
public class FileServer {
    public static void main(String[] args) throws  Exception{
        //创建ServerSocket 并指定端口号
        ServerSocket listener = new ServerSocket(8888);
        //侦听,返回客户端套接字
        System.out.println("服务器已启动");
        Socket socket = listener.accept();
        //获取输入流
        InputStream is = socket.getInputStream();
        FileOutputStream fos = new FileOutputStream("图片路径");
        byte[] bytes = new byte[1024];
        int len = -1;
        //读取数据
        while ((len = is.read(bytes))!= -1) {
            fos.write(bytes,0 ,len );
        }
        //关闭
        fos.close();
        is.close();
        socket.close();
        listener.close();
        System.out.println("接收文件完毕");
    }
}



/**
 * TCP客户端
 */
public class FileClient {
    public static void main(String[] args) throws Exception{
        //创建socket
        Socket socket = new Socket("xxxx.xxxx.xxxx.xxxx",8888 );
        //获取输出流
        OutputStream  os = socket.getOutputStream();
        //读取文件并输出
        FileInputStream fis = new FileInputStream("图片路径");
        byte[] bytes = new byte[1024];
        int len = -1;
        while ((len = fis.read(bytes))!=-1) {
            os.write(bytes,0,len);
        }

        //关闭
        fis.close();
        os.close();
        socket.close();
        System.out.println("发送完毕");

    }
}
2.4 多个客户端和一个服务端通信【线程版本】
/**
 * 多线程处理
 */
public class ChatThread extends Thread {
    private Socket socket;

    public ChatThread(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        BufferedReader br = null;
        if (socket != null) {
            try {
                InputStream is = socket.getInputStream();
                br = new BufferedReader(new InputStreamReader(is));
                while (true) {
                    String data = br.readLine();
                    System.out.println(socket.getInetAddress().getHostAddress() + "说:" + data);
                    if (data.equals("拜拜") || data.equals("over") || data.equals("886")) {
                        System.out.println(socket.getInetAddress().getHostAddress() + "退出了");
                        break;
                    }
                }
            } catch (IOException e) {
//                e.printStackTrace();
                System.out.println(socket.getInetAddress().getHostAddress() + "异常退出了...");

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

            }

        }
    }
}



/**
 * TCP服务器端
 */
public class ChatServer {
    public static void main(String[] args) throws Exception{
        //1创建ServerSocket
        ServerSocket listener=new ServerSocket(9999);
        //2监听
        System.out.println("聊天服务器已启动....");
        try {
            while(true) {
                Socket socket = listener.accept();
                new ChatThread(socket).start();
            }
        } catch (IOException e) {
            System.out.println("聊天室结束了");
        }finally {
            listener.close();
        }
    }
}



/**
 * TCP客户端
 */
 public class ChatClient {
    public static void main(String[] args) throws Exception {
        //1创建socket
        Socket socket=new Socket("xxxx.xxxx.xxxx.xxxx", 9999);
        //2 获取输出流
        OutputStream os = socket.getOutputStream();
        BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(os));
        //3发送
        Scanner input=new Scanner(System.in);
        while(true){
            String data = input.next();
            bw.write(data);
            bw.newLine();
            bw.flush();
            if(data.equals("拜拜")||data.equals("over")||data.equals("886")){
                break;
            }
        }
        //4关闭
        bw.close();
        socket.close();
    }
}

*该聊天室只能实现一对多无差别的通信,如果需要在该聊天室中与特定的某个人聊天的话,该如何实现呢?

首先,我们应该知道并获取对方的IP地址,其次服务器应该实现对特定消息进行转发。具体实现如下:

//线程端
public class ChatThread extends Thread {
    private Socket socket;
    private Map<String,Socket> maps;

    public ChatThread(Socket socket,Map<String,Socket> maps) {
        this.socket = socket;
        this.maps=maps;
    }

    @Override
    public void run() {
        BufferedReader br=null;
        if(socket!=null){
            try {
                InputStream is = socket.getInputStream();
                br=new BufferedReader(new InputStreamReader(is));
                while(true){
                    String data = br.readLine();
                    if(data==null){
                        System.out.println(socket.getInetAddress().getHostAddress()+"退出了");
                        maps.remove(this.socket.getInetAddress().getHostAddress());
                        break;
                    }
                    System.out.println(socket.getInetAddress().getHostAddress()+"说:"+data);
                    if(data.equals("baibai")||data.equals("over")||data.equals("886")){
                        System.out.println(socket.getInetAddress().getHostAddress()+"退出了");
                        maps.remove(this.socket.getInetAddress().getHostAddress());
                        break;
                    }

                    
                    //截取ip地址
                    String ip=data.substring(0, data.indexOf(":"));
                    String pattern = "((2(5[0-5]|[0-4]\\d))|[0-1]?\\d{1,2})(\\.((2(5[0-5]|[0-4]\\d))|[0-1]?\\d{1,2})){3}";
                    if(ip!=null){
                        boolean result = ip.matches(pattern);
                        if(result){
                            Socket socket = maps.get(ip);
                            if(socket!=null){
                                //转发
                                synchronized (socket){
                                    OutputStream os = socket.getOutputStream();
                                    BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(os));
                                    String address = this.socket.getInetAddress().getHostAddress();
                                    bw.write(address+"说:"+data.substring(data.indexOf(":")+1));
                                    bw.newLine();
                                    bw.flush();
                                    System.out.println(address+"给"+ip+"转发了数据");
                                }
                            }
                        }
                    }
                }
            } catch (Exception e) {
                //e.printStackTrace();
                //e.printStackTrace();
                System.out.println(socket.getInetAddress().getHostAddress()+"异常退出了...");
                maps.remove(this.socket.getInetAddress().getHostAddress());
            }finally {
                try {
                    br.close();
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}


//服务器端
public class ChatServer {
    public static void main(String[] args) throws IOException {
        //1创建ServerSocket
        ServerSocket listener = new ServerSocket(9999);

        Map<String, Socket> maps = Collections.synchronizedMap(new HashMap<>());

        //2监听
        System.out.println("聊天服务器已启动....");
        try {
            while (true) {
                Socket socket = listener.accept();
                System.out.println("连接成功:" + socket.getInetAddress().getHostAddress());
                maps.put(socket.getInetAddress().getHostAddress(), socket);
                new ChatThread(socket, maps).start();
            }
        } catch (IOException e) {
            System.out.println("聊天室结束了");
        } finally {
            listener.close();
        }
    }
}


//客户端
public class ChatClient {
    public static void main(String[] args) throws Exception {
        //1创建socket
        Socket socket = new Socket("xxxx.xxxx.xxxx", 9999);

        //2发送线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                BufferedWriter bw = null;
                try {
                    //2 获取输出流
                    OutputStream os = socket.getOutputStream();
                    bw = new BufferedWriter(new OutputStreamWriter(os));
                    //3发送
                    Scanner input = new Scanner(System.in);
                    while (true) {
                        String data = input.nextLine();
                        bw.write(data);
                        bw.newLine();
                        bw.flush();
                        if (data.equals("baibai") || data.equals("over") || data.equals("886")) {
                            break;
                        }
                    }
                    //4关闭

                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    try {
                        bw.close();
                        if (!socket.isClosed()) {
                            socket.close();
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();


        //3接受数据线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                BufferedReader br = null;
                try {
                    InputStream is = socket.getInputStream();
                    br = new BufferedReader(new InputStreamReader(is));
                    while (true) {
                        String data = br.readLine();
                        System.out.println(data);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    try {
                        br.close();
                        if (!socket.isClosed()) {
                            socket.close();
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }
}
2.5TCP实现注册登录
//客户端
public class Client {
	/**
	 * 注册
	 * @param userName 用户名
	 * @param password	密码
	 */
	public void doRegister(String userName,String password) {
		realAction(userName, password, "10.31.165.42", 6666);
	}
	
	/**
	 * 登录
	 * @param userName 用户名
	 * @param password	密码
	 */
	public void doLogin(String userName,String password) {
		realAction(userName, password, "10.31.165.42", 7777);
	}
	
	/**
	 * 将用户名和密码发送给服务端
	 * @param userName
	 * @param password
	 * @param ip
	 * @param port
	 */
	private void realAction(String userName,String password,String ip,int port) {
		
		Socket client = null;
		try {
			//1.实例化一个Socket的对象
			client = new Socket(ip, port);
			
			//2.获取输出流
			//缓冲字符流
			BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
			
			//3.写入数据
			writer.write(userName + "," + password);//yang123123abc
			writer.flush();
			
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		finally {
			try {
				client.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}	
	}
}



//服务端
public class Server {
	private ServerSocket registerSocket;// 用来注册
	private ServerSocket loginSocket;// 用来登录

	// 将每次需要注册的用户名和密码以键值对的形式存储到配置文件中,结合Properties使用
	// 实例化一个Peroperties的对象
	private Properties userlist = new Properties();

	// 构造代码块
	{
		// 同步配置文件中的内容
		try {
			userlist.load(new BufferedInputStream(new FileInputStream(new File("file/userlist.properties"))));
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * 开启服务
	 */
	public void start() {
		// 开启注册服务
		new Thread() {
			@Override
			public void run() {
				startRegisterService();
			}
		}.start();

		// 开启登录服务
		new Thread() {
			@Override
			public void run() {
				startLoginService();
			}
		}.start();
	}
	
	/**
	 * 实现注册功能
	 */
	private void startRegisterService() {
		
		try {
			//1.实例化一个ServerSocket的对象
			this.registerSocket = new ServerSocket(6666);
			
			while(true) {
				//2.获取连接到的客户端
				Socket socket = this.registerSocket.accept();
				System.out.println("连接到客户端" + socket);
				//3.获取客户端发送来的数据
				BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
				
				//4.读取
				String string = reader.readLine();//zhangsan,abc123
				System.out.println(string);
				//5.解析用户名和密码
				String[] arr = string.split(",");
				
				//6.注册
				//arr[0]:用户名
				//arr[1]:密码
				if(this.userlist.containsKey(arr[0]) && this.userlist.containsValue(arr[1])) {
					System.out.println("该用户已经存在,无需注册");
				} else {
					//新增一个用户
					this.userlist.setProperty(arr[0], arr[1]);
					//将用户名和密码同步到配置文件中进行持久化
					this.userlist.store(new BufferedOutputStream(new FileOutputStream(new File("file/userlist.properties"))), "add an user");
					System.out.println("注册成功");
				}	
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		finally{
			try {
				this.registerSocket.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}	
	}
	
	/**
	 * 实现登录功能
	 */
	private void startLoginService() {
		
		try {
			//1.实例化一个ServerSocket的对象
			this.loginSocket = new ServerSocket(7777);
			
			//2.获取连接到的客户端
			Socket socket = this.loginSocket.accept();
			
			//3.获取客户端发送来的用户名和密码
			BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			
			//4.读取
			String string = reader.readLine();
			
			//5.解析用户名和密码
			String[] arr = string.split(",");
			
			//6.登录
			if(this.userlist.containsKey(arr[0])) {
				
				if(arr[1].equals(this.userlist.getProperty(arr[0]))) {
					System.out.println("登录成功");
				} else {
					System.out.println("用户名/密码错误");
				}
				
			} else {
				System.out.println("还未注册,请先注册");
				//startRegisterService();
			}
			
		} catch (IOException e) {
			e.printStackTrace();
		}	
	}
}
3.UDP编程
3.1UDP基本概念

​ User Datagram Protocol的简称,用户数据包协议,提供面向事务的简单不可靠信息传送服务

​ 特点:

​ 1.不安全

​ 2.无连接

​ 3.效率高

​ 4.UDP传输数据时是有大小限制的,每个被传输的数据报必须限定在64KB之内

3.2基于UDP的网络编程
3.2.1 客户端发送消息,服务端接收消息
public class Receiver {
    public static void main(String[] args) throws Exception{
        //创建DatagramSocket,指定端口号
        DatagramSocket ds =  new DatagramSocket(9999);
        //创建一个接收的数据报包
        byte[] bytes = new byte[1024*8];
        DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
        //接收(阻塞方法,如果没有数据就阻塞,有数据就接收)
        System.out.println("准备接收:");
        ds.receive(dp);
        //处理数据
        String data = new String(dp.getData(),0,dp.getLength());
        System.out.println(dp.getAddress().getHostAddress()+"对方说:"+data );
        //关闭
        ds.close();
    }
}




public class Sender {
    public static void main(String[] args) throws Exception {
        //创建DatagramSocket,使用随机端口号
        DatagramSocket ds = new DatagramSocket();
        //创建发送数据报包
        String say = "好久不见";
        DatagramPacket dp = new DatagramPacket(say.getBytes(), say.getBytes().length, InetAddress.getLocalHost(), 9999);
        //发送
        ds.send(dp);
        //接收回复
        byte[] bytes = new byte[1024*8];
        DatagramPacket dp2 =  new DatagramPacket(bytes,bytes.length );

        //关闭
        ds.close();
    }
}

3.2.2客户端发送消息,服务端回复消息
public class Receiver {
    public static void main(String[] args) throws Exception{
        //创建DatagramSocket,指定端口号
        DatagramSocket ds =  new DatagramSocket(9999);
        //创建一个接收的数据报包
        byte[] bytes = new byte[1024*8];
        DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
        //接收(阻塞方法,如果没有数据就阻塞,有数据就接收)
        System.out.println("准备接收:");
        ds.receive(dp);
        //处理数据
        String data = new String(dp.getData(),0,dp.getLength());
        System.out.println(dp.getAddress().getHostAddress()+"对方说:"+data );
        //回复
        String reply= "十分想念";
        DatagramPacket dp2 = new DatagramPacket(reply.getBytes(),reply.getBytes().length,dp.getAddress(),dp.getPort() );
        ds.send(dp2);
        //关闭
        ds.close();
    }
}



public class Sender {
    public static void main(String[] args) throws Exception {
        //创建DatagramSocket,使用随机端口号
        DatagramSocket ds = new DatagramSocket();
        //创建发送数据报包
        String say = "好久不见";
        DatagramPacket dp = new DatagramPacket(say.getBytes(), say.getBytes().length, InetAddress.getLocalHost(), 9999);
        //发送
        ds.send(dp);
        //关闭
        ds.close();
    }
}

3.2.3简易个人聊天室

public class ChatReceiver {
    public static void main(String[] args) throws Exception {
        new Thread(new Runnable() {
            @Override
            public void run() {
                DatagramSocket ds = null;
                try {
                    ds = new DatagramSocket(9999);
                    byte[] bytes = new byte[1024 * 8];
                    DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
                    while (true) {
                        ds.receive(dp);
                        String data = new String(dp.getData(),dp.getLength());
                        System.out.println(dp.getAddress().getHostAddress() + "说:" + data);
                        if (data.equals("886")) {
                            System.out.println(dp.getAddress().getHostAddress() + "退出了");
                        }
                    }
                } catch (SocketException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    ds.close();
                }
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                DatagramSocket ds = null;
                try {
                    ds = new DatagramSocket();
                    Scanner input = new Scanner(System.in);
                    while (true) {
                        String data = input.next();
                        DatagramPacket dp = new DatagramPacket(data.getBytes(), data.getBytes().length, InetAddress.getByName("10.9.21.255"), 9999);
                        ds.send(dp);
                        if (data.equals("886")) {
                            break;
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    ds.close();
                }
            }
        }).start();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值