Java网络编程

网络基础

一句话:
两个小人通过管道丢菜
小人是IP
管道是Socket
菜盘子是端口
菜是传输的数据

需要引入的包:
1.网络编程相关

java.net.*;

2.输入输出相关:

import java.util.Scanner;

3.字节输入输出流

import java.io.*;
1。InetAddress 标识网络的硬件(每台电脑)
2.Socket DatagramSocket 数据网络传输的通道
3.IP:唯一标识一台计算器的身份证号码(查看IP:win+R cmd ipconfig)
4.端口:同一台机器上不同进程(应用程序)的标识  范围:0-65535
5.域名: 例如:www.baidu.com 网址
两台机器的数据传输:两种协议
1.传输控制协议TCP
2.用户数据报协议UDP

InetAddress

实现主机名与IP地址的转换
无构造方法,不能直接创建对象
静态方法获取对象

//获取对象
InetAddress add1 = InetAddress.getByName("www.163.com");
byte[] b = new byte[1024];
b = add1.getAddress();//返回对象原始IP地址
String getHostAddress() //返回对象IP地址字符串
String getHostName()//返回对象主机名称

举例:

package net_1;

import java.net.*;

public class Test {
	public static void main(String []args) throws Exception{
		InetAddress add1 = InetAddress.getByName("www.baidu.com");
		InetAddress add2 = InetAddress.getByName("127.0.0.1");
		InetAddress add3 = InetAddress.getLocalHost();//本地主机IP地址
		
		String ip1 = add1.getHostAddress();
		String mai1 = add1.getHostName();
		
		String ip2 = add2.getHostAddress();
		String mai2 = add2.getHostName();
		
		String ip3 = add3.getHostAddress();
		String mai3 = add3.getHostName();
		
		System.out.println("对象1Ip地址:"+ip1);
		System.out.println("对象1主机名称:"+mai1);
		
		System.out.println("对象2Ip地址:"+ip2);
		System.out.println("对象2主机名称:"+mai2);
		
		System.out.println("对象3Ip地址:"+ip3);
		System.out.println("对象3主机名称:"+mai3);
	}
}

输出:

对象1Ip地址:183.2.172.185
对象1主机名称:www.baidu.com
对象2Ip地址:127.0.0.1
对象2主机名称:activate.navicat.com
对象3Ip地址:172.29.3.69
对象3主机名称:1NPC069

InetSocketAddress

