第十九节,轻松学Java_网络编程

InetAddress

在这里插入图片描述
第一个方法用于获得表示指定主机的InetAddress对象,第二个方法用于获得本地主机的InetAddress对象。

TCP网络编程

在这里插入图片描述
UDP 通信与TCP 通信的区别在于:UDP 中只有发送端和接收端,不区分客户端与服务器端,计算机之间可以任意地发送数据;而TCP 通信是严格区分客户端与服务器端的,在通信时,必须先由客户端主动连接服务器端才能实现通信,服务器端不可以主动连接客户端,并且服务器端程序需要事先启动,等待客户端的连接。(先运行服务器端程序,再运行客户端程序)

在开发TCP 程序时,首先需要创建服务器端程序。JDK 的java.net 包中提供了ServerSocket 类,该类的实例对象可以实现一个服务器端的程序。

使用ServerSocket 对象可以实现服务器端程序,但只实现服务器端程序还不能完成通信,此时还需要一个客户端程序与之交互,为此JDK 提供了一个Socket 类。
Socket c常用方法:在这里插入图片描述

多线程的TCP网络编程

如果需要进行多次数据交互,就可以在程序中设置一个循环,不断地向对方发送请求,即可完成多次数据交互。同样,如果需要让服务器端同时响应多个客户端的请求,可以使用多线程的方法,也就是服务器端每接收到一个新的连接请求,就启动一个专门的线程与该客户端进行交互。

package com.test;

import java.util.Scanner;
import java.net.Socket;
import java.io.DataInputStream;
import java.io.DataOutputStream;
public class ClientTest {
	public static void main(String args[])
	{
		Scanner scanner = new Scanner(System.in);
		String input=null;
		Socket socket=null;
		DataInputStream in=null;
		DataOutputStream out=null;
		String serverIP="127.0.0.1"; //服务器地址
		int port=5050;//服务器端口
		
		try
		{  
			socket=new Socket(serverIP,port);//连接服务器
			in=new DataInputStream(socket.getInputStream());//创建输入流
			out=new DataOutputStream(socket.getOutputStream());//创建输出流
			System.out.println("请输入一个正整数的四则运算表达式:");
			
			while(scanner.hasNext())
			{
				input=scanner.nextLine();//从键盘输入一个待计算的四则运算表达式
				if (!input.equals("0"))
				{
					out.writeUTF(input);//向服务器端发送运算请求
					String result=in.readUTF();//等待读取运算结果
					System.out.println("服务器返回的计算结果:"+result);
					System.out.println("请输入一个正整数的四则运算表达式(输入0退出):");
				}
				else 
					break;//请求结束
			}
		}
		catch(Exception e)
		{
			System.out.println("与服务器连接中断");
		}
		finally
		{
			try//关闭网络连接
			{
				in.close();
				out.close();
				socket.close();
				System.out.println("连接结束");
			}
			catch(Exception e){}
		}
	}
}

package com.test;

import java.net.ServerSocket;
import java.net.Socket;
import java.io.IOException;
public class ServerTest{
	public static void main(String args[]) 
	{
		ServerSocket server_socket=null;
		Socket socket=null;
		int port=5050;
		
		while(true) 
		{
			try
			{  
				server_socket=new ServerSocket(port);
				System.out.println("服务器启动!");
			}
			catch(IOException e1) 
			{ 
				System.out.println("正在监听"); //ServerSocket对象不能重复创建
			} 
			
			try
			{  
				System.out.println("等待客户请求");
				socket=server_socket.accept();
				System.out.println("客户的地址:"+socket.getInetAddress()+":"+socket.getPort());
			} 
			catch (IOException e) 
			{
				System.out.println("正在等待客户");
			}
			
			if(socket!=null) 
			{ 
				new ThreadTest(socket); //为每个客户启动一个专门的线程  
			}
		} 
	}
}


package com.test;

import java.net.Socket;
import java.io.DataInputStream;
import java.io.DataOutputStream;
public class ThreadTest extends Thread{
	Socket socket=null;
	DataInputStream in=null;
	DataOutputStream out=null;
	String str;
	String response;
	String ip;
	int port;
	
