黑马程序员——网络编程

------- android培训java培训、期待与您交流! ----------

一、概述

(一)网络传输过程

1.找到对方IP

2.数据要发送到对方指定的应用程序上。为了标示这些应用程序,给这些APP都用数字进行标识。即是端口(逻辑端口)

3.定义通讯协议 TCP/IP协议 192.168.1.254-局域网保留地址

(二)网络模型

OSI参考模型

TCP/IP参考模型

 

1.OSI参考模型OpenStyleInternet

数据封包:层层封装数据添加每个层次的特有信息

 

应用层

表示层

会话层

传输层 tcp

网络层 ip

数据链路层

物理层 网线 光纤无线网

 

2.TCP/IP参考模型

 

tcp/ip模型将上三层理解为应用层http/ftp

传输层 tcp udp

网际层 ip

将下二层理解为基本底层(主机至网络层)

 

传输给目标地址后:数据拆包,到应用层后数据根据端口发送到相应的程序

 

写程序:

网络编程网际层和传输层

Javaweb开发在应用层

(三)网络传输基本三要素:IP 端口协议

1. IP

本地回环地址:127.0.0.1 主机名:localhost

有专门描述IP对象的类

import java.net.*;

 

Class InetAddress

 |--Inet4Address

 |--Inet6Address

无构造函数,有非静态方法和静态方法,说明有静态方法获取本类对象

获取IP对象的方法以getHostAddress()为主

 

2.端口

用于表示进程的逻辑地址,不同进程标识不同

有效端口0-65535  0-1024为系统使用或保留端口

因为只有数字标识,所以不需要对象

 

3.协议

UDP:无连接,限制大小,不可靠,速度快

a.面向无连接(发数据之前不需要建立连接(邮局寄送包裹))

b.将数据源和目的地一同封包

c.每个数据包的大小被限制在64k以内

d.因为是无连接。是不可靠协议

e.不需要建立连接,速度快

聊天就是UDP

 

TCP:必连接,大数据,可靠,效率稍低

a.必须连接,形成传输数据的通道。三次握手,s-在吗? r-在,你在?s-在,开始吧

b.连接中进行大数据量传输

c.通过三次握手完成连接,可靠

d.必须建立连接,效率稍低

下载 是tcp

电话是tcp,步话机是udp


二、IP对象

1获取指定IP对象的方法

1)getByName()

a.url

b.ip

2)getAllByName()

3)getByAddress()

4)getLocalHost()

2获取IP对象地址

3获取IP对象的名称

InetAddressi1a=InetAddress.getByName(“www.baidu.com”);

InetAddress i1b=InetAddress.getByName(“192.168.1.100”);

InetAddress[] i2=InetAddress.getAllByName(“www.baidu.com”);

InetAddress i3=InetAddress.getByAddress(newbyte[]{(byte)192,(byte)168,1,101});

InetAddress i4=InetAddress.geLocalHost(); 

i4.getHostName();

i4.getHostAddress();

=================

150527 add:

可以对InetAddress对象调用getAddress()方法获取其地址值的byte[4]数组。用处:进行ip地址的大小比较。for循环4次,如果当前段数值相同则continue;byte超过127则表示为负数,所以比较两个段数值的大小,必须分情况讨论。

getByName获取ip对象时需要处理异常:UnknownHostException

三、Socket套接字对象

Socket是为网络服务提供的一种机制

通信的两端都有Socket。

网络通信的实质就是Socket之间的通信

数据在两个Socket之间通过IO传输

Socket是传输的通路,先有码头,才有船运输货物

不同传输协议有不同的Socket

(一)UDP

DatagramSocket此类标识用来发送和接收UDP协议数据报包的套接字,既可以发送也可以接收

==========

150527 add:

DatagramSocket在新建对象时可以指定使用的端口号,这样就不容易冲突 ds=new DatagramSocket(10086);

新建DatagramSocket需要处理 SocketException


DatagramPacket表示数据报包

数据报包实现无连接包投递服务

DatagramPacket(byte[] buf,intlength,InetAddress addr,int port)//发送

带地址的方法都是用于发送数据

DatagramPacket(byte[] buf,int length)//接收 

==========

150527 add:

这里传入数据报包的参数是缓冲区字节数组以及数组长度!length应当传入的是buf.length而不是cntBuf。



send(DatagramPacket p)//从此套接字发送数据报包

receive(DatagramPacket p)//从此套接字接收数据报包

 

UDP发送

通过UDP传输方式,将一段文字数据发送出去

思路:

1建立UDP Socket服务

2提供数据,并将数据封装到数据包中

3通过Socket服务的发送功能,将数据包发送出去,

4关闭资源(因为数据包的传输至少要通过网卡)

 

DatagramSocket ds=new DatagramSocket();

 

byte[] buf=”hello”.getBytes();

DatagramPacket dp= new DatagramPacket(buf,buf.length,InetAddress.getByName(“192.168.1.100”),10000);

 

ds.send(dp);

 

ds.close();

 

UDP接收

DatagramPacket获取数据报包数据的方法:

ip对象InetAddress getAddress()

端口int getPort()

字节数据数组byte[] getData()

字节数据长度int getLength

 

DatagramSocket ds=new DatagramSocket();

 

byte[] buf= byte[1024];

DatagramPacket dp=newDatagramPacket(buf,buf.length);

 

ds.receive(dp);

 

String ip=dp.getAddress().getHostAddress();

int port=dp.getPort();

String info=new String(dp.getData(),0,dp.getLength());

 

ds,close();

import java.net.*;
import java.io.*;
/*发送键盘录入的数据到目标地址
1建立输入流 bin
-关闭bin
2.建立套接字
-关闭套接字
3.处理输入的数据
4.建立数据报包
5.使用套接字发送服务
*/
class UDPSender implements Runnable{
	public void run() {
		
		byte[] buf = null;
		String tmp=null;
		
		BufferedReader bin=new BufferedReader(new InputStreamReader(System.in));
		
		DatagramSocket ds = null;
		DatagramPacket dp = null;
		try {
			ds = new DatagramSocket();
		} catch (SocketException e) {
			e.printStackTrace();
		}		
		
		try {
			while(!"over".equals(tmp=bin.readLine())){
				buf=tmp.getBytes();			
					
				try {
					dp=new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.100"),10000);
				} catch (UnknownHostException e) {
					e.printStackTrace();
				}
					
				try {
					ds.send(dp);
				} catch (IOException e) {
					e.printStackTrace();
				}	
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		
		try {
			bin.close();
		} catch (IOException e) {
			e.printStackTrace();
		}		
		if(null!=ds){
			ds.close();
		}
	}
}

class UDPReceiver implements Runnable{
	public void run() {
		DatagramSocket ds=null;
		DatagramPacket dp=null;
		byte[] buf=new byte[1024];
		try {
			ds=new DatagramSocket(10086);
		} catch (SocketException e) { 
			e.printStackTrace();
		}
		
		
		
		while(true){
			dp=new DatagramPacket(buf,buf.length);
			try {
				ds.receive(dp);
			} catch (IOException e) { 
				e.printStackTrace();
			}
			
			String ip= dp.getAddress().getHostAddress();
			int port=dp.getPort();
			String info=new String(dp.getData(),0,dp.getLength());

			System.out.println("ip: "+ip+":"+port+" - "+info);
			
		}		
		
	}
	
	
}
class host1{
	public static void main(String[] args){
		new Thread(new UDPSender()).start();
		new Thread(new UDPReceiver()).start();
	}
}

class test2{
	public static void main(String[] args){
		new Thread(new UDPSender()).start();
		new Thread(new UDPReceiver()).start();
	}
}

(二)TCP

UDP分发送端和接收端

TCP分客户端Socket和服务器端ServerSocket

1.建立Socket和ServerSocket

2.建立连接后,通过Socket中的IO流进行数据的传输

3.关闭Socket

 

Socket

1.ctor

Socket(InetAddress address,int port)

Socket()//空参数的ctor可以在创建对象后使用connect方法进行连接

 

因为TCP面向连接,所以建立时就须要有服务器端存在,并连接成功。

形成通路后再向该通路进行数据传输

 

2.接收

1)创建客户端对象:

Socket()//创建空参数的客户端对象,一般用于服务端接收数据

Socket(String host,int port)//指定要接收的IP地址和端口号

2)创建服务端对象:ServerSocket(int port)//指定接收的客户端的端口

3)Socket accept()//监听并接受到此套接字的连接       

4)InputStream getInputStream()//返回此套接字的输入流,Socket对象调用

