黑马程序员 网络编程


-----------android培训java培训、java学习型技术博客、期待与您交流! -----------


网络通信流程:
每台机子有一个IP,找到对方的IP,然后本机某端口的进程发送数据过去。对方有着相应端口号的进程获取数据。

IP地址:网络中设备的标识。本地回环地址:127.0.0.1主机名:localhost


端口:标识进程的逻辑地址。
有效端口:0~65535,其中0~1024是系统使用或保留的端口。

网络参考模型


发送数据从上到下不断进行包装,接受数据从下到上解包
数据在网络上传输的常见协议:
UDP:

1,将数据,源和目的封装在数据包中。。
2,数据大小限制在64K内。
3,不需要建立连接,故不可以靠,但速度快。
TCP:
1,点对点之间的通信,需要建立连接。
2,在连接中可以进行大量数据的传输。
3,通过三次握手来确保链接成功,协议可靠,但效率不高。


net包中

InetAddress类:没有构造函数,不需要new。静态方法返回该类,非静态方法进行使用。
常用方法:
静态:
getLocalHost() 返回本地主机。
getByName(String host) :在给定主机名的情况下确定主机的 IP 地址。
InetAddress[] getAllByName(String host) :在给定主机名的情况下,根据系统上配置的名称服务返回其 IP 地址所组成的数组。 例如百度,会有很多台主机,不只一个IP。
非静态:
String getHostAddress()  :  返回 IP 地址字符串(以文本表现形式)。
String getHostName()   : 获取此 IP 地址的主机名  

eg:

class IPDemo
{
	public static void main(String[] args)throws Exception
	{
		InetAddress i = InetAddress.getLocalHost();
		//获取本地主机IP
		System.out.println("address:"+i.getHostAddress());
		//获取主机名称。
		System.out.println("name:"+i.getHostName());
		//获取百度主机的IP
		InetAddress ia = InetAddress.getByName("www.baidu.com");
		//InetAddress[] ia = InetAddress.getAllByName("www.baidu.com");
		System.out.println("address:"+ia.getHostAddress());
		System.out.println("name:"+ia.getHostName());
	}
}

Socket类:为网络服务提供的机制。


UDP传输:
DatagramSocket类:

void receive(DatagramPacket p) 从此套接字接收数据报包。 
void send(DatagramPacket p)  从此套接字发送数据报包。
void close() 关闭此套接字。 

DatagramPacket类:用来封装和接受数据。
构造函数中:
DatagramPacket(byte[] buf, int length) 
接受长度为length的数据包
DatagramPacket(byte[] buf, int length, InetAddress address, int port) 
  构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。

使用UDP建立客户端与服务端的方式:
发送端:

1,建立服务
DatagramSocket ds = new DatagramSocket(6666);//这里端口不指定,系统将自动分配。
2,将数据封装成数据包
byte[] buf = "发送的数据".getBytes();
DatagramPacket dp =new DatagramPacket(buf,buf.length,InetAddress.getByName("www.baidu.com"),10000)
3,发送
ds.send(dp);
4,关闭资源
ds.close();

接收端:
1,建立服务
DatagramSocket ds = new DatagramSocket(10000);
2,定义一个数据包,用来存储数据。
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf, buf.length) ;
3,接受数据,存储到dp数据包中。 
ds.receive(dp);//阻塞式方法。
4,用数据包中的方法获取其中数据。
int port = dp.getPort();//发送端的数据端口6666.
String ip = dp.getAddress().getHostAddress();
String data = new String(dp.getData(),0,dp.getLength());
System.out.println(ip+":"+data+":"+port);
ds.close();

TCP传输:
客户端对应的对象是Socket
服务端对应的对象是ServerSocket

Socket:
Socket(InetAddress address, int port) 
          创建一个网络流并将其连接到指定 IP 地址的指定端口号。
Socket(String host, int port) 
          创建一个网络流并将其连接到指定主机上的指定端口号
Socket可以获取字节输入输出流。进行数据传输。

InetAddress getInetAddress()  返回网络流连接的地址对象。 


ServerSocket:
ServerSocket(int port, int backlog) :利用指定的 backlog 创建服务器套接字并将其绑定到指定的本地端口号。
                                                                  backlog代表能连接到服务器的客户端的最大个数。

Socket accept() :侦听并接受到此网络流的连接 。

通过TCP建立客户端和服务端的方式:

