一、网络模型
二、通信协议三要素
1.IP地址:
InetAddress类:其中IP地址与java相关的类为InetAddress类。InetAddress类无构造函数,可以通过静态方法getLocalHost()方法获取本机的InetAddress对象。
常用方法如下:
static InetAddress getByName(String host)
//获取指定主机的IP和主机名。(最好用ip地址去获取,主机名需要解析)
static InetAddress[] getAllByName(String host)
//在给定主机名的情况下,根据系统上配置的名称服务返回IP地址所组成的数组。返回对象不唯一时,用此方法。
String getHostAddress()
//返回IP地址字符串文本形式,以IP地址为主。
String getHostName()
//返回IP地址主机名。
练习这些常用方法:
package com.itheima;
/*
* 练习使用InetAddress类的一些常用方法:
* 包括static修饰的类方法 InetAddress.getLocalHost(),InetAddress.getByName(String host),InetAddress.getAllbyName(String host)
* 以及对象方法getHostAddress(),getHostName()。
*/
import java.net.*;
public class InetAddressPractice {
public static void main(String[] args)throws Exception {
//获取本机的InetAddress对象
InetAddress myInetAdd = InetAddress.getLocalHost();
//获取本机的IP地址(字符串形式)和主机名
String myIPAddress = myInetAdd.getHostAddress();
String myHostName = myInetAdd.getHostName();
System.out.println("my host ip is "+myIPAddress+",Name is "+myHostName);
//获取给定指定Ip地址的主机的InetAddress对象
InetAddress givenInetAdd = InetAddress.getByName("221.236.31.210");
System.out.println("given host Name is "+ givenInetAdd.getHostName());
//获取给定指定域名的主机的InetAddress对象
InetAddress givenInetAddName[] = InetAddress.getAllByName("www.baidu.com");
for(InetAddress inet : givenInetAddName){
System.out.println("given host ip is "+ inet.getHostAddress());
}
}
}
2.端口号:
用于标识进程的逻辑地址;
有效端口:0~65536,系统使用或保留的端口是0~1024。
3.网络协议:
通信规则,包含TCP和UDP协议。4.Socket对象:
JAVA与网络编程最基础的对象。
a、它被称为插座,是网络服务提供的一种机制;
b、通信两端都要有Socket,才能建立服务;
c、网络通信其实就是Socket间的通信,数据在两个Socket间通过IO传输。
三、UDP编程
概念:
特点:
a、面向无连接,即将数据及源和目的封装成数据包中,不建立链接的发送
b、每个数据包的大小限制在64K之内
c、因无连接,是不可靠的协议
d、不建立连接,速度快。
步骤:
b、提供数据,并将数据封装到数据包中
c、通过socket服务的发送功能,将数据包发送出去
d、关闭资源
2)接收数据:
a、定义UDPSocket服务。通常会监听一个端口,其实就是给这个接收网路应用程序定义数字标识,方便于明确哪些数据过来该应用程序可以处理。
b、定义一个数据包,用来存储接收到的字节数据,因为数据包对象中有更多功能可以提取字节数据中的不同数据信息。
c、通过socket服务的receive方法接收到的数据存入已定义好的数据包中
d、通过数据包对象的特有功能,将这些不同的数据取出,打印在控制台上
e、关闭资源
在定义接收数据的方法中,仍会在DatagramSocket构造函数中传入DatagramPacket的参数,这是因为收到的数据太多,需要解析,通过将数据封装成对象,易于解析,所以需要传入参数。
1、发送端与接收端是两个独立的运行程序。
2、在发送端,要在数据包对象中明确目的地IP及端口。
3、在接收端,要指定监听的端口。
package com.itheima;
/*
* 设置一个通过UDP传输协议的发送端,并发送一段数据
*/
import java.net.*;
public class MySendProgramUDP {
public static void main(String[] args)throws Exception {
//创建数据报套接字对象
DatagramSocket sendSocket = new DatagramSocket();
//创建数据包对象
byte datebyte[] = "this is send content".getBytes();
DatagramPacket dataPacket = new DatagramPacket(datebyte,datebyte.length,InetAddress.getByName("127.0.0.1"),3002);
//发送数据
sendSocket.send(dataPacket);
sendSocket.close();
}
}
接收端:
/*
* 接收一段通过UDP协议发送的数据
*/
import java.net.*;
public class MyReceiveProgramUDP {
public static void main(String[] args)throws Exception {
while(true){
//创建一个DatagramSocket对象
DatagramSocket receiveSocket = new DatagramSocket(3002);
//创建一个接收数据的数据包对象
byte bytes[] = new byte[1024];
DatagramPacket receivePacket = new DatagramPacket(bytes,bytes.length);
receiveSocket.receive(receivePacket);
System.out.println("content is:"+new String(receivePacket.getData(),0,receivePacket.getLength()));
receiveSocket.close();
}
}
}
练习:
package com.itheima;
/**
* 开发一个即时聊天小程序
*/
import java.net.*;
import java.io.*;
class Send implements Runnable{
private DatagramSocket ds ;
public Send(DatagramSocket ds){
this.ds = ds;
}
public void run(){
BufferedReader in = null;
DatagramPacket dp = null;
try{
in = new BufferedReader(new InputStreamReader(System.in));
String str = null;
while((str=in.readLine())!=null){
dp = new DatagramPacket(str.getBytes(),str.length(),InetAddress.getByName("192.168.103.23"),10000);
ds.send(dp);
if(str.equals("886"))
break;
}}catch(IOException e){e.printStackTrace();}
finally{
if(in!=null)
try {
in.close();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
if(ds!=null)
ds.close();
}
}
}
class Receive implements Runnable{
private DatagramSocket ds;
public Receive(DatagramSocket ds){
this.ds = ds;
}
public void run(){
byte bs[] = new byte[1024];
DatagramPacket dp = new DatagramPacket(bs,bs.length);
try{
while(true){
ds.receive(dp);
String str = new String(dp.getData(),0,dp.getLength());
System.out.println(str);
if(str.equals("886"))
break;
}}catch(IOException e){}
finally{
if(ds !=null)
ds.close();
}
}
}
public class Chat{
public static void main(String[] args){
try {
new Thread(new Send(new DatagramSocket())).start();
new Thread(new Receive(new DatagramSocket(10000))).start();
} catch (SocketException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
四、TCP协议
概念:
特点:
a、面向连接,在建立连接后,形成传输数据的通道
b、在连接中进行大数据量的传输
c、通过三次握手完成连接,是可靠的协议
d、必须建立连接,效率稍慢
三次握手:第一次本方发送请求,第二次对方确认连接,第三次本方再次确认连接成功。
步骤:
客户端:
通过查阅Socket对象的API文档,发现在该对象在建立时,就可去连接指定主机,因为TCP是面向连接的,所以在建立Socket服务时,就要有服务端存在,并连接成功,形成通路后,再通过该通道进行数据的传输。
1)创建Socket服务,并指定要连接的主机端口。通路一建立,就会产生Socket流(包括输入流和输出流),通过方法获取
2)为了发送数据,应获取Socket中的输出流,如果要接收服务端的反馈信息,还需要获取Socket的输入流
3)通过输出流的write()方法将要发送的数据写入到流中
4)关闭Socket流资源
服务端:
服务器套接字等待请求通过网络传入。它基于该请求执行某些操作,然后可能向请求者返回结果。需监听一个端口。
1)建立服务端的Socket服务,并监听一个端口。通过ServerSocet带端口参数的构造函数
2)获取连接过来的客户对象,通过ServerSocket的accept()方法,此方法是阻塞式的,如果服务端没有连接到就会一直等待
3)客户端如果发过来数据,则服务端要使用对应的客户端对象,并获取到该客户端对象的读取流读取发过来的数据,并输出到指定目的地。
4)关闭服务端(可选)。一般服务端是常开的,因为在实际应用中,随时有客户端在请求连接和服务。但这里需要定时关闭客户端对象流,避免某一个客户端长时间占用服务器端。
package com.itheima;
//ServerSocket类.accept方法获取Socket对象,使用Socket的方法获取输出流和输入流进行编程
import java.net.*;
import java.io.*;
public class MyServer{
public static void main(String[] args)throws IOException{
ServerSocket ss = new ServerSocket(10001);
Socket socket = ss.accept();
OutputStream out = socket.getOutputStream();
out.write("hello World by TCP transmission".getBytes());
out.close();
}
}
package com.itheima;
import java.net.*;
import java.io.*;
public class MyClient {
public static void main(String[] args)throws IOException{
Socket socket = new Socket("192.168.103.45",10001);
InputStream in = socket.getInputStream();
byte bs[] = new byte[1024];
int len;
while((len = in.read(bs))!=-1){
System.out.print(new String(bs,0,len));
}
System.out.println();
socket.close();
}
}
练习:
package com.itheima;
/*
* 传输图片的服务器端
*/
import java.net.*;
import java.io.*;
public class PhotographServer {
public static void main(String[] args)throws IOException {
InputStream in;
ServerSocket ss = new ServerSocket(10003);
Socket socket = ss.accept();
in = new FileInputStream("a.jpg");
OutputStream out = socket.getOutputStream();
byte bs[] = new byte[1024];
int len;
while((len = in.read(bs))!=-1){
out.write(bs,0,len);
}
in.close();
ss.close();
}
}
package com.itheima;
/*
* 传输图片的客户机端
*/
import java.net.*;
import java.io.*;
public class PhotographClient {
public static void main(String[] args)throws IOException{
Socket socket = new Socket("192.168.103.45",10003);
InputStream in = socket.getInputStream();
OutputStream out = new FileOutputStream("b.jpg");
byte bs[] = new byte[1024];
int len;
while((len = in.read(bs))!=-1){
out.write(bs,0,len);
}
out.close();
socket.close();
}
}