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

黑马程序员----Java网络编程

2015-06-18 20:29 507 查看
——- android培训java培训、期待与您交流! ———-

IP是互联网上的每一台计算机都有得一个唯一表示自己的标记。

IP地址使用4个8位的二进制数据表示,每8位之间使用圆点隔开,每个8位整数可以转换成一个0~255的十进制整数,因此我们一般看到的IP地址类似:192.168.1.1

分类:

IPv4:32位,分4段,0~255之间的十进制表示

IPv6:128位,分8段,0000~FFFF的十六进制数值,冒号分割。

java中InetAddress类要来表示IP地址,有两个子类:

Inet4Address(IPv4)

Inet6Address(IPv6)

常用方法

public static InnetAddress getByName(String host):根据主机获取对应的InetAddress对象
public static InnetAddress getLocalHost():根据本机过得InetAddress对象
public static InetAddress getByAddress(byte[] addr):根据原始Ip获得InetAddress对象
public String getHostName():得到IP地址
public boolean isReachable(int timeout):判断地址是否可以到达,同时指定超时时间


实例代码:

package xia.wt.net;

import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;

public class InetAddressDemo {

public static void main(String[] args) throws IOException {
//获得百度的InetAddress
InetAddress  iad = InetAddress.getByName("www.baidu.com");
//获得百度的InetAddress
byte[] ip = new byte[]{(byte)180,97,33,107};
InetAddress  iadd = InetAddress.getByAddress(ip);
//获得本地InetAddress
InetAddress  localiad = InetAddress.getLocalHost();

System.out.println(iad);
System.out.println(iadd);
System.out.println(localiad);
//检测是否可以到达百度主机//如果可以获得权限,则典型实现将使用 ICMP ECHO REQUEST;否则它将试图在目标主机的端口 7 (Echo) 上建立 TCP 连接。可能此方式被百度防火墙拦截,一只显示连接不上
System.out.println(iad.isReachable(1000000));

}
}

/**输出结果
www.baidu.com/180.97.33.107
/180.97.33.107
TL-WR745N/192.168.1.107
false
*/


URL(Uniform Resource Locator)统一资源定位符,可以直接使用此类找到互联网上的资源如一个简单的网页。

一般由:协议名,资源所在主机,端口,资源名等部分组成。

常用构造方法:

URL(String spec):根据指定的地址实例化URL对象;
URL(String protocol, String host, int port, String file) :实例化URL,并指定协议,主机,端口名字,资源文件
public URLConnection openConnection():得到URLConnection 对象
public final InputStream openStream():得到输入流


URLConnection封装访问远程网络资源一般方法的类,通过它可以建立与远程服务器的连接,检查远程资源的一些属性。

Java中URLEncoder可以为传递的内容编码,而URLDecoder可以为传递的内容解码;

URLEncoder:

public static String encode(String s,String enc):使用指定的编码机制将字符串转编码成application/x-www-form-urlencoded MIME字符串;

URLDecoder:

public static String decode(String s,String enc):使用指定编码机制对application/x-www-form-urlencoded MIME字符串解码

public class URLEncoderDemo {
public static void main(String[] args) throws UnsupportedEncodingException {
String s ="原始文字";
System.out.println(s);
//将s进行utf-8编码
s = URLEncoder.encode(s, "utf-8");
System.out.println(s);
//将s进行utf-8解码
s=URLDecoder.decode(s, "utf-8");
System.out.println(s);
}
}

/**输出结果
原始文字
%E5%8E%9F%E5%A7%8B%E6%96%87%E5%AD%97
原始文字*/


TCP(Transmission Control Protocal)

是一种面向连接的、可靠的、基于字节流的传输层通信协议。

应用层向TCP层发送用于网间传输的、用8位字节表示的数据流,然后TCP把数据流分区成适当长度的报文段(通常受该计算机连接的网络的数据链路层的最大传输单元([1] MTU)的限制)。之后TCP把结果包传给IP层,由它来通过网络将包传送给接收端实体[1] 的TCP层。TCP为了保证不发生丢包,就给每个包一个序号,同时序号也保证了传送到接收端实体的包的按序接收。然后接收端实体对已成功收到的包发回一个相应的确认(ACK);如果发送端实体在合理的往返时延(RTT)内未收到确认,那么对应的数据包就被假设为已丢失将会被进行重传。TCP用一个校验和函数来检验数据是否有错误;在发送和接收时都要计算校验和。

Java中使用Socket实现TCP程序开发,使用此类可以方便的建立可靠的,双向的,持续的,点对点的通讯连接。

在Socket程序开发中,服务器端使用ServerScoket等待客户端的连接,在Java的网络程序中,每一个客户端都使用Socket对象表示。

在服务器端每次运行都要使用aceept()方法等待客户端连接,此方法执行之后服务器将进入阻塞状态,直到客户端连接之后程序才可以向下继续执行,此方法的返回类型是Socket,每一个Socket都表示每一个客户端连接对象。

Socket编程步骤:

1.建立网络连接;

2.打开连接到Socket的输入/输出流;

3.通过已打开的IO流进行读写操作;

4.关闭已打开的IO流和Socket;

示例代码:客户端和服务器端相互发送数据

客户端:

public class Client {

public static void main(String[] args) throws UnknownHostException, IOException {
//创建一个客户端对象
Socket s = new Socket(InetAddress.getLocalHost(),11260);
//准备输出、输入流
OutputStream os  = s.getOutputStream();
InputStream is = s.getInputStream();
//像服务器发送数据
os.write((Thread.currentThread().getName()+"客户端发来的消息").getBytes());
byte[] bs = new byte[1024];
int i = 0;
i = is.read(bs);
String str = new String(bs,0,i);
System.out.println(str);
//将接受到的数据返回给客户端
os.write(str.getBytes());
os.close();
is.close();
s.close();
}
}


服务器端:

public class Servers {
public static void main(String[] args) throws IOException {
//创建ServerSocket对象并接受客户端发来的Socket对象
ServerSocket ss = new ServerSocket(11260);
Socket s = ss.accept();
//获得输入、输出流
InputStream is = s.getInputStream();
OutputStream os = s.getOutputStream();
//接受客户端发来的数据
byte[] bs =new byte[1024];
int i = 0;
i=is.read(bs);
String str = new String(bs,0,i);
System.out.println(str);
//像客户端送返回数据
os.write((str+"Echo").getBytes());
//再次接受客户端发来的数据
i = is.read(bs);
str = new String(bs,0,i);
System.out.println(str);
os.write((str+"Echo").getBytes());
//通讯结束,关闭资源
os.close();
is.close();
s.close();
ss.close();
}
}


一个ServerSocket在一个时间段内只能为一个Socket客户端提供服务,要想同时对多个Socket提供服务可以使用多线程。

实例代码:

服务端:

package xia.wt.net;

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.ServerSocket;
import java.net.Socket;

public class ThreadSocketSer {

public static void main(String[] args) throws IOException {
//创建服务器对象
ServerSocket ss = new ServerSocket(8888);
/*死循环接受客户端请求,没有客户端连接就一只阻塞主线程,
有客户端连接就将就收到的客户端交给一个新线程处理,主线程继续等待客户端*/
while(true){
//接受客户端请求或阻塞在此处
Socket s = ss.accept();
//有客户端连接就交给新线程处理
new Thread(new ThreadsServer(s)).start();;
}
}
}

class ThreadsServer implements Runnable{

private Socket s;
//接受主线程传来的客户端信息
public ThreadsServer(Socket s){
this.s = s;
}

@Override
public void run() {
try (//创建输入输出流
BufferedReader  bf = new BufferedReader(new InputStreamReader(s.getInputStream()));
PrintWriter pw  = new PrintWriter(s.getOutputStream(),true);
){
boolean tag = true;
while(tag){
//循环接受客户端数据并应答,直到客户端发送的数据是以5结尾
String s = bf.readLine();
if(s.endsWith("4")){tag=false;}
System.out.println(s);
pw.println(s+"--Echo+"+Thread.currentThread().getName());
}

bf.close();pw.close();s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}


客户端:

public class ThreadSocketCli{

public static void main(String[] args) {
//主线程创建5个线程,分别向服务端发送数据
for(int j =0;j<5;j++){
new Thread(new ThreadClient(),"线程"+j).start();

}

}
}

class ThreadClient implements Runnable{

@Override
public void run() {
try(//创建客户端对象并创建输入输出流
Socket s = new Socket(InetAddress.getLocalHost(),8888);
PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
BufferedReader bf= new BufferedReader(new InputStreamReader(s.getInputStream()));
) {
for (int i = 0; i < 5; i++) {
//向服务端发送包含请求次数的数据
pw.println(Thread.currentThread().getName()+"for"+i);
//打印服务端返回的数据
System.out.println(bf.readLine());
}
pw.close();
bf.close();
s.close();
} catch (IOException e) {

e.printStackTrace();
}

}
}


UDP(User Datagram Prptocol)

UDP协议全称是用户数据报协议 ,在网络中它与TCP协议一样用于处理数据包,是一种无连接的协议。在OSI模型中,在第四层——传输层,处于IP协议的上一层。UDP有不提供数据包分组、组装和不能对数据包进行排序的缺点,也就是说,当报文发送之后,是无法得知其是否安全完整到达的。UDP用来支持那些需要在计算机之间传输数据的网络应用。包括网络视频会议系统在内的众多的客户/服务器模式的网络应用都需要使用UDP协议。UDP协议从问世至今已经被使用了很多年,虽然其最初的光彩已经被一些类似协议所掩盖,但是即使是在今天UDP仍然不失为一项非常实用和可行的网络传输层协议。

与所熟知的TCP(传输控制协议)协议一样,UDP协议直接位于IP(网际协议)协议的顶层。根据OSI(开放系统互连)参考模型,UDP和TCP都属于传输层协议。UDP协议的主要作用是将网络数据流量压缩成数据包的形式。一个典型的数据包就是一个二进制数据的传输单位。每一个数据包的前8个字节用来包含报头信息,剩余字节则用来包含具体的传输数据。

UDP开发中使用DatagramPacket包装一条要发送的信息,之后使用DatagramSocket完成发送操作。

实例代码

客户端向服务端发送数据

客户端:

public class UDPClient {
public static void main(String[] args) throws IOException {
//准备要发送的数据,并打包为DatagramPacket
byte[] bs = "客户端发来的数据".getBytes();
DatagramPacket dp=new DatagramPacket(bs,bs.length,InetAddress.getLocalHost(),8888);
//发送数据
DatagramSocket da = new DatagramSocket(8080);
da.send(dp);
}

}


服务端:

public class UDPServer {
public static void main(String[] args) throws IOException {
//准备数据包,用于接受数据
byte[] bs = new byte[1024];
DatagramPacket dp =new DatagramPacket(bs,bs.length);
//接受数据并打印
DatagramSocket da = new DatagramSocket(8888);
da.receive(dp);
System.out.println(new String(bs,0,dp.getLength()));

}

}


TCP & UDP简单对比

1。基于连接与无连接 ;

2。对系统资源的要求(TCP较多,UDP少) ;

3。UDP程序结构较简单 ;

4。流模式与数据报模式 ;

5。TCP保证数据正确性,UDP可能丢包,TCP保证数据顺序,UDP不保证;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  网络