5)OutputStream getOutputStream()//返回套接字的输出流,Socket对象调用

 

3.基本思路

客户端:

1)客户端需要明确服务器的ip地址以及端口,这样才可以去试着建立连接,如果连接失败,会出现异常。

2)连接成功,说明客户端与服务端建立了通道,那么通过IO流就可以进行数据的传输,而Socket对象已经提供了输入流和输出流对象,通过getInputStream(),getOutputStream()获取即可。

3)与服务端通讯结束后,关闭Socket。

服务端:

1)服务端需要明确它要处理的数据是从哪个端口进入的。

2)当有客户端访问时,要明确是哪个客户端,可通过accept()获取已连接的客户端对象,并通过该对象与客户端通过IO流进行数据传输。

3)当该客户端访问结束,关闭该客户端。

 

4.步骤

客户端:

1)创建Socket服务,并指定要连接的主机端口。通路一建立,就会产生Socket流(包括输入流和输出流),通过方法获取

2)为了发送数据,应获取Socket中的输出流,如果要接收服务端的反馈信息,还需要获取Socket的输入流

3)通过输出流的write()方法将要发送的数据写入到流中

4)关闭Socket流资源

服务端:       

1)建立服务端的Socket服务,并监听一个端口。

2)获取连接过来的客户对象,通过ServerSocket的accept()方法,此方法是阻塞式的,如果服务端没有连接到就会一直等待

3)客户端如果发过来数据,则服务端要使用对应的客户端对象,并获取到该客户端对象的读取流读取发过来的数据,并输出到指定目的地。

4)关闭客户端的套接字资源。

 

import java.net.*;
import java.io.*;

class TCPSender implements Runnable {

	public void run() {

		Socket s = null;
		try {
			s = new Socket(InetAddress.getByName("192.168.1.100"), 10000);
		} catch (UnknownHostException e2) {

			e2.printStackTrace();
		} catch (IOException e2) {

			e2.printStackTrace();
		}
		OutputStream out = null;
		try {
			out = s.getOutputStream();
		} catch (IOException e1) {

			e1.printStackTrace();
		}

		try {
			out.write("hello!".getBytes());
		} catch (IOException e1) {

			e1.printStackTrace();
		}

		try {
			s.close();
		} catch (IOException e) {

			e.printStackTrace();
		}

	}

}

class TCPReceiver implements Runnable {

	public void run() {

		ServerSocket ss = null;
		try {
			ss = new ServerSocket(10000);
		} catch (IOException e) {

			e.printStackTrace();
		}
		Socket s = null;
		try {
			s = ss.accept();
		} catch (IOException e1) {

			e1.printStackTrace();
		}
		InputStream in = null;
		try {
			in = s.getInputStream();
		} catch (IOException e1) {

			e1.printStackTrace();
		}

		byte[] buf = new byte[1024];
		int cnt = 0;
		try {
			cnt = in.read(buf);
		} catch (IOException e1) {

			e1.printStackTrace();
		}
		System.out.println(new String(buf, 0, cnt));

		try {
			s.close();
		} catch (IOException e) {

			e.printStackTrace();
		}
		try {
			ss.close();
		} catch (IOException e) {

			e.printStackTrace();
		}
	}
}


服务器端并发处理客户端的连接:

ServerSocket sServer=newServerSocket(port);

while(true)

{

         newThread(new Session(sServer.accept())).start();

}

 

客户端上传图片到服务器端

1.客户端:

1创建tcp的套接字

2获取输出流

3获取文件输入流

4将图片传输到服务器端

 

服务器端:

1.创建服务器端tcp套接字

2.循环accept获取新的客户端套接字

3.获取客户端的输入流

4.获取文件输出流

5.保存图片并添加时间戳

import java.net.*;
import java.util.Date;
import java.io.*;
import java.text.*;


