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();
}
}