------- 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("服务端失败");
}
}
}