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

黑马程序员_网络编程

2014-01-22 20:12 253 查看
一、网络编程(概述)
1.网络模型
OSI(Open System Interconnection )开放系统互联参考模型,是一个逻辑上定义的规范,它把网络协议从逻辑上分为了7层。(应用层,表示层,会话层,传输层,网络层,数据链路层,物理层)
TCP/IP 参考模型 优化为4层,(应用层,传输层,网络层,网络接口层).



2.网络通讯要素
IP地址:网络中设备的标识;
端口号:用于标识进程的逻辑地址,不同进程标识.范围在0~65535,其中0~1024系统使用或保留端口
传输协议:TCP,UDP.
UDP协议(对讲机,视频连接的特点)

将数据以及源和目的封装到数据包中,不需要建立连接.每个数据包的大小限制64k内.
缺点:因为无连接,是不可靠协议.
优点:不需要建立连接,使得速度快.
TCP协议(打电话)
建立连接,形成传输数据的通道,在连接中进行大数据传输,通过三次握手完成连接,是可靠协议.必须建立连接,效率会稍低.
二、UDP传输
DatagramSocket与DatagramPacket
建立发送端,接收端
建立数据包
调用Socket的发送端接收方法.
关闭Socket
发送端和接收端是两个独立的运行程序
public class UDP_聊天程序测试 {

/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
DatagramSocket ds = new DatagramSocket();
DatagramSocket dp = new DatagramSocket(9999);
new Thread(new UDP_聊天程序发送端(ds)).start();
new Thread(new UDP_聊天程序接收端(dp)).start();
}

}