class TCPSender implements Runnable {
	private String strIP;
	private int port;
	private File file;
	public TCPSender(String strIP,int port,File file) {
		super();
		this.port = port;
		this.strIP = strIP;
		this.file=file;
	}
	public void run() {
		Socket s=null;
		FileInputStream fin=null;
		byte[]buf=new byte[1024*20];
		int cntBuf=0;
		try {
			fin=new FileInputStream(file);			
			s=new Socket(strIP,port);
			OutputStream sout=s.getOutputStream();
			InputStream sin=s.getInputStream();
			byte[] filename=file.getName().getBytes();
			sout.write(filename);
			
			cntBuf=sin.read(buf);
			if("accept_name".equals(new String(buf,0,cntBuf))){
				System.out.println("filename accepted,begin sending data");
				while(-1!=(cntBuf=fin.read(buf))){					
					sout.write(buf,0,cntBuf);
				}
			}else{
				System.out.println("filename not accepted,closing connection");
			}			
			s.shutdownOutput();
			cntBuf=sin.read(buf);
			System.out.println(new String(buf,0,cntBuf));
		}
		catch (FileNotFoundException e) {
			e.printStackTrace();
			throw new RuntimeException("cannot find the file");
		}
		catch (UnknownHostException e) {
			e.printStackTrace();
			throw new RuntimeException("cannot find the host");
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		finally{
			if(null!=fin){
				try {
					fin.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if(null!=s){
				try {
					s.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

}

class Session implements Runnable {
	private Socket sClient;
	private String path="G:\\Codes\\Language\\JAVA\\Project\\eclipse\\workspace\\test\\temp";
	public Session(Socket sClient) {
		super();
		this.sClient = sClient;
	}

	public void run() {
		byte[] buf=new byte[1024*20];
		int cntBuf=0;
		FileOutputStream fout=null;	
		InputStream sin=null;
		OutputStream sout=null;


		try {
			sin=sClient.getInputStream();
			sout=sClient.getOutputStream();
				
			cntBuf=sin.read(buf);
			String fileName=new String(buf,0,cntBuf);
			System.out.println(fileName);	
			if(checkName(fileName)){				
				fout=new FileOutputStream(new File(path,getTimeNow()+fileName));				
			
				sout.write("accept_name".getBytes());
			
				while(-1!=(cntBuf=sin.read(buf))){
					fout.write(buf,0,cntBuf);
				}
				sout.write("upload completely".getBytes());
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally{
			try {
				sClient.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
			if(null!=fout){
				try {
					fout.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	private String getTimeNow() {
		SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd_hh-mm-ss-SSS");		
		return "["+sdf.format(new Date())+"]";
	}	
	// 可以利用此方法检查上传文件名		
	private boolean checkName(String string) {		
		return true;
	}
}

//TCPServer
class test2 {
	private static int port=12345;
	
	public static void main(String[] args){
		ServerSocket sServer=null;

		try {
			sServer=new ServerSocket(port);
			while(true)
			{
				new Thread(new Session(sServer.accept())).start();				
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally{
			if(null!=sServer){			
				try {
					sServer.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}


class TCPClient{
	public static void main(String[] args) {
		new Thread(new TCPSender("192.168.1.100",12345,new File("F:\\WallPaper\\Wall102.jpg"))).start();
	}
	
}

四、URL和URLConnection

(一)URL

方法:

1       URL(Stringprotocol,String host,int port,String file);//根据指定 protocol、host、port号和 file 创建 URL对象。

2       StringgetProtocol();//获取协议名称

3       StringgetHost();//获取主机名

4       intgetPort();//获取端口号

5       StringgetFile();//获取URL文件名

6       StringgetPath();//获取此URL的路径部分

7       StringgetQuery();//获取此URL的查询部,客户端传输的特定信息

一般输入网址,是不带端口号的,此时可进行获取,通过获取网址返回的port,若port为-1,则分配一个默认的80端口,可能的实现形式:

       int port = getPort();

       if(port == -1){port = 80;}

(二)URLConnection

获取URLConnection对象:

URLConnection openConnection();//返回URLConnection 对象,表示到 URL 所引用的远程对象的连接。

//URL url=…;

URLConnection uc=url.openConnection();

 

URLConnection可以获取连接可使用的IO流

InputStream getInputStream();//获取输入流

OutputStream getOutputStream();//获取输出流


try{  
    //封装地址对象  
URL url =new URL(path);
    URLConnection conn=url.openConnection();  
    //获取流,用于读取服务器返回数据  
    InputStream in=conn.getInputStream();  
    //读取数据
    byte[] buf=new byte[1024*1024];  
    int len=in.read(buf);  
    //将数据显示在文本区中  
    System.out.println(new String(buf,0,len));  
}catch (Exception e){  
    throw new RuntimeException("连接"+path+"网站失败");  
}  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值