------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ------
Java提供了InetAddress来代表IP地址,InetAddress类没有提供构造器,而是提供了如下两个静态方法来获取InetAddress实例。getByName(String host)方法据主机获取对应的InetAddress对象,getByAddress(byte[] addr)根据原始IP地址来获取对应的InetAddress对象,InetAddress提供了三个方法来获取实例对应的IP地址和主机名。String getCanonicalHostName()获取此IP地址的全限定域名,getHostAddress,获取此IP的地址字符串。
InetAddress ip=new InetAddress.getName("www.baidu.com");
ip.getHostAddress();
Socket就是为网络服务提供的一种机制,通信的两端都有Socket,网络通信其实就是Socket间的通信,数据就是在两个Socket间通过IO传输。
UDP是User Datagram Protocol的缩写,不用建立链路,是不可靠的协议,对于实时性要求很强的场合比较适用。使用DatagramSocket和DatagramPacket发送接收数据,第一步是建立发送端与接收端,第二步是建立数据包,第三步是调用Socket的发送接收方法,第四步是关闭Socket。发送与接收端是两个独立的程序。当客户端与服务器使用UDP协议的时候,实际上并没有明显的服务器与客户端,因为双方都需要建立一个DatagramSocket对象用于接收发送数据,然后使用DatagramPacket对象作为传输数据的载体。通常固定IP与端口的对象所在的程序称之为服务器。一旦创立了DatagramSocket实例之后,我们使用两个方法来接收发送数据,receive()与send()方法。
接收端的代码:
DatagramPacket packet=new DatagramPacket(buf,256);
socket.receive(packet);
发送端的代码:发送端的代码里有数据需要到达的目的地址,包括IP和端口,数据的发送时需要send方法来完成的。
DatagramPacket packet=new DatagramPacket(buf,length,address,port);
socket.send(packet);
我们知道在接收端接收到一些信息的时候,往往需要给发送端反馈一些信息,可是UDP传输是面向非连接的,我们需要调用以下方法来获取发送者的IP和端口。getAddress(),获取发送接收的IP地址,getPort()获取发送接收端口,getSocketAddress()返回此数据包的目标SocketAddress。
UDP也是要调用底层资源,所以我们在结束完了后记得关闭资源close方法。
下面以服务端的UDP代码来说明其协议的写法。
public class UDPServer {
private static final int PORT = 5000;
private DatagramSocket dataSocket;
private DatagramPacket dataPacket;
private byte receiveByte[];
private String receiveStr;
public UDPServer() {
Init();
}
public void Init() {
try {
dataSocket = new DatagramSocket(PORT);
receiveByte = new byte[1024];
dataPacket = new DatagramPacket(receiveByte, receiveByte.length);
receiveStr = "";
int i = 0;
while (i == 0)// 无数据,则循环
{
dataSocket.receive(dataPacket);
i = dataPacket.getLength();
// 接收数据
if (i > 0) {
<span style="color:#ff0000;"> // 指定接收到数据的长度,可使接收数据正常显示,开始时很容易忽略这一点
</span>
receiveStr = new String(receiveByte, 0, dataPacket.getLength());
System.out.println(receiveStr);
i = 0;// 循环接收
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String args[]) {
new UDPServer();
}
}
我们在建立了服务端后,就要建立客户端,为了两者的数据的传输,端口的代码需要尤为注意。
public class UDPClient {
private static final int PORT = 4561;
private DatagramSocket dataSocket;
private DatagramPacket dataPacket;
private byte sendDataByte[];
private String sendStr;
public UDPClient() {
Init();
}
public void Init() {
try {
// 指定端口号,避免与其他应用程序发生冲突
dataSocket = new DatagramSocket(PORT+1);
sendDataByte = new byte[1024];
sendStr = "UDP方式发送数据";
sendDataByte = sendStr.getBytes();
dataPacket = new DatagramPacket(sendDataByte, sendDataByte.length,
InetAddress.getByName("localhost"), PORT);
dataSocket.send(dataPacket);
} catch (SocketException se) {
se.printStackTrace();
} catch (IOException ie) {
ie.printStackTrace();
}
}
public static void main(String args[]) {
new UDPClient();
}
}
前面是UDP不可靠的链接方式,TCP作为面向链接的,通信之前需要建立连接的。我们通过一些方法来创建TCP服务器,Java中接收其他的通信实体连接请求的是SeverSocket,ServerSocket对象用于监听来自客户端的Socket连接,如果没有连接,它将一直处于等待状态。Socket accept();接收到客户端的socket的连接请求,该方法返回一个与客户端socket对应的socket,否则线程被阻塞。
ServerSocket(int port)用于指定端口来创建一个serversocket,因为调用了底层的资源,所以需要使用close来关闭serversocket .
ServerSocket ss=new ServerSocket();
while(true)
{
Socket s=ss.accept();
}
我们需要使用的Socket来进行通信 ,创建Socket(),Socket提供了两个方法来获取数据:InputStream getInputStream()返回该Socket对象对应的输入流,让程序通过该输入流从Socket中取出数据。同样的我们知道OutputStream getOutputStream()返回该Socket对象对象的输出流,让程序向socket输出数据。
下面我们基础测试里的一道题来说明接收与发送的代码
- public class ClientDemo {
- public static void main(String[] args) throws IOException {
-
- // 创建发送端Socket对象
- Socket s = new Socket("192.168.1.109", 10010);
-
- q: while (true) {
- // 封装键盘录入
- BufferedReader br = new BufferedReader(new InputStreamReader(
- System.in));
- // 把通道内的输出流封装为字符流
- BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
- s.getOutputStream()));
- String line = null;
- while ((line = br.readLine()) != null) {
- // 发送数据
- bw.write(line);
- // 换行
- bw.newLine();
- // 刷新数据
- bw.flush();
-
- // 判断结束标记
- if (line.equals("over")) {
- break q;
- }
-
- // 获取服务端发回的数据
- BufferedReader brReader = new BufferedReader(
- new InputStreamReader(s.getInputStream()));
- String str = null;
- while ((str = brReader.readLine()) != null) {
- // 将服务端发过来的数据输出到控制台
- System.out.println(str);
- break;
- }
-
- }
-
- }
- // 关闭资源
- s.close();
-
- }
- }
- public class ServerDemo {
- public static void main(String[] args) throws IOException {
- // 创建服务端对象,并指定好端口
- ServerSocket ss = new ServerSocket(10010);
-
- q: while (true) {
- // 监听客户端连接
- Socket s = ss.accept();
-
- // 对通道内的数据进行包装
- BufferedReader br = new BufferedReader(new InputStreamReader(
- s.getInputStream()));
- String line = null;
- while ((line = br.readLine()) != null) {
- // 判断结束标记
- if (line.equals("over")) {
- break q;
- }
-
- // 将得到的数据反转
- String data = reverseString(line);
- // 将反转后的数据发送给客户端
- BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
- s.getOutputStream()));
- bw.write("Server: " + data);
- bw.newLine();
- bw.flush();
-
- }
- }
- // 释放资源
- ss.close();
- }
-
- // 数据反转方法
- private static String reverseString(String line) {
-
- StringBuffer sb = new StringBuffer(line.length());
-
- for (int i = line.length() - 1; i >= 0; i--) {
- char c = line.charAt(i);
- sb.append(c);
- }
-
- return sb.toString();
- }
- }