	public ThreadTest(Socket socket)
	{
		this.socket=socket;
		start();
	}
	public void run()
	{
		try
		{
			in=new DataInputStream(socket.getInputStream());//创建输入流
			out=new DataOutputStream(socket.getOutputStream());//创建输出流
			ip=socket.getInetAddress().getHostAddress();//客户端IP地址
			port=socket.getPort();//客户端的端口号
			
			while (true)
			{
				str=in.readUTF();//获取客户端的表达式
				System.out.println("客户端"+ip+":"+port+"发送的请求内容:");
				System.out.println(str+"=?");
				
				if (str.equals("0"))
				{
					System.out.println("连接结束");
					break;
				}
				else
				{
					response =doComputer(str);//对表达式进行计算
					out.writeUTF(response);//响应计算结果
				}
			}
		}
		catch(Exception e)
		{
			System.out.println("连接结束");
		}
		finally
		{
			try
			{
				in.close();
				out.close();
				socket.close();
			}
			catch(Exception e){}
		}
	}
	public String doComputer(String str)
	{
		String input;
		String[] sym;
		String [] data;
		int a=0,b=0,result=0;
		input = str;
		data = input.split("\\D+");//分解表达式中的正整数
		sym = input.split("\\d+");//分解表达式中的运算符
		a = Integer.parseInt(data[0]);//第一个正整数
		b = Integer.parseInt(data[1]);//第二个正整数
		
		try
		{
			switch(sym[1])//判断运算符,完成相应的运算
			{
			case "+":
				result=a+b;break;
			case "-":
				result=a-b;break;
			case "*":
				result=a*b;break;
			case "/":
				result=a/b;
			}
			System.out.println("计算结果:"+input+"="+result);
			return String.valueOf(result);
		}
		catch(java.lang.ArithmeticException e)
		{
			System.out.println("数据错误!");
			return "数据错误!";
		}
	}
}

请输入一个正整数的四则运算表达式:
2+5
服务器返回的计算结果:7
请输入一个正整数的四则运算表达式(输入0退出):
6+3
服务器返回的计算结果:9
请输入一个正整数的四则运算表达式(输入0退出):

服务器启动!
等待客户请求
客户的地址:/127.0.0.1:10233
正在监听
等待客户请求
客户端127.0.0.1:10233发送的请求内容:
2+5=?
计算结果:2+5=7
客户端127.0.0.1:10233发送的请求内容:
6+3=?
计算结果:6+3=9
连接结束
在这里插入图片描述

UDP网络编程

使用DatagramSocket的实例对象就可以发送和接收DatagramPacket 数据包。
在这里插入图片描述

package com.test;

import java.net.DatagramSocket;
import java.net.DatagramPacket;
import java.net.InetAddress;
public class ClientTest {
	public static void main(String[] args)
	{
		DatagramSocket socket=null;
		DatagramPacket packet_send=null;
		DatagramPacket packet_receive=null;
		String server="127.0.0.1";//服务器端IP地址
		int port=5151;//服务器端口号
		String str="Hello,I am Client A";
		byte[] data=str.getBytes();//将发送信息转换成字节数组
		
		try
		{
			socket=new DatagramSocket();//创建连接socket对象
			InetAddress addr=InetAddress.getByName(server);//将服务器端IP地址封装成InetAddress对象
			packet_send=new DatagramPacket(data,data.length,addr,port);//创建数据包对象
			socket.send(packet_send);//向服务器端发送数据
			byte [] r=new byte[1024];//设置接收缓冲区
			packet_receive=new DatagramPacket(r,r.length);//创建数据包对象
			socket.receive(packet_receive);//接收数据包
			byte [] response=packet_receive.getData();//读取数据包中的数据信息
			int len=packet_receive.getLength();//获取数据长度
			String str1=new String (response,0,len);//将字节数据转换成字符串
			System.out.println("服务器响应的信息是:"+str1);
		}
		catch(Exception e)
		{
			System.out.println(e);
		}
		finally
		{
			socket.close();
		}
	}
}

package com.test;

import java.net.DatagramSocket;
import java.net.DatagramPacket;
import java.net.InetAddress;
public class ServerTest{
	public static void main(String[] args)
	{
		DatagramSocket socket=null;
		DatagramPacket packet_send=null;
		DatagramPacket packet_receive=null;
		int port=5151;//服务器监听端口
		try
		{
			socket=new DatagramSocket(port);//创建连接对象
			System.out.println("服务器启动!");
			byte [] r=new byte[1024];//创建缓存数组
			packet_receive=new DatagramPacket(r,r.length);//创建数据包对象
			socket.receive(packet_receive);//接收数据包
			InetAddress client_ip=packet_receive.getAddress();//客户机地址
			int client_port=packet_receive.getPort();//客户机端口号
			byte [] data=packet_receive.getData();//客户机字节数据
			int len=packet_receive.getLength();//数据有效长度
			String str1=new String (data,0,len);//将字节数据转换成字符串
			System.out.println("客户机"+client_ip+":"+client_port+"\n发送的信息是:"+str1);
			String response="Hello,I am Server B";
			byte [] s=response.getBytes();
			packet_send=new DatagramPacket(s,s.length,client_ip,client_port);//创建响应数据包对象
			socket.send(packet_send);//发送响应数据包
		}
		catch(Exception e)
		{
			System.out.println(e);
		}
		finally
		{
			socket.close();
		}
	}
}

广播数据播报

要实现广播,需要使用java.net.MulticastSocket 类。该类是一种基UDP 的DatagramSocket,用于发送和接收IP 多播包。该类的对象可以加入Internet 上其他多播主机的“组”中。类DatagramSocket 的常用方法如下:
(1)MulticastSocket(int port) throws IOException:创建一个多播套接字,并将其绑定到指定端口上。
(2)MulticastSocket(SocketAddress bindaddr) throws IOException:创建一个多播套接字,并将其绑定到一个指定套接字地址上。
(3)public void joinGroup(InetAddress mcastaddr) throws IOException:将多播套接字加入指定多播组。
(4)public void leaveGroup(InetAddress mcastaddr) throws IOException:将多播套接字移出多播组。
(5)public void setTimeToLive(int ttl) throws IOException:设置在此MulticastSocket 上发出的多播数据包的默认生存时间。

ttl 参数设置数据包最多可以跨过多少个网络:
 当ttl 为0 时,数据包应停留在本地主机。
 当ttl 为1 时,数据包应发送到本地局域网。
 当ttl 为32 时,数据包应发送到本站点的网络上。
 当ttl 为64 时,数据包应保留在本地区。
 当ttl 为128 时,数据包应保留在本大洲。
 当ttl 为255 时,数据包可以发送到所有地方。

package com.test;

import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.DatagramPacket;
import java.io.IOException;
class Broadcast
{
	public void send()
	{
		String msg="Hello,This is Broadcast Message";//多播的内容
		int port=6666;//多播端口
		InetAddress group=null;
		MulticastSocket ms=null;
		
		try
		{
			group=InetAddress.getByName("224.1.1.1");//创建多播地址
			ms=new MulticastSocket(port);//创建多播套接字
			ms.joinGroup(group);//将套接字加入多播地址
			ms.setTimeToLive(1);//设置数据报发送范围为本地
			DatagramPacket dp=new DatagramPacket(msg.getBytes(),msg.length(),group,port);//创建待发送的数据报
			ms.send(dp);//发送数据报
		}
		catch(IOException e)
		{
			System.out.println(e);
		}
		finally
		{
			ms.close();//关闭套接字
		}
	}
}

public class BroadcastTest 
{
	public static void main(String[] args)
	{
		new Broadcast().send();
	}
}

package com.test;

import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.DatagramPacket;
import java.io.IOException;
class Receiver
{
	public void receive()
	{
		byte [] data=new byte[1024];//数据缓存区
		int port=6666;//多播端口
		InetAddress group=null;
		MulticastSocket ms=null;
		
		try
		{
			group=InetAddress.getByName("224.1.1.1");//创建多播地址
			ms=new MulticastSocket(port);//创建多播套接字
			ms.joinGroup(group);//将套接字加入多播地址
			DatagramPacket dp = new DatagramPacket(data, data.length,group, port);//创建待接收的数据报
			ms.receive(dp);//接收数据报
			String msg=new String(dp.getData(),0,dp.getLength());
			System.out.println("接收的广播数据为:"+msg);
		}
		catch(IOException e)
		{
			System.out.println(e);
		}
		finally
		{
			ms.close();//关闭套接字
		}
	}
}

public class ReceiverTest
{
	public static void main(String[] args)
	{
		new Receiver().receive();
	}
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

身影王座

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值