您的位置:首页 > 理论基础 > 计算机网络

黑马程序员-Java基础知识预备之Java网络编程

2013-07-16 14:13 796 查看
--------- android培训java培训、期待与您交流!----------
一、网络编程的基础知识
1、网络模型
(1)OSI参考模型
应用层:
①功能:文件传输,电子邮件,文件服务,虚拟终端。
②TCP/IP族:HTTP,SNMP,FTP,SMTP,DNS,Telnet等。
表示层:
①功能:数据格式化,代码转换,数据加密。
②TCP/IP族:没有协议。
会话层:
①功能:解除或建立与别的结点的联系。
②TCP/IP族:没有协议。
传输层:
①功能:提供端对端的接口
②TCP/IP族:TCP,UDP
网络层:
①功能:为数据包选择路由。
②TCP/IP族:IP,ICMP。
数据链路层:
①功能:传输有地址的帧,错误检测功能。
②TCP/IP族:ARP,RARP。
物理层:
①功能:以二进制数据在物理媒体上传输数据。
②TCP/IP族:ISO2110,IEEE802等。
(2)TCP/IP参考模型
应用层:对应OSI的应用层、表示层、会话层。
传输层:对应OSI的传输层。
互联网层:对应OSI的网络层。
网络接口层:对应OSI的数据链路层和物理层。
①互联网层协议:
IP(Internetworking Protocol,网络互联协议)用以实现IP地址管理、路由选择、数据包的分片与重组。
ICMP(Internet Control Message Protocol,互联网控制信息协议)用于在IP主机、路由器之间
传递控制消息。
ARP(Address Resolution Protocol,地址解析协议)用以实现网络地址解析
RARP(Reverse Address Resolution Protocol,反地址解析协议)用以实现网络地址的反向解析
②传输层协议
TCP(Transport Control Protocol,传输控制协议)用以实现基于连接、可靠的字节流传输。
UDP(User Datagram Protocol,用户数据报协议)用以实现基于无连接的、不可靠的报文传输。
③应用层协议
HTTP(Hyper Text Transfer Protocol,超文本传输协议)用于对Web网页进行浏览。
DNS(Domain Name Service,域名地址服务协议)用以提供域名和IP地址间的转换服务。
Telnet(Telecommunication Network,远程登录协议)用以实现远程登录,即提供终端到主机交互式访问的虚拟终端访问服务。

2、TCP、UDP、IP服务的特点对比
TCP:(1)通过三次握手完成连接,可靠的、端到端(2)面向连接(虚拟连接)(3)因必须建立连接,所以速度慢(4)在连接中进行大数据传输,全双工数据流
UDP:(1)不可靠的、端到端(2)面向无连接(3)不需要建立连接,所以速度快(4)应用程序承担可靠性的全部工作(5)每个数据报的大小限制在64k内。
IP:(1)不可靠(2)面向无连接(3)尽最大努力投递

3、数据要发送到对方的应用程序上,为了标识这些应用程序,所以给这些网络应用程序都用数字进行标识。为了方便称呼这个数字,所它叫做端口。其为逻辑端口。端口就是TCP和UDP为了识别一个主机上的多个目标而设计的,如HTTP是80端口、FTP是21端口、Telnet是23端口、域名服务是53端口等。

二、InetAddress
1、Java提供了InetAddress类来代表IP地址,InetAddress还有两个子类:Inet4Address(IPv4)、Inet6Address(IPv6)。

2、InetAddress没有构造器,而是提供了静态方法。如:
getAllByName(String host):在给定主机名的情况下,根据系统上配置的名称服务返回其 IP 地址所组成的InetAddress数组。
getByName(String name):根据主机获取对应的InetAddress对象
getByAddress(byte[] addr):根据原始IP地址来获取对应的InetAddress对象,(不常用)

3、InetAddress还提供了如下几个方法来获取InetAddress实例对应的IP地址和主机名。
String CanonicalHostName():获取此IP地址的全限定域名。
String getHostAddress():返回该InetAddress实例对应的IP地址字符串(以字符串形式)
String getHostName():获取此IP地址的主机名。
还有获取本机IP地址对应的InetAddress实例:getLocalHost()

