网络通讯要素
传输协议
IP(Ineternet Protocol)地址
端口号
传输协议:TCP(Transfer Control Protocol)/UDP
IP地址:分4段,每一段一个字节,一个字节所能表示的最大数为2^8=256,因为从0计算,所以最大数为255
127.0.0.1是本地回环地址,测试网卡用的,ping 127.0.0.1
局域网中,处于一个IP段的机器可以通讯
端口:0~65536,通常0~1024被系统保留
常见端口
Web端口 80
TomCat 8080
MySQL 3306
网络模型
OSI参考模型
TCP/IP参考模型
数据依次从上往下封包,通过物理层发送出去,接收到被封包的数据,依次从下往上拆包
在TCP/IP参考模型中各层对应的协议
应用层:HTTP/FTP协议
传输层:TCP/UDP协议
网际层:IP协议
InetAddress
InetAddress表示IP类,可以生成IP对象
通过InetAddress的静态方法获取InetAddress对象(InetAddress无构造函数)
static InetAddress getLocalHost() //获取本机IP对象
static InetAddress getByName(String host) //通过主机名或者IP地址字符串获取IP对象
static InetAddress[] getAllByName(String host) //百度不止一个主机,此方法可以获取所有的主机
Method:
String getHostAddress() //获取IP地址
String getHostName() //获取主机名,不一定可以解析出来
import java.net.InetAddress;
/**
获取本机的InetAddress对象
*/
class InetAddressTest2
{
public static void main(String[] args) throws Exception
{
//获取本地主机的IP对象(包括主机名称和主机地址)
InetAddress i = InetAddress.getLocalHost();
System.out.println("本地主机IP对象:" + i.toString());
//获取主机名称
String hostName = i.getHostName();
//获取主机地址
String hostAddress = i.getHostAddress();
//打印主机名称和地址
System.out.println("主机名:" + hostName + "\n主机地址:" + hostAddress);
}
}
TCP和UDP
TCP特点:
需要建立连接,通过三次握手完成连接,是可靠协议。但效率相对于UDP的不需要建立连接稍低
在连接中进行大数据量传输
举例:
HTTP协议基于TCP协议,所以必须先与服务器建立连接
下载等不允许丢包的情况下使用TCP
UDP特点:
不需要建立连接,是不可靠协议。将数据、源和目的信息封装到数据报中,每个数据报的大小限制在64KB内,但速度相对于TCP要快
举例:
视频会议、桌面共享等可以允许丢包而影响不大的用UDP
Socket与ServerSocket
Socket(插座/套接字)
Socket是为网络服务提供的一种机制
通信的两端都有Socket
网络通信其实就是Socket间的通信
数据在两个Socket间通过IO传输
Constructor:
Socket() //通过connect(SocketAddress endpoint)方法建立连接
Socket(InetAddress address, int port) //创建Socket服务时即连接服务器
ServerSocket
Construct:
ServerSocket(int port) //建立连接,指定监听的端口
ServerSocket(int port, int backlog) //限定最大连接数为backlog个
Method:
Socket accept() //获取客户端的Socket对象
void close() //关闭ServerSocket
基于TCP协议的网络传输
Socket和ServerSocket
建立客户端和服务器端
建立连接后,通过Socket中的IO流进行数据的传输
关闭Socket
import java.net.Socket;
import java.io.OutputStream;
/**
基于TCP协议的客户端
*/
class TcpClient
{
public static void main(String[] args) throws Exception
{
//创建客户端的Socket服务,指定目的主机和端口
Socket s = new Socket("127.0.0.1", 10000);
//获取客户端Socket服务中的输出流
OutputStream os = s.getOutputStream();
os.write("什么情况?".getBytes());
s.close();
}
}
import java.net.ServerSocket;
import java.net.Socket;
import java.io.InputStream;
/**
基于TCP协议的服务端
客户端通过自身的输出流发送数据到服务端
而服务端通过客户端的输入流来接收数据,服务端向客户端发送数据会使用客户端的输出流
*/
class TcpServer
{
public static void main(String[] args) throws Exception
{
//创建服务端的ServerSocket服务,指定监听端口
ServerSocket ss = new ServerSocket(10000);
//通过accept方法获取连接过来的客户端对象
Socket s = ss.accept(); //accept方法是一个阻塞式方法
//获取连接过来的客户端ip
String ip = s.getInetAddress().getHostAddress();
//使用客户端的输入流来读取发送过来的数据
InputStream is = s.getInputStream();
byte[] buf = new byte[1024];
int len = is.read(buf);
System.out.println(ip+":"+ (new String(buf, 0, buf.length)));
//关闭客户端
s.close();
//服务端一般不关闭
}
}
TCP:浏览器客户端,自定义服务端
import java.io.*;
import java.net.*;
/**
客户端:浏览器
服务端:自定义
服务端获取浏览器发送的HTTP请求消息头,并打印出来
GET / HTTP/1.1
Host: 127.0.0.1:10000
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:13.0) Gecko/20100101 Firefox/13.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,* /*;q=0.8
Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
*/
class Server
{
public static void main(String[] args) throws Exception
{
ServerSocket ss = new ServerSocket(10000);
Socket s = ss.accept();
System.out.println(s.getInetAddress().getHostAddress()+"....connected");
InputStream isSocket = s.getInputStream();
OutputStream osSocket = s.getOutputStream();
//获取浏览器发送过来的http请求消息头,并打印出来
byte[] buf = new byte[1024];
int num = isSocket.read(buf);
System.out.println(new String(buf, 0, num));
osSocket.write("浏览器你好".getBytes());
s.close();
}
}
TCP:浏览器客户端,Tomcat服务端
开启Tomcat服务器,在浏览器中输入http://127.0.0.1:8080
TCP:浏览器自定义,Tomcat服务器
import java.io.*;
import java.net.*;
/**
客户端:自定义
服务端:Tomcat
客户端需要发送HTTP请求消息头
GET / HTTP/1.1
Host: 127.0.0.1:8080
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:13.0) Gecko/20100101 Firefox/13.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,* /*;q=0.8
Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
*/
class MyIE
{
public static void main(String[] args) throws Exception
{
Socket s = new Socket("127.0.0.1", 8080);
PrintWriter pwSocket = new PrintWriter(s.getOutputStream(), true);
BufferedReader brSocket = new BufferedReader(new InputStreamReader(s.getInputStream()));
pwSocket.println("GET / HTTP/1.1");
pwSocket.println("Host: 127.0.0.1:8080");
pwSocket.println("User-Agent:*/*");
pwSocket.println("Accept-Language: zh-cn");
pwSocket.println("Connection: keep-alive");
pwSocket.println(); //必须留一个空行
String line = null;
while((line = brSocket.readLine()) != null)
{
System.out.println(line);
}
s.close();
}
}
URL和URLConnection
之前的TCP例子中,均在传输层,而URL和URLConnection到了应用层
import java.net.URL;
/**
URL
getProtocol():http
getHost():127.0.0.1
getPort():8080
getPath():/myweb/demo.html
getFile():/myweb/demo.html?name=haha&age=30
getQuery():name=haha&age=30
*/
class URLDemo
{
public static void main(String[] args) throws Exception
{
URL url = new URL("http://127.0.0.1:8080/myweb/demo.html?name=haha&age=30");
System.out.println("getProtocol():"+url.getProtocol());
System.out.println("getHost():"+url.getHost());
//当没有URL中指定端口时,返回-1
System.out.println("getPort():"+url.getPort());
System.out.println("getPath():"+url.getPath());
System.out.println("getFile():"+url.getFile());
System.out.println("getQuery():"+url.getQuery());
}
}
import java.io.*;
import java.net.*;
/**
基于TCP协议的客户端,使用URL和URLConnection连接服务器
当接收服务器的返回信息时,会屏蔽显示应答信息,而只显示内容主体,因为此时来到了应用层
应用层对传输层发上来的信息进行了拆包
*/
class URLConnectionDemo
{
public static void main(String[] args) throws Exception
{
URL url = new URL("http://127.0.0.1:8080/");
//url可以直接连接服务器,返回URLConnection对象
URLConnection conn = url.openConnection();
InputStream is = conn.getInputStream();
byte[] buf = new byte[1024];
int num = 0;
while((num = is.read(buf)) != -1)
{
System.out.println(new String(buf, 0, num));
}
}
}
基于UDP协议的网络传输
import java.net.DatagramSocket;
import java.net.DatagramPacket;
import java.net.InetAddress;
/**
基于UDP协议的发送端
*/
class UdpSend
{
public static void main(String[] args) throws Exception
{
//建立DatagramSocket服务,并指定使用的端口
DatagramSocket ds = new DatagramSocket(8888);
//创建要发送的数据报包
byte[] buf = "udp send".getBytes();
DatagramPacket dp = new DatagramPacket(buf, buf.length, InetAddress.getByName("127.0.0.1"), 10000);
//发送数据
ds.send(dp);
//关闭资源
ds.close();
}
}
import java.net.DatagramSocket;
import java.net.DatagramPacket;
/**
基于UDP协议的接收端
*/
class UdpReceive
{
public static void main(String[] args) throws Exception
{
//建立DatagramSocket服务,并指定使用的端口
DatagramSocket ds = new DatagramSocket(10000);
//创建数据报包对象,用于存放接收到的数据报包
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf, buf.length);
//接收被监听端口发送过来的数据报,并存放到dp内
ds.receive(dp);
//获取dp内的数据信息
String ip = dp.getAddress().getHostAddress();
String data = new String(dp.getData(), 0, dp.getLength());
int port = dp.getPort();
System.out.println(ip+"::"+data+"::"+port);
//关闭资源
ds.close();
}
}
域名解析
域名好记,但网络中只有IP才可以确定主机,所以需要把域名解析成IP
解析过程:
域名-->hosts文件-->DNS缓存-->DNS服务器
上述过程中,任一步解析成功,则停止后面的解析
---------------------- ASP.Net+Android+IOS开发</a>、 .Net培训、期待与您交流! ----------------------