黑马程序员_网络编程

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


一 网络编程

1 网络模型:传输方式
(1)OSI参考模型,共7层。应用层、表示层、会话层、传输层、网络层、数据链路层、物理层。每一层都有自己特有的数据信息。
(2)TCP/IP参考模型,共5层。应用层、传输层、网际层、主机至网络层。

2 网络通信要素
(1)IP地址。IP地址用于标识网络设备,可起个主机名字。本地回环地址,默认127.0.0.1
(2)端口号。应用程序的一个数字标识,对方指定的应用程序。端口限定在0-65535。而0-1024被系统保留。
常见端口:
Tomcat 8080、Web服务80

(3)传输协议。传输协议可以理解为通信规则。国际通用协议TCP/IP。常见的传输方式有UDP和TCP。

3 IP地址
(1)java将IP地址封装成对象。InetAddress类

(2)此类中没有定义构造方法
方法摘要:
getLocalHost()//获取本地主机InetAddress对象
getByName(String host)//获取任意主机InetAddress对象
getHostAddress()//获取主机地址
getHostName()//获取主机名字


4 传输协议:通信规则
(1)常见的协议:UDP和TCP
UDP:将数据和目的封装成包,每个包限制在64K以内,面向无连接,是不可靠协议,速度快。 例如:聊天工具、网络视频会议、桌面共享
TCP:进行大数据传输,面向连接,是可靠协议,速度稍慢。例如:下载工具

(2)Socket是为网络服务提供的一种机制,网络两端要进行通信必须先有Socket,网络通信其实就是Socket间的通信,数据在两个Socket间通过io传输

5 UDP传输
(1)UDP分为发送端和接收端
(2)UDP发送端编程思想
1、定义一个Socket服务,用DatagramSocket
2、将数据(数据包括数据,数据大小,地址以及端口)封包,用DatagramPacket
3、通过端点将包发送出去,用send(DatagramPacket)方法
4、关闭资源
代码如下:

代码如下:
import java.net.*;
//发送端
class  SendDemo
{
	public static void main(String[] args) throws Exception
	{
		//定义Socket服务
		DatagramSocket ds=new DatagramSocket();
		//将数据封包
		byte[] buf="发送端发送数据".getBytes();
		DatagramPacket dp=new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.100"),10086);
		//通过Socket服务发送数据包
		ds.send(dp);
		//关闭资源
		ds.close();
	}
}

(3)UDP接收端编程思想
1、定义一个Socket服务,并监听一个端口(如果没有,系统会分配一个,但可能接收不到数据),用DatagramSocket类
2、定义一个数据包用于存储接收到的数据包,用DatagramPacket类
3、用Socket服务的receive(DatagramSocket)方法将接收到的数据包存到定义的数据包中
4、通过数据包特有的方法对数据进行解析
5、关闭资源
代码如下:

import java.net.*;
//接收端
class ReceiveDemo
{
	public static void main(String[] args)throws Exception
	{
		//定义一个Socket服务,并监听一个端口
		DatagramSocket ds=new DatagramSocket(10086);
		//定义一个数据包存储接收到的数据包
		byte[] buf=new byte[1024];
		DatagramPacket dp=new DatagramPacket(buf,buf.length);
		//接收数据并存到数据包中
		ds.receive(dp);
		//解析数据
		String ip=dp.getAddress().getHostAddress();
		int port=dp.getPort();
		String data=new String(dp.getData(),0,dp.getLength());
		System.out.println(ip+"::"+port+"::"+data);
		//关闭资源
		ds.close();
	}
}

(4)练习:编写一个聊天工具,运用多线程一个负责发一个负责收。
代码:

import java.io.*;
import java.net.*;
//定义一个线程负责发送端
class Send implements Runnable
{
	private DatagramSocket ds;
	Send(DatagramSocket ds)
	{
		this.ds=ds;
	}
	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[] buf=line.getBytes();
				//将数据封包并发送
				DatagramPacket dp=new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.100"),10081);
				ds.send(dp);
			}
			bufr.close();
			ds.close();
		}
		catch (Exception e)
		{
			throw new RuntimeException("发送失败");
		}
	}
}
//定义一个线程负责接收端
class Receive implements Runnable
{
	private DatagramSocket ds;
	Receive(DatagramSocket ds)
	{
		this.ds=ds;
	}
	public void run()
	{
		try
		{
			while(true)
			{
				//定义一个数据包用于存储发送端发送的数据
				byte[] buf=new byte[1024];
				DatagramPacket dp=new DatagramPacket(buf,buf.length);
				//接收数据
				ds.receive(dp);
				//通过数据包获取发送端主机和数据
				String ip=dp.getAddress().getHostAddress();
				String data=new String(dp.getData(),0,dp.getLength());
				System.out.println(ip+":"+data);
			}
		}
		catch (Exception e)
		{
			throw new RuntimeException("接收失败");
		}
	}
}