三、基于UDP的网络编程
UDP协议是一种不可靠的协议,所以不管对方是否可以接收到数据。应用虽没有TCP广泛,但是在一些实时性很强的应用场景中,比如网络游戏、视频会议,QQ聊天等还是有其独特的魅力的。实现UDP网络编程,其通信实例的两端的必须各建立一个Socket,但这两个Socket之间并没有虚拟链路,这两个Socket只是发送、接收数据报的对象。Java提供了DatagramSocket对象作为基于UDP协议的Socket,使用DatagramPacket代表DatagramSocket发送、接收的数据报。
下面以一个例子来具体说明:
/*
需求:编写一个聊天程序。
分析:1.有收数据的部分,和发数据的部分。
(1)建立Send和Rece两个类来实现
2.这两部分需要同时执行。那就需要用到多线程技术。
一个纯种控制收,一个线程控制发。
(1)实现Runnable或Thread接口
(2)因为收和发动作是不一致的,所以要定义两个run方法。
而且这两个方法要封装到不同的类中
*/
import java.io.*;
import java.net.*;
//发送端
class Send implements Runnable
{
private DatagramSocket ds;
public Send(DatagramSocket ds)
{
this.ds = ds;
}
//覆盖Runnable的run方法
public void run()
{
try
{
//获取键盘录入
BufferedReader bufr =
new BufferedReader(new InputStreamReader(System.in));
//定义一个容器,存储每次键盘输入的数据。
String line = null;
while((line = bufr.readLine()) != null)
{
if("over".equals(line))
break;
//将读取到的字符串转换成字节数组
byte[] bufs = line.getBytes();
//定义一个数据包,将读取到的数据封装到包里
DatagramPacket dp = new DatagramPacket
(bufs, bufs.length,InetAddress.getByName("127.0.0.1"),10000);
//将数据发送出去
ds.send(dp);
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
//接收端
class Rece implements Runnable
{
private DatagramSocket ds;
public Rece(DatagramSocket ds)
{
this.ds = ds;
}
public void run()
{
try
{
while(true)
{
//定义一个容器,用来存储接收到的数据
byte[] bufs = new byte[1024];
//将接收到的数据打包,并利用其功能,抽取信息
DatagramPacket dp =
new DatagramPacket(bufs, bufs.length);
//接收数据
ds.receive(dp);
//抽取数据包中的数据
String ip = dp.getAddress().getHostAddress();
//因为1024是缓冲区,不可能全部存满了,所以要获取指定长度。
String data = new String(dp.getData(), 0, dp.getLength());
//将接收到的数据打印到控制台
System.out.println(ip + "::" + data);
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
//测试类
class ChatDemo2
{
public static void main(String[] args) throws Exception
{
//建立发送端的socket服务对象,
DatagramSocket sendSocket = new DatagramSocket();
//建立接收端的socket服务对象。并侦听端口
DatagramSocket receSocket = new DatagramSocket(10000);
//创建并开启线程
//      Thread t1 = new Thread(new Send(sendSocket));
//      Thread t2 = new Thread(new Rece(receSocket));
//      t1.start();
//      t2.start();
new Thread(new Send(sendSocket)).start();
new Thread(new Rece(receSocket)).start();
}
}

四、基于TCP的网络编程
1、需要服务端和客户端

2、当多个客户端向一个服务端发送请求时,要用到多线程。

3、注意read,accept等方法是阻塞式的方法,它必须获取到数据后才会运行,否则等待。所以当服务端和客户端都莫名等待时,是因为客户端和服务端都有阻塞式方法。这此方法都没有读到结束标记。那么就一直等而导致两端都在等待。

4、以一个简单的例子来说明
/*
需求:
建立一个文本转换服务器。
客户端给服务发送文本,服务端会将文本转成大写再返回给客户端。
而且客户端可以不断的进行文本转换。当客户端输入over时,转换结束。
分析:
1.由题意,需要分别建立客户端和服务端。
class Client
class Server
2.客户端要操作文本,需要用到FileReader,因socket中的流对象是字节
流所以需要转换流InputStreamReader ,又需要提高效率,所以需要用到
缓冲区,BufferedReader
3.先建立客户端
(1)建立socket服务,并确定目的地址及端口号。
(2)获取socket中的流对象 ,并对其进行包装。
(3)将本地文本文件输出到socket流对象中。
(4)再创建一个socket读取流对象用来读取服务端的反馈信息,也就是文本处理后的结果
(5)因可以不断的进行文本转换,所以不需要关闭流,而当输入over时,结束。
4.建立服务端
(1)建立ServerSocket服务,并绑定侦听端口号。
(2)侦听并接收客户端socket对象。
(3)建立客户端socket读取流对象,并对其进行处理。
(4)建立客户端socket写入流对象,用来回馈处理后的结果。
(5)关闭客户端资源。
*/
import java.io.*;
import java.net.*;
//客户端
class Client
{
public static void main(String[] args) throws Exception
{
//建立socket
Socket s = new Socket("127.0.0.1",10000);
//获取socket中的流对象 ,并对其进行包装
BufferedWriter out = new
BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
//获取键盘录入
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
//创建获取服务器的反馈信息的流对象,并打印在控制台上
BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
//用来存储数据
String line = null;
while((line = bufr.readLine()) != null)
{
//定义程序结束标记
if("over".equals(line))
break;
out.write(line);
//换行,可做为数据结束标记
out.newLine();
//刷新,将数据刷新到socket输出流中以便传给服务端的socket输入流
out.flush();
//读取反馈信息
String str = in.readLine();
System.out.println("server:"+str);
}
}
}
//服务端
class Server
{
public static void main(String[] args) throws Exception
{
//建立服务端socket对象,并绑定指定端口
ServerSocket ss = new ServerSocket(10000);
//用来接收客户端socket
Socket s = ss.accept();
//读取socket流中的数据
BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
//定义一个socket输出流,以便将反馈信息写入其中
PrintWriter out = new PrintWriter(s.getOutputStream(),true);
//获取并打印连进来的ip地址,以明确对象。
String ip = s.getInetAddress().getHostAddress();
System.out.println(ip);
//读取socket流中的数据。
String line = null;
while((line = in.readLine()) != null)
{
System.out.println(line);
out.println(line.toUpperCase());
}
s.close();
}
}

--------- android培训java培训、期待与您交流!----------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  网络编程