InetSocketAddress:包装InetAddressIP 地址 + 端口号)。
1.构造方法
(1InetSocketAddress(InetAddress addr, int port)
 IP 地址和端口号
(2InetSocketAddress(int port)
创建套接字地址,其中 IP 地址为通配符地址,端口号为指定值。
(3InetSocketAddress(String hostname, int port)
根据主机名和端口号创建套接字地址。

2.常用方法
(1)InetAddress getAddress()
获取 InetAddress(2)String getHostName()
获取 hostname。
(3)int getPort()
获取端口号。

TCP通信一发一收

在这里插入图片描述

客户端程序

在这里插入图片描述
1.创建服务端对象(找对方的位置)(我在本机测试的)

InetAddress add1 = InetAddress.getLocalHost();

2.创建通道(对方的位置,对方使用的应用程序)

Socket socket = new Socket(add1,5555);

3.从socket管道得到字节输出流(输出到服务端)

OutputStream os = socket.getOutputStream();

4.包装数据

DataOutputStream dos = new DataOutputStream(os);

5.向服务端写数据

dos.writeUTF("hhh");

6.关闭部分

dos.close();
socket.close();

总体代码:

package net_1;

import java.io.*;
import java.net.*;

public class Test2 {
	public static void main(String []args) throws Exception{
		//本机InetAddress对象
		InetAddress add1 = InetAddress.getLocalHost();
		//1.请求与服务器的连接  IP字符串/InetAddress对象 端口号
		Socket socket = new Socket(add1,5555);
		
		//2.从socket管道得到字节输出流
		OutputStream os = socket.getOutputStream();
		
		//3.包装
		DataOutputStream dos = new DataOutputStream(os);
		
		//4.写数据
		dos.writeUTF("hhh");
		//5.关闭
		dos.close();
		socket.close();
	}
}

在这里插入图片描述

服务端程序

在这里插入图片描述
在这里插入图片描述
1.指定自己的端口

ServerSocket serv = new  ServerSocket(5555);

2等待客户端连接,得到Socket对象

Socket so = serv.accept();

3.得到字节输入流

InputStream is = so.getInputStream();

4.包装字节输入流

DataInputStream dis = new DataInputStream(is);

5.接收数据

String s = dis.readUTF();

6.关闭资源

dis.close();
serv.close();
package net_1;

import java.io.*;
import java.net.*;

public class Server {
	public static void main(String []args) throws Exception{
		//服务端对象                           接口
		ServerSocket serv = new  ServerSocket(5555);
		
		//2.调用accept
		Socket so = serv.accept();
		
		//3.字节输出流
		InputStream is = so.getInputStream();
		
		//4.包装
		DataInputStream dis = new DataInputStream(is);
		
		//5.接收
		String rs = dis.readUTF();
		
		System.out.println("输出"+rs);
		
		//6.关闭资源
		dis.close();
		serv.close();
	}
}

在这里插入图片描述
先启动服务端

TCP通信多发多收

增加了while循环和输入

客户端

package 网络TCP;

import java.io.*;
import java.net.*;
import java.util.Scanner;

public class Sender {
	public static void main(String []args) throws Exception{
		//1.获取本机InetAddress对象,一般为服务端的ip地址
		InetAddress add1 = InetAddress.getLocalHost();
		
		//1.请求与服务器的连接  服务端的IP字符串/InetAddress对象 端口号
		Socket socket = new Socket(add1,5555);
		
		//2.从socket管道得到字节输出流
		OutputStream os = socket.getOutputStream();
		
		//3.包装
		DataOutputStream dos = new DataOutputStream(os);
		
		Scanner in = new Scanner(System.in);
		while(true) {
			System.out.println("请输入:");
			String s = in.nextLine();//输入数据
			if("exit".equals(s)) {
				System.out.println("用户下线");
				dos.close();
				socket.close();
				break;
			}
			//4.写数据
			dos.writeUTF(s);
			System.out.println("发送成功");
		}
		//5.关闭
		
	}
}

服务端

package 网络TCP;

import java.io.*;
import java.net.*;

public class Server {
	public static void main(String []args) throws Exception{
		System.out.println("接收:");
		//1.创建服务端对象                      定义自己的接口
		ServerSocket serv = new  ServerSocket(5555);
		
		//2.接收管道,调用accept
		Socket so = serv.accept();
		
		//3.字节输出流
		InputStream is = so.getInputStream();
		
		//4.包装
		DataInputStream dis = new DataInputStream(is);
		
		while(true) {
			try {
				//5.读数据
				String rs = dis.readUTF();
				System.out.println("接收成功:");
				System.out.println("输出"+rs);
			}catch(Exception e) {
				System.out.println("客户端下线了");
				//6.关闭资源
				dis.close();
				serv.close();
				break;
			}
		}
	}
}

与多个客户端通信(多线程)

改进了服务端部分

在这里插入图片描述

服务端部分

package 网络TCP;

import java.io.*;
import java.net.*;

public class Server {
	public static void main(String []args) throws Exception{
		System.out.println("接收:");
		//1.创建服务端对象                      定义自己的接口
		ServerSocket serv = new  ServerSocket(5555);
		
		while(true) {
			//2.接收管道,调用accept
			Socket so = serv.accept();
			
			System.out.println("有人上线了"+so.getRemoteSocketAddress());
			//把客户端对应的管道,交给独立的线程处理
			new ServerReaderSocket(so).start();
		}
	}
}

每个进程部分

package 网络TCP;

import java.net.*;
import java.io.*;
public class ServerReaderSocket extends Thread{
	Socket so;
	ServerReaderSocket(Socket s){//当前管道
		this.so = s;
	}
	public void run() {
		try {
			//获得输入流
			InputStream is = so.getInputStream();
			//包装
			DataInputStream dis = new DataInputStream(is);
			//读数据
			while(true) {
				try {
					String s = dis.readUTF();
					System.out.println(so.getRemoteSocketAddress()+"读取数据:"+s);
				}catch(Exception e){
					System.out.print(so.getRemoteSocketAddress());
                    System.out.println("下线了");
                    //关闭资源
                    dis.close();
                    so.close();
                    break;				}
			}
		}catch(Exception e) {
		System.out.print(so.getRemoteSocketAddress());
        System.out.println("下线了");
		}		
	}
}

运行:先启动服务端
在启动客户端(这里需要更改设置,勾选Allow mutiply instances)
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

群聊

某个客户端的消息发给服务端,然后发给每个客户端
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

UDP

客户端

在这里插入图片描述
1.创建小人:

DatagramSocket sender = new DatagramSocket();

2.对方小人(服务端)的位置

InetAddress ip1 = InetAddress.getLocalHost();

3.自己的菜:

byte[] cai;

4.对方小人的盘子:

DatagramPacket pan_zi = new DatagramPacket(cai,len,ip1,5555);
//装的菜,菜的多少,对方小人的位置,对方菜盘子的位置

5.把菜盘子扔过去:

sender.send(pan_zi);

6.把人噶了:

sender.close();

总体代码:(增加了输入部分)

package 网络UDP通信;

import java.net.*;
import java.util.Scanner;
public class Sender {
	public static void main(String []args) throws Exception{
		System.out.println("发送");
		//客户端
		DatagramSocket sender = new DatagramSocket();
		//服务端ip,服务端端口
		//服务端主机地址,服务端端口
		//先打开服务端,在执行客户端
		//InetAddress ip1 = InetAddress.getByName("10.118.242.48");
		InetAddress ip1 = InetAddress.getLocalHost();
		//盘子
		Scanner in = new Scanner(System.in);
		
		while(true) {
			System.out.println("请说:");
			
			String s = in.nextLine();
			
			if("exit".equals(s)) {
				System.out.println("退出成功");
				sender.close();
				break;
			}
			
			byte[] b = s.getBytes();
			int len = b.length;
			
			//包装数据  字节数组,长度,ip地址,端口号
			DatagramPacket pac = new DatagramPacket(b,len,ip1,5555);
			//发送data
			sender.send(pac);
			//关闭
			System.out.println("发送成功");
		}
		
		
	}
}

服务端

在这里插入图片描述
1.创建小人,指定盘子位置

DatagramSocket people = new DatagramSocket(5555);

2.准备盘子

byte []a= new byte[1024*64];

3.包装盘子

DatagramPacket panzi = new DatagramPacket(a,a.length);

4.小人接收客户端小人送过来的菜

people.receive(panzi);
package 网络UDP通信;

import java.net.*;
public class Receiver {
	public static void main(String []args) throws Exception{
		System.out.println("接收");
		
		//1.创建服务端对象
		DatagramSocket re = new DatagramSocket(5555);//服务端加port
		//2.准备盘子
		byte[] a = new byte[1024*64];
		//3.包装数据
		DatagramPacket data = new DatagramPacket(a,a.length);
		
		while(true) {
			//4.服务器接收数据
			re.receive(data);
			//获取实际数据长度
			int len = data.getLength();
			String s = new String(a,0,len);
			System.out.println(s);
			System.out.println("接收成功");
			
			System.out.println(data.getAddress().getHostAddress());
			System.out.println(data.getPort());//获取端口号
			System.out.println("---------------------");
		}
		
	}
}

示例

一对一

在这里插入图片描述

Triangle类:

package Exer2;

import java.io.Serializable;

public class Triangle implements Serializable{
	double sideA;
	double sideB;
	double sideC;
	String area;
	public Triangle(double a,double b,double c) {
		this.sideA = a;
		this.sideB = b;
		this.sideC = c;
	}
	public boolean isLegal() {//判断三角形是否合法
		if(sideA + sideB > sideC && sideA + sideC > sideB && sideB + sideC > sideA) {
			return true;
		}
		return false;
	}
	public String calculateArea() {
		double p = (sideA + sideB + sideC) / 2.0;
		area = "" + Math.sqrt(p * (p - sideA) * (p-sideB) *(p - sideC));
		return area;
	}
}

Client类:(客户端)

package Exer2;

import java.net.*;
import java.io.*;
public class Client {
	public static void main(String []args) throws Exception{
		//服务端ip
		InetAddress add1 = InetAddress.getLocalHost();
		//管道
		Socket socket = new Socket(add1,5555);
		//输出流
		OutputStream os = socket.getOutputStream();
		//包装
		ObjectOutputStream oos = new ObjectOutputStream(os);
		//发送数据
		Triangle t = new Triangle(3,4,5);
		oos.writeObject(t);
		System.out.println("发送成功");
		//接收数据
		InputStream is = socket.getInputStream();
		DataInputStream dis = new DataInputStream(is);
		String res = dis.readUTF();
		System.out.println("结果是:"+res);
		//关闭资源
		oos.close();
		socket.close();
	}
}
//1.先做类
//2.界面
//3.多线程

Server:服务端

package Exer2;

import java.net.*;
import java.io.*;

public class Server {
	public static void main(String []args) throws Exception{
		//服务端管道
		ServerSocket server = new ServerSocket(5555);
		Socket so = server.accept();
		//输入流
		InputStream is = so.getInputStream();
		//包装
		ObjectInputStream ois = new ObjectInputStream(is);
		
		//得到对象
		Triangle r = (Triangle)ois.readObject();
		System.out.println("接收成功");
		//计算面积
		String area = r.calculateArea();
		
		//返回面积
		//输出流
		OutputStream os = so.getOutputStream();
		DataOutputStream dos = new DataOutputStream(os);
		
		dos.writeUTF(area);
		System.out.println("发送成功");
		//关闭资源
		ois.close();
		dos.close();
		server.close();
	}
}

多线程

客户端Client


import java.net.*;
import java.io.*;
import java.util.Scanner;
public class Client {
    public static void main(String []args) throws Exception{
        //服务端ip
        InetAddress add1 = InetAddress.getLocalHost();
        //管道
        Socket socket = new Socket(add1,5555);
        //输出流
        OutputStream os = socket.getOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(os);
        //输入流
        InputStream is = socket.getInputStream();
        DataInputStream dis = new DataInputStream(is);

        Scanner in = new Scanner(System.in);
        while(true){
            try{
                System.out.println("请输入三角形三条边(输入0 0 0 表示退出):");
                double a = in.nextDouble();
                double b = in.nextDouble();
                double c = in.nextDouble();
                if(a == 0 && b == 0 && c == 0){
                    throw new Exception();
                }
                //发送数据
                Triangle t = new Triangle(a,b,c);
                oos.writeObject(t);
                System.out.println("发送成功");
                //接收数据

                String res = dis.readUTF();
                System.out.println("结果是:"+res);
            }catch(Exception e){
                System.out.println("服务端下线");
                //关闭资源
                dis.close();
                oos.close();
                socket.close();
                break;
            }
        }

    }
}
//1.先做类
//2.界面
//3.多线程

ServerThread


import java.net.*;
import java.io.*;
public class ServerThread extends Thread{
    Socket so;
    ServerThread(Socket so){
        this.so = so;
    }
    public void run() {
        try {
            //输入流
            InputStream is = so.getInputStream();
            ObjectInputStream ois = new ObjectInputStream(is);
            //输出流
            OutputStream os = so.getOutputStream();
            DataOutputStream dos = new DataOutputStream(os);
            try {
                while(true){
                    //读数据
                    Triangle r = (Triangle)ois.readObject();
                    System.out.println("接收成功");
                    //计算面积
                    String area = r.calculateArea();

                    //写数据
                    dos.writeUTF(area);
                    System.out.println("成功发送面积");
                }
            }catch(Exception e) {
                //关闭资源
                System.out.println(so.getRemoteSocketAddress()+"下线");
                ois.close();
                dos.close();
                so.close();
            }

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

    }
}

  • 15
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值