class  UdpDemo
{
	public static void main(String[] args) throws Exception
	{
		//创建发送端线程和接收端线程并执行
		new Thread(new Send(new DatagramSocket())).start();
		new Thread(new Receive(new DatagramSocket(10081))).start();
	}
}

6 TCP传输
(1)TCP分为客户端和服务端
(2)客户端编程思想(客户端定义的是Socket对象)
1、定义Socket服务,并指定服务端地址和端口,通过Socket类
2、通过getOutputStream()方法获取Socket对象的输出流发送数据
3、通过getInputStream()方法获取Socket对象的输入流读取服务端发送的数据
4、关闭资源
代码:

import java.io.*;
import java.net.*;
//客户端
class TcpClient 
{
	public static void main(String[] args) throws Exception
	{
		//定义Socket服务,并指定发送的主机和端口。通过Socket对象
		Socket s=new Socket("192.168.1.100",10009);
		//获取输出流向服务端发送数据
		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();
	}
}

(3)服务端编程思想
1、定义服务端的Socket服务,并监听一个端口,通过ServerSocket类
2、通过accept()方法获取客户端Socket对象
3、通过客户端Socket对象的getInputStream()方法获取输入流读取客户端发送的数据
4、通过客户端Socket对象的getOutputStream()方法获取输出流向客户端发送数据
5、关闭资源(可以不关)
代码:

import java.io.*;
import java.net.*;
//服务端
class TcpServer
{
	public static void main(String[] args)throws Exception
	{
		//定义Socket服务并监听一个端口。通过ServerSocket对象
		ServerSocket ss=new ServerSocket(10009);
		//接收客户端Socket对象
		Socket s=ss.accept();
		String ip=s.getInetAddress().getHostAddress();
		System.out.println(ip+"...连接");
		//通过Socket对象获取输入流读取客户端发送的数据
		InputStream in=s.getInputStream();
		byte[] buf=new byte[1024];
		int len=in.read(buf);
		System.out.println(new String(buf,0,len));
		//通过Socket对象获取输出流向客户端发送数据
		OutputStream out=s.getOutputStream();
		out.write("服务端收到".getBytes());
		//关闭资源
		s.close();
		ss.close();
	}
}

(4)练习:客户端并发登陆服务端。客户端最多只能输入三次,如果都没登陆成功则程序结束。
代码:

import java.io.*;
import java.net.*;
//客户端
class Client1 
{
	public static void main(String[] args) throws Exception
	{
		//创建Socket服务,并指定主机和端口
		Socket s=new Socket("192.168.1.100",10000);
		//获取键盘录入
		BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
		//获取Socket对象输出流将数据发送给服务端
		PrintWriter out=new PrintWriter(s.getOutputStream(),true);
		//获取Socket对象输入流读取服务端发送的数据
		BufferedReader in=new BufferedReader(new InputStreamReader(s.getInputStream()));
		//只能输入3次
		for (int x=0;x<3;x++)
		{
			//读取键盘录入的数据并发送到服务端去
			String line=bufr.readLine();
			if(line==null)
				break;
			out.println(line);
			//读取服务端发送的数据
			String info=in.readLine();
			System.out.println(info);
			//如果提示信息包含欢迎两字就不校验了
			if(info.contains("欢迎"))
				break;
		}
		s.close();
	}
}
//服务端
class Server1
{
	public static void main(String[] args)throws Exception
	{
		//创建服务端Socket服务
		ServerSocket ss=new ServerSocket(10000);
		while (true)
		{
			//获取客户端Socket对象
			Socket s=ss.accept();
			//客户端创建线程并执行
			new Thread(new ClientThread(s)).start();
		}
		
	}
}
//客户端线程
class ClientThread implements Runnable
{
	private Socket s;
	ClientThread(Socket s)
	{
		this.s=s;
	}
	public void run()
	{
		try
		{
			//获取Socket对象的输入流读取客户端发送的数据
			BufferedReader in=new BufferedReader(new InputStreamReader(s.getInputStream()));
			//获取字符输入流读取文本数据
			BufferedReader bufr=new BufferedReader(new FileReader("User.txt"));
			//获取Socket对象的输出流向客户端发送数据
			PrintWriter out=new PrintWriter(s.getOutputStream(),true);
			//只校验三次
			for (int x=0;x<3;x++)
			{
				//读取客户端发送的数据
				String str=in.readLine();
				if(str==null)
					break;
				//读取文本数据
				String line=null;
				boolean flag=false;//定义一个标记
				while ((line=bufr.readLine())!=null)
				{
					//判断客户端发送的数据是否跟文件中读取到的数据一样
					if (line.equals(str))
					{
						//相同的话就改变标记
						flag=true;
						break;
					}
				}
				//判断标记给客户端提示
				if(flag)
				{
					System.out.println("用户已登录");
					out.println("欢迎光临");
					break;
				}
				else
				{
					System.out.println("用户尝试登陆");
					out.println("用户不存在,请重新输入");
				}
					
			}
			s.close();
			bufr.close();
		}
		catch (Exception e)
		{
			throw new RuntimeException("服务端失败");
		}
	}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章