网络编程
一.java提供网络功能的四大类
1.InetAddress:用于标识网络上的硬件资源。
2.URL:统一资源定位符,通过URL可以直接读取或写入网络上的数据。
3.Sockets:使用TCP协议实现网络通信的Socket相关的类。
4.Datagram:使用UDP协议,将数据保存在数据报中,通过网络进行传送。
二.InetAddress:无构造方法,通过静态方法获取实例
例如:InetAddress address = InetAddress.getLocalHost();//返回本地主机
常用方法 | |
byte[] | getAddress() 返回此 InetAddress 对象的原始 IP 地址。 |
static InetAddress[] | getAllByName(String host) 在给定主机名的情况下,根据系统上配置的名称服务返回其 IP 地址所组成的数组。 |
static InetAddress | getByAddress(byte[] addr) 在给定原始 IP 地址的情况下,返回 InetAddress 对象。 |
static InetAddress | getByAddress(String host, byte[] addr) 根据提供的主机名和 IP 地址创建 InetAddress。 |
static InetAddress | |
getCanonicalHostName() 获取此 IP 地址的完全限定域名。 | |
getHostAddress() 返回 IP 地址字符串(以文本表现形式)。 | |
getHostName() 获取此 IP 地址的主机名。 | |
static InetAddress | getLocalHost() 返回本地主机。 |
boolean | isReachable(int timeout) 测试是否可以达到该地址。 |
boolean | isReachable(NetworkInterface netif, int ttl, int timeout) 测试是否可以达到该地址。 |
toString() 将此 IP 地址转换为 String。 |
测试代码:
package javaapplication12;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author Administrator
*/
public class JavaApplication12 {
public void test() throws UnknownHostException {
// TODO code application logic here
InetAddress address = InetAddress.getLocalHost();
System.out.println("计算机名"+address.getHostName());
System.out.println("IP地址:"+address.getHostAddress());
byte[] bytes = address.getAddress();
System.out.println("字节数组形式的IP:"+Arrays.toString(bytes));
System.out.println(address);
InetAddress address2 = InetAddress.getByName("192.168.0.106");
System.out.println("计算机名"+address2.getHostName());
System.out.println("IP地址:"+address2.getHostAddress());
}
public static void main(String[] args) {
try {
JavaApplication12 ja = new JavaApplication12();
ja.test();
} catch (UnknownHostException ex) {
Logger.getLogger(JavaApplication12.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
运行结果:
计算机名DESKTOP-GKGBN4L
IP地址:169.254.226.146
字节数组形式的IP:[-87, -2, -30, -110]
DESKTOP-GKGBN4L/169.254.226.146
计算机名192.168.0.106
IP地址:192.168.0.106
三.URL详解
URL 代表一个统一资源定位符,它是指向互联网“资源”的指针。资源可以是简单的文件或目录,也可以是更为复杂的对象的引用,例如对数据库或搜索引擎的查询。
构造方法摘要 | |
| |
URL(String protocol, String host, int port, String file) 根据指定 protocol、host、port 号和 file 创建 URL 对象。 |
|
URL(String protocol, String host,int port, String file, URLStreamHandler handler)根据指定protocol、host、port 号、file 和 handler 创建 URL 对象。 |
|
URL(String protocol, String host, String file) 根据指定的 protocol 名称、host 名称和 file 名称创建 URL。 |
|
| |
URL(URL context, String spec, URLStreamHandler handler) 通过在指定的上下文中用指定的处理程序对给定的 spec 进行解析来创建 URL。 |
|
常用方法摘要 | |
getContent() 获取此 URL 的内容。 | |
getContent(Class[] classes)获取此 URL 的内容。 | |
int | getDefaultPort() 获取与此 URL 关联协议的默认端口号。 |
getFile() 获取此 URL 的文件名。 | |
getHost() 获取此 URL 的主机名(如果适用)。 | |
getPath() 获取此 URL 的路径部分。 | |
int | getPort() 获取此 URL 的端口号。 |
getProtocol() 获取此 URL 的协议名称。 | |
getQuery() 获取此 URL 的查询部分。 | |
getRef() 获取此 URL 的锚点(也称为“引用”)。 | |
openConnection() 返回一个 URLConnection 对象,它表示到 URL 所引用的远程对象的连接。 | |
openConnection(Proxy proxy) 与 openConnection() 类似,所不同是连接通过指定的代理建立;不支持代理方式的协议处理程序将忽略该代理参数并建立正常的连接。 | |
openStream() 打开到此 URL 的连接并返回一个用于从该连接读入的 InputStream。 | |
toString() 构造此 URL 的字符串表示形式。 |
测试代码:
package javaapplication12;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
public class TestURl {
public static void main(String[] args){
try {
URL imooc = new URL("http://www.imooc.com");
URL url = new URL(imooc,"/index.html?usename =tom#test");//?后面表示参数,#后面表示锚点
System.out.println("协议:"+url.getProtocol());
System.out.println("主机:"+url.getHost());
//如果未指定端口号,则使用默认的端口号,此时getPort()方法返回-1
System.out.println("端口号:"+url.getPort());
System.out.println("文件路劲:"+url.getPath());
System.out.println("文件名:"+url.getFile());
System.out.println("查询字符串:"+url.getQuery());
URL urlt = new URL("http://www.qq.com");
InputStream is = urlt.openStream();
InputStreamReader isr = new InputStreamReader(is,"utf-8");
BufferedReader br = new BufferedReader(isr);
String data = br.readLine();
while(data!=null){
System.out.println(data);
data = br.readLine();
}
br.close();
isr.close();
is.close();
} catch (Exception ex) {
ex.getStackTrace();
}
}
}
四.TCP通信
#TCP/IP协议:三次握手,四次挥手。详细看在链接学习:点击打开链接
1.实现服务器:
a.建立服务器套接字:ServerSocket serverSocket = new ServerSocket(int port);
b.建立监控端口:Socket socket = serverSocket.accept();//用于告诉服务器不停地等待,直到有客户端连接到这个端口。一旦有客户端请求连接,就会返回连接已经建立的Socket对象。
c.从Socket对象得到输入输出流:
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
d.关闭连接进来的套接字:socket.close();
为多个客户端服务思想:利用多线程实现,循环调用accept()方法,为每个客户请求创建单独的Socket线程对话
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* 给予TCP协议的Socket通讯,实现用户登录 服务端
*/
public class Server {
public static void main(String[] args) {
try {
ServerSocket serverSocket = new ServerSocket(8808);
System.out.println("***服务器即将启动,等待客户端的连接***");
Socket socket = null;//调用accept()方法开始监听
int count = 0;
while (true) {
socket = serverSocket.accept();
ServerThread serverThread = new ServerThread(socket);
serverThread.start();
count++;
System.out.println("客户端的数量:"+count);
InetAddress address = socket.getInetAddress();
System.out.println("IP地址:"+address.getHostAddress());
}
} catch (IOException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
class ServerThread extends Thread {//利用多线程为多个客户端服务
Socket socket = null;
public ServerThread(Socket socket) {
this.socket = socket;
}
public void run() {
InputStream is = null;
InputStreamReader isr = null;
BufferedReader br = null;
OutputStream os = null;
PrintWriter pw = null;
try {
is = socket.getInputStream();
isr = new InputStreamReader(is);
br = new BufferedReader(isr);
String info = null;
while ((info = br.readLine()) != null) {
System.out.println("我是服务器,客户端说:" + info);
}
socket.shutdownInput();//关闭输入流
os = socket.getOutputStream();
pw = new PrintWriter(os);
pw.write("欢迎您!");
pw.flush();
} catch (IOException ex) {
ex.getStackTrace();
} finally {
try {
if (pw != null) {
pw.close();
}
if (os != null) {
os.close();
}
if (br != null) {
br.close();
}
if (isr != null) {
isr.close();
}
if (is != null) {
is.close();
}
if (socket != null) {
socket.close();
}
} catch (IOException ex) {
ex.getStackTrace();
}
}
}
}
2.实现客户端:
a.创建客户端Socket,指定服务器地址和端口:Socket socket = new Socket(InetAddress address, int port);
b.从Socket对象得到输入输出流:
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
c.关闭与连接客户端的套接字:socket.close();
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
/**
* 客户端
*/
public class Client {
public static void main(String[] args) {
try {
//1.创建客户端Socket,指定服务器地址和端口
Socket socket = new Socket("localhost", 8808);
OutputStream os = socket.getOutputStream();
PrintWriter pw = new PrintWriter(os);
pw.write("用户名:javk;密码:123");
pw.flush();//要记住!!!
socket.shutdownOutput();
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String info = null;
while ((info = br.readLine()) != null) {
System.out.println("我是客户端,服务端说:" + info);
}
socket.shutdownInput();//
br.close();
isr.close();
is.close();
pw.close();
os.close();
socket.close();
} catch (IOException ex) {
ex.getStackTrace();
}
}
}
五.UDP通信
1.实现服务器:
a.创建DatagramSocket,制定端口号: DatagramSocket socket = new DatagramSocket(int port);
b.创建数据报,用于接收客户端发送的数据:
byte[] data = new byte[1024];//指定数据报的大小
DatagramPacket packet = new DatagramPacket(data,data.length);
c.接收客户端发送的信息:socket.receive(packet);//此方法在接收数据报之前一直堵塞
d.向客户端发送信息:创建数据报,包含发送的信息
DatagramPacket packet2 = new DatagramPacket(byte[] data,int data_length,Inetaddress address,int port);
socket.send(packet2);
e.关闭连接:socket.close();
同样使用多线程实现为多个客户端服务。
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* 服务器端,实现基于UDP的用户登录
*/
public class UDPServer {
public static void main(String[] args) throws SocketException, IOException {
System.out.println("服务器已经启动......");
//1.创建服务器端DatagramSocket,指定端口
DatagramSocket socket = new DatagramSocket(8213);
for(int i = 0;i<100;i++){
UDPThread thread = new UDPThread(socket);
thread.start();
}
}
}
class UDPThread extends Thread{
private DatagramSocket socket = null;
public UDPThread(DatagramSocket socket){
this.socket = socket;
}
public void run(){
//创建数据报,用于接收客户端发送的数据
byte[] data = new byte[1024];//指定数据报的大小
DatagramPacket packet = new DatagramPacket(data,data.length);
//接收客户端发送的信息
try {
socket.receive(packet);//此方法在接收数据报之前一直堵塞
} catch (IOException ex) {
Logger.getLogger(UDPThread.class.getName()).log(Level.SEVERE, null, ex);
}
String info = new String(data,0,packet.getLength());
System.out.println("我是服务器,客户端说:"+info);
/*
*向客户端发送消息
*/
InetAddress address = packet.getAddress();
int port = packet.getPort();
byte[] data2 = "欢迎您!".getBytes();
//创建数据报,包含发送的信息
DatagramPacket packet2 = new DatagramPacket(data2,data2.length,address,port);
try {
socket.send(packet2);
} catch (IOException ex) {
Logger.getLogger(UDPThread.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
2.实现客户端:
a.创建DatagramSocket,用于发送和接收信息:DatagramSocket socket = new DatagramSocket();
b.指定服务器的地址、端口号和数据,创建数据报,用于发送信息:
DatagramPacket packet = new DatagramPacket(byte[] data,int data_length,InetAddress address,int port);
socket.send(packet);
c.创建数据报,用于接收客户端发送的数据:
byte[] data = new byte[1024];//指定数据报的大小
DatagramPacket packet2 = new DatagramPacket(data,data.length);
socket.receive(packet2);//此方法在接收数据报之前一直堵塞
d.关闭连接:socket.close();
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
/**
*客户端
*/
public class UDPClient {
public static void main(String[] args) throws UnknownHostException, SocketException, IOException {
System.out.println("客户端启动!");
//1.指定服务器的地址、端口号和数据
InetAddress address = InetAddress.getByName("localhost");
int port = 8213;
byte[] data = "用户名:army,密码:789".getBytes();
//2.创建数据报,包含发送的信息
DatagramPacket packet = new DatagramPacket(data,data.length,address,port);
DatagramSocket socket = new DatagramSocket();
socket.send(packet);
/*
*接收服务端发送的信息
*/
byte[] data2 = new byte[1024];
DatagramPacket packet2 = new DatagramPacket(data2,data2.length);
socket.receive(packet2);//此方法在接收数据报之前一直堵塞
String reply = new String(data2,0,packet2.getLength());
System.out.println("我是客户端,服务器端说:"+reply);
socket.close();
}}
六.TCP与UDP的区别
1.基于连接与无连接。
2.对系统资源的要求,TCP较多,UDP较少。
3.UDP程序结构较简单,TCP较复杂。
4.TCP是流模式,UDP是数据报模式。
5TCP保证数据正确性,UDP可能丢包,TCP保证数据顺序,UDP不保证。