网络编程
网络编程是指编写运行在多个设备(计算机)的程序,这些设备都通过网络连接起来。 ava提供的网络类库,可以实现网络连接,联网的底层细节被隐藏在java的本机系统里,由jvm控制
1. IP和端口号
1.1 IP的理解
唯一的标识Internet上的计算机 本地回环地址():127.0.0.1/localhost
IP地址分类1:IPV4和IPV6 IPV4: 4个字节组成,4个0-255,大概42亿,30亿都在北美,亚洲4亿.2011年初 已经用尽…例如十进制写法:192.168.0.1
IPV6: 128位(16个字节),写成8个无符号整数,每个整数用四个十六进制位表示 数之间冒号隔开 例如: 3ffe: 3ffe: 3ffe: 3ffe: 3ffe: 3ffe: 3ffe: 3ffe
IP地址分类2:公网地址(万维网使用)和私有地址(局域网使用) 192.168开头的就是私有地址,即范围为:192.168.0.0~192.168.255.255
Internet上的主机有两种方式表示地址 域名(hostName):www.baidu.com IP地址(hostAddress):202.164.35.10
域名解析 域名容易记忆,当在连接网络时输入一个主机的域名后,域名服务器(DNS)负责将域名转化为IP地址,这样才能和主机建立连接
1.2 端口号的理解
端口号标识正在计算机上运行的进程(程序), 被规定为一个16位的整数0-65535 不同的进程有不同的端口号
端口分类: 公认端口: 0-1023(被预先定义的服务通信占用例如HTTP占用端口80,FTP占用的端口21) 注册端口: 1024-49151(Tomcat占用端口8080,MySQL占用端口3306,Oracle占用端口1521等) 动态/私有端口: 49152-65535
端口号与IP地址的组合得出一个网络套接字:Socket
1.3 InetAddress类
InetAddress类主要表示IP地址,两个子类Inet4Address Inet6Address
方法:
-
static InetAddress getByAddress(byte[] addr) 在给定原始 IP 地址的情况下,返回 InetAddress 对象。 -
static InetAddress getByAddress(String host, byte[] addr) 根据提供的主机名和 IP 地址创建 InetAddress。 -
static InetAddress getByName(String host) 在给定主机名的情况下确定主机的 IP 地址。 -
String getHostAddress() 返回 IP 地址字符串(以文本表现形式)。 -
String getHostName() 获取此 IP 地址的主机名。 -
static InetAddress getLocalHost() 返回本地主机。 -
String toString() 将此 IP 地址转换为 String。
public static void main(String[] args) {
try {
InetAddress inte1=InetAddress.getByName("www.baidu.com");
System.out.println("inte1"+inte1);
InetAddress[] intes=InetAddress.getAllByName("www.baidu.com");
for(InetAddress i:intes){
System.out.println("百度IP地址为:"+i.getHostAddress());
}
InetAddress inte2=InetAddress.getByName("14.215.177.39");
System.out.println("inte2"+inte2);
InetAddress inte3=InetAddress.getLocalHost();
System.out.println("主机名:"+inte3.getHostName());
System.out.println("ip地址:"+inte3.getHostAddress());
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
2. 网络协议
2.1 TCP
TCP(英语:Transmission Control Protocol,传输控制协议) 是一种面向连接的、可靠的、基于字节流的传输层通信协议,TCP 层是位于 IP 层之上,应用层之下的中间层。TCP 保障了两个应用程序之间的可靠通信。通常用于互联网协议,被称 TCP / IP。
-
使用TCP协议前,必须先建立TCP连接,形成传输数据通道 -
传输前,采用"三次握手"方式,点对点通信,是非常可靠 -
TCP协议进行通信的两个应用进程:客户端 服务端 -
在连接中可以进行大数据传输,数据传输完毕后,需要释放连接,效率低
2.2 UDP
UDP (英语:User Datagram Protocol,用户数据报协议),位于 OSI 模型的传输层。一个无连接的协议。提供了应用程序之间要发送数据的数据报。由于UDP缺乏可靠性且属于无连接协议,所以应用程序通常必须容许一些丢失、错误或重复的数据包。
- 将数据/源/目标封装成数据包,不需要建立连接
- 每个数据报的大小限制在64k内
- 发送方不管对方是否准备好,接收方收到也不会确认,故是不可靠的
- 可以广播发送
- 发送数据结束时候无需释放资源,开销小,速度快
2.3 Socket (套接字)编程
网络上具有唯一标识的IP地址和端口号组合在一起构成唯一识别的标识符套接字 套接字使用TCP提供了两台计算机之间的通信机制。
Socket原理机制 通信的两端(客户端/服务端)都有socket,网络通信其实就是Socket通信,数据在两个Socket间通过IO通信
使用套接字建立TCP连接步骤:
-
服务器实例化一个 ServerSocket 对象,表示通过服务器上的端口通信。 -
服务器调用 ServerSocket 类的 accept() 方法,该方法将一直等待,直到客户端连接到服务器上给定的端口。 -
服务器正在等待时,一个客户端实例化一个 Socket 对象,指定服务器名称和端口号来请求连接。 -
Socket 类的构造函数试图将客户端连接到指定的服务器和端口号。如果通信被建立,则在客户端创建一个 Socket 对象能够与服务器进行通信。 -
在服务器端,accept() 方法返回服务器上一个新的 socket 引用,该 socket 连接到客户端的 socket。
案例: 使用多线程的方式
- 服务器端创建ServerSocket对象,循环调用accept()等待客户端连接
- 客户端创建一个Socket并请求和服务端连接
- 服务端接收请求,创建Socket与该客户端建立专线连接
- 建立连接的两个socket在一个单独的线程上对话
- 服务器端继续等待新的连接
服务器
public void action() throws IOException {
ServerSocket server=new ServerSocket(8099);
System.out.println("服务器已经启动,等待客户端连接.....");
while(true){
Socket client=server.accept();
new Thread(new QQClientThread(client)).start();
}
}
public static void main(String[] args) throws IOException {
QQServer server=new QQServer();
server.action();
}
}
class QQClientThread implements Runnable{
Socket client;
public QQClientThread(Socket client){
this.client=client;
}
@Override
public void run() {
try {
InputStream in=client.getInputStream();
OutputStream out=client.getOutputStream();
BufferedReader reader=new BufferedReader(new
InputStreamReader(in,"utf-8"));
PrintWriter pw=new PrintWriter(new
OutputStreamWriter(out,"utf-8"),true);
String name=reader.readLine();
pw.println("欢迎来到吴签选妃群!请踊跃发言,提高选中率!");
String line;
while((line=reader.readLine())!=null){
System.out.println(line);
pw.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
客户端
public void action() throws IOException {
Socket socket=new Socket("localhost",8099);
InputStream in=socket.getInputStream();
OutputStream out=socket.getOutputStream();
new ReadFromServer("都某竹", in).start();
new WriteToServer("都某竹",out).start();
}
public static void main(String[] args) throws IOException {
QQClient client=new QQClient();
client.action();
}
}
class ReadFromServer extends Thread{
String name;
InputStream in;
public ReadFromServer(String name,InputStream in){
this.in=in;
this.name=name;
}
@Override
public void run(){
try {
BufferedReader reader=new BufferedReader(
new InputStreamReader(in,"UTF-8"));
String line;
while((line=reader.readLine())!=null){
System.out.println(line);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
class WriteToServer extends Thread{
String name;
OutputStream out;
public WriteToServer(String name,OutputStream out){
this.out=out;
this.name=name;
}
@Override
public void run(){
try {
Scanner key =new Scanner(System.in);
PrintWriter pw=new PrintWriter(new
OutputStreamWriter(out,"utf-8"),true);
pw.println(name);
while(true){
String line=key.nextLine();
pw.println(name+"说:"+line);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
|