客户端:
1,建立链接:
Socket s = new Socket("192.168.1.255",10002);
2,发送数据,获取输出流:
OutputStream os = s.getOutputStream();
os.write("客户端数据".getBytes());
3,获取服务端的数据
InputStream in = s.getInputStream();
byte[] buf =new byte[1024];
int len = in.read(buf);
new String(buf,0,len)
3,关闭链接。
s.close();

服务端:
1,建立链接,并监听一个端口。:
ServerSocket ss = new ServerSocket(10002);
2,通过accept方法获取连接过来的客户端对象。accept方法是阻塞式的。
Socket s = ss.accept();
//获取客户端的Ip:
String ip =s.getInetAddress().getHostAddress()
3,获取客户端发过来的数据,使用客户端对象的读取流来读取数据(该源是网络流)
InputStream in = s.getInputStream();
byte[] buf = new byte[1024];
int len = in.read(buf);
new String(buf,0,len);
4,给客户端发数据
OutputStream out = s.OutputStream();
out.write("好的收到".getBytes());
4,关闭客户端
s.close();
5,关闭服务端
ss.close();

eg:

class TcpClient
{
	public static void main(String[] args)throws Exception
	{
		//建立Socket对象,目标指向指定IP和端口。
		Socket s = new Socket("192.168.1.102",10001);
		//输出语句
		OutputStream out = s.getOutputStream();
		out.write("服务端你好".getBytes());
		//读取服务端发过来的信息
		InputStream in = s.getInputStream();
		byte[] buf = new byte[1024];
		int len = in.read(buf);
		System.out.println(new String(buf,0,len));
		s.close();
	}
}
class TcpServer
{
	public static void main(String[] args)throws Exception
	{
		//建立服务监听。
		ServerSocket ss = new ServerSocket(10001);
		Socket s = ss.accept();//获取服务端的socket对象,
		String ip = s.getInetAddress().getHostAddress();
		System.out.println(ip+"....is connected");
		//输入流读取客户端发来的信息
		InputStream in = s.getInputStream();
		byte[] buf = new byte[1024];
		int len = in.read(buf);
		System.out.println(new String(buf,0,len));
		//输出流将信息发给客户端。
		OutputStream out = s.getOutputStream();
		out.write("客户端,你也好".getBytes());
		s.close();	
	}
}

注意:如果在传输数据中用到缓冲技术,记得flush刷新。输出流可以用PrintStream进行优化。
     客户端,服务端都有阻塞式方法,这些方法需要结束标记。用readLine(),
    如果让服务端停止循环,可以在客户端加上   s.shutdownOutput();   关闭客户端的输出流。

            为了能让多客服并发访问服务器。最好将每个客户端封装到一个单独线程中。
            定义线程:将每个客户端要在服务端执行的代码存到run方法中。

eg:

class ServerThread implements Runnable
{
	private Socket s;
	ServerThread(Socket s)
	{
		this.s = s;
	}
	public void run()
	{
		String ip = s.getInetAddress().getHostAddress();
		System.out.println(ip+"...连接成功");
		try{
			InputStream in = s.getInputStream();
			File f = new File("Copy.jpg");		
			FileOutputStream fo = new FileOutputStream(f);
			byte[] buf = new byte[1024];
			int len = 0;
			while((len=in.read(buf))!=-1){
				fo.write(buf,0,len);
			}
			OutputStream out = s.getOutputStream();
			out.write("上传成功".getBytes());
			fo.close();
			s.close();
		}
		catch(Exception e)
		{
			throw new RuntimeException("上传错误");
		}
	}
}
class TcpServer
{
	public static void main(String[] args)throws Exception
	{
		ServerSocket ss = new ServerSocket(10001);
		while(true)
		{
			Socket s = ss.accept();
			new Thead(new ServerThread(s)).start();
		}
	}
}


Tomcat服务器,纯java编写的服务器。功能强大。

URL类,用来封装网址,在用java建立浏览器的时候,可以用来解析服务器传过来的消息头。

URL url = new URL("http://www.baidu.com");
URLConnection conn = url.openConnection();//获取URL所引用的远程对象的连接。
conn.getInputStream();//获取网络读取流。通过该流获取的内容,过滤掉了响应头。

SocketInetAddress类,封装的是IP地址加端口。

感觉如果要封一个网站,可以将网站在DNS服务器中的映射修改或擦除。使用户无法通过域名访问该网站。

-----------android培训java培训、java学习型技术博客、期待与您交流! -----------


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值