public class UDP_聊天程序发送端  implements Runnable{
//定义发送端
private DatagramSocket ds;

public UDP_聊天程序发送端(DatagramSocket ds) {
super();
this.ds = ds;
}

//发送之后就能接收,需要使用到多线程
public void run() {
try {
//键盘录入数据
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = null;
while((line=br.readLine())!=null){
byte [] buf = line.getBytes();
//将键盘录入的数据存放在Datagranacket数据包中
DatagramPacket dp = new DatagramPacket(buf, buf.length,InetAddress.getByName("192.168.1.102"),9999);
ds.send(dp);
if("886".equals(line)){
break;
}
}
ds.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

public class UDP_聊天程序接收端 implements Runnable {
private DatagramSocket ds;

public UDP_聊天程序接收端(DatagramSocket ds) {
super();
this.ds = ds;
}

public void run() {
try {
while (true) {
// 1.创建数据包
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf, buf.length);
// 2.使用接收方法将数据存储到数据包中
ds.receive(dp);
// 3.通过数据包对象的方法,解析其中的数据,比如地址,端口,数据内容
String ip = dp.getAddress().getHostAddress();
int port = dp.getPort();
String text = new String(dp.getData(), 0, dp.getLength());
System.out.print(ip + ":" + port + ":" + text+"\r\n");
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}


二、TCP传输
Socket和ServerSocket
建立客户端和服务端
建立连接后,通过Socket中的IO流进行数据的传输
关闭Socket
同样,客户端与服务端也是两个独立的应用程序.

public class TCP_客户端 {
/**
* 文本转换客户端
* 思路:
* 		客户端
* 		1.一提到客户端需要定义Socket客户端;
* 		2.客户端的数据源:键盘;
* 		3.客户端的目的:Socket
* 		4.数据显示打印出来:控制台....;
* 		5.操作的都是文本数据
*
* 		转换客户端
* 		1.创建Socket
* 		2.键盘录入字符串并发送给Socket输出流;
* 		3.通过Socket中getOutputStream()获取键盘录入的信息并输出.
* @throws IOException
* @throws UnknownHostException
*/
public static void main(String[]args) throws UnknownHostException, IOException{
//1.创建Socket
Socket s = new Socket("192.168.1.103", 10001);
//2.键盘录入
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//3.将录入的信息通过Socket发送出去,Socket输出流
//BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
PrintWriter pw = new PrintWriter(s.getOutputStream(),true);//必须自动刷新

//4.读服务器返回的数据
BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));
String len = null;
while((len=br.readLine())!=null){//rend()和rendLine()都是阻塞式方法..出现一个问题就是客户端和服务端都会莫名的等待
if(len.equals("over")){		 //客户端和服务端都会出现阻塞式的方法,这些方法没有读到结束标记(回车换行),就会一直等.
break;					 //而导致两端都在等待.(换行,刷新解决了)或者PrintWriter自动刷新
}
pw.println(len); //所以避免read阻塞这里必须是换行输出,同时PrintWriter自动刷新.为true
//			bw.write(len);
//			bw.newLine();
//			bw.flush();
System.out.println(len);

//写完同时读取服务端传回来的数据
String str = bufIn.readLine();
System.out.println(str);
}
br.close();
s.close();
}
}

public class TCP_服务端 {
/**
* 转换服务端
* 分析:
* 		1.创建服务端ServerSocket
* 		2.获取Socket对象
* 		3.源:Socket,读取到客户端的数据,转换成大写;
* 		4.再将处理过后的数据转发给客户端.
* @param args
* @throws IOException
* @throws UnknownHostException
*/
public static void main(String[] args) throws UnknownHostException, IOException {
//1.创建服务端
ServerSocket ss  = new ServerSocket(10001);
//2.获取Socket,侦听并接受到此套接字的连接
Socket s = ss.accept();
String ip = s.getLocalAddress().getHostAddress();
System.out.println(ip+"已连接");
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));

//3.转换后就发送出去,定义一个输出流
//BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
PrintWriter pw = new PrintWriter(s.getOutputStream(),true);//必须自动刷新
String len = null;
while((len=br.readLine())!=null){

System.out.println(len);
String str = len.toUpperCase();
//			bw.write(str);
//			bw.newLine();
//			bw.flush();
pw.println(str);  //所以避免read阻塞这里必须是换行输出,同时PrintWriter自动刷新.为true

}
s.close();
ss.close();
}

}


TCP上传文本文件
public class TCP协议_上传文本文件客户端 {
/**
* 上传文件客户端
* 		思路:1.创建Socket客户端
* 			 2.客户端数据源:硬盘文本文件
* 			 3.客户端目的:Socket
* 			 4.上传是文本文件
* @param args
* @throws IOException
* @throws UnknownHostException
*/
public static void main(String[]args) throws UnknownHostException, IOException{
//1.定义客户端
Socket s = new Socket("192.168.1.102", 10002);
//2.获取文本文件
BufferedReader br = new BufferedReader(new FileReader("E:\\新建文本文档.txt"));
//3.将文本信息通过Socket发送给服务端
PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
String len = null;
while((len=br.readLine())!=null){
pw.println(len);
}
s.shutdownOutput();//告诉服务端,客户端输出完毕,Soclket结束标记,避免出现阻塞现象

//4.获取服务端的反馈信息
BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));
System.out.println(bufIn.readLine().toString());
br.close();
s.close();
}
}

public class TCP协议_上传文本文件服务端 {

/**
* 上传文本文件服务端
* 			思路:1.创建服务端ServerSocket
* 				 2.创建客户端对象,侦听连接
* 				 3.获取客户端的文本数据
* 			     4.将文本数据上传到硬盘中
* 				 5.反馈客服端上传成功
* @throws IOException
*/
public static void main(String[] args) throws IOException {
//1.创建服务端
ServerSocket ss = new ServerSocket(10002);
//2.创建客户端对象.侦听连接
Socket s = ss.accept();
System.out.println(s.getLocalAddress().getHostAddress());
//3.接收客户端的文本数据
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
//4.将文本数据写在硬盘中
BufferedWriter bw= new BufferedWriter(new FileWriter("e:\\partfiles\\111.txt"));
String len = null;
while((len=br.readLine())!=null){
bw.write(len);
bw.newLine();
bw.flush();
}
PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
pw.println("上传成功!");
s.close();
ss.close();
}
}

TCP上传图片(媒体)文件

public class TCP_上传图片文件客户端 {
public static void main(String[] args) throws UnknownHostException, IOException {
//健壮性判断一下文件
String str = "e:\\0010.jpg";
args  = new String[1];
if(args.length!=1){
System.out.println("请选择一个jpg格式的文件");
return;
}
args[0]=str;
File file = new File(args[0]);
if(!file.exists()||!file.isFile()){
System.out.println("文件不存在或者不是文件类型");
return;
}
if(!file.getName().endsWith(".jpg")){
System.out.println("文件格式的错误,请选择一个图片格式文件(jpg)");
return;
}
if(file.length()>1024*1024*5){
System.out.println("图片文件不能大于5M!");
return;
}

//1.创建客户端
Socket s = new Socket("192.168.1.102", 10004);
//2.创建图片文件读取流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
//3.创建Socker输出流
BufferedOutputStream bos = new BufferedOutputStream(s.getOutputStream());
//4.接收图片文件流,并通过Socker客户端发送给服务端
byte [] ch = new byte[1024];
int num = 0;
while((num=bis.read(ch))!=-1){
bos.write(ch, 0, num);
bos.flush();			////缓冲需要写刷新
}
s.shutdownOutput();//告诉服务端,客户端输出完毕,Soclket结束标记,避免出现阻塞现象
//5.同时接收服务端反馈成功的信息
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
System.out.println(br.readLine());

s.close();
bis.close();
}
}

class PicThread implements Runnable{
private Socket s;
PicThread(Socket s){
this.s = s;
}
public void run() {
try {
String ip = s.getInetAddress().getHostAddress();
int count = 1;
//3.接收客户端传来的图片字节流
BufferedInputStream bis = new BufferedInputStream(s.getInputStream());
//4.定义上传的文件路径
File file = new File("e:\\partfiles\\"+ip+"("+(count)+")"+".jpg");
while(file.exists()){
file = new File("e:\\partfiles\\"+ip+"("+(count++)+")"+".jpg");
}
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
int len = 0;
byte [] ch = new byte[1024*1024];
while((len=bi
ab78
s.read(ch))!=-1){
bos.write(ch, 0, len);
bos.flush();               //缓冲需要写刷新
}
//5.上传成功发送给客户端
PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
pw.println("上传成功!");

bos.close();
bis.close();
s.close();
} catch (IOException e) {
throw new RuntimeException("上传失败!");
}
}

}
public class TCP_上传图片文件服务端 {

public static void main(String[] args) throws IOException {
//1.创建服务端
ServerSocket ss = new ServerSocket(10004);

while(true){
//2.关联客户端
Socket s = ss.accept(); //这是一个阻塞式,所以不会担心无限循环,当有客户端上传就回执行,没有就一直等待
//3.开启多线程!
new Thread(new PicThread(s)).start();

}
}
}


总结:UDP----发送端,接收端
TCP----客户端,服务端(服务端一般都是用到多线程技术)
三、常见的客户端和服务端

最常见的客户端
浏览器:IE. 浏览器有多种但内核都是IE.像搜狗,它的内核不止一个,后期担心IE会收费,就拥有自己的核心内容Webkit是一个开源的浏览器引擎.
最常见的服务端
服务器:TomCat 对外提供Web资源访问,FTP文件传输协议
HTTP协议是web浏览器与服务端的一种通讯规则,是一种超文本传输协议
原理:HTTP协议和浏览器中的http是URL地址,用于同一的资源定位,其中包括http协议,访问的地址,端口号,访问的资源.
URL:统一资源定位符,定位网络中的资源
URI:统一资源标识符

URL中openConnection()方法
URLConnection conn = url.openConnection();获取url对象的URL连接器对象.
将连接封装成了对象:java中内置的可解析的具体协议的对象+Socket

四、网络结构
1.C/S client/server
特点:该结构的软件,客户端和服务端都需要编写.开发成本较高,维护较为麻烦.
优点:客户端在本地可以分担一部分运算.
2.B/S browser/server
特点:该结构的软件,只开发服务器端,不开发客户端.开发成本相对较低,维护更简单.
缺点:所有运算都在服务端完成.

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: