引言
网络是计算机通信的基础,网络编程是学习计算机网络最佳方法,通常标准的计算机网络通信协议有UDP和TCP两种(此处不包含微计算机网络通信协议(如CAN等)),首先小猿引入几个面试常见的问题。
1、网络编程三要素是什么?
答:网络编程的三要素是,ip,传输协议,端口号。
2、网络模型有几种?如何理解?
答:网络模型现常见的有五层分发,七层分法、还有四层说法,这几种分法的示意图如下所示:
7层示意图和各层协议解释。
7层协议和5层协议对比
每个iso层所用到的协议。
3、我们的编程属于那一层?
答:我们的编程属于应用层。
下文将重点介绍有关UDP和TCP相关的编程。
UDP
UDP是一种用户协议,它是一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务。UDP特点:
UDP是无连接的,即通信时不需要创建连接,可减少网路资源开销(报文字节比较少),可缩短发送时间,UDP可采用广播等通行方式。
案例
采用udp协议实现一收一发。
udp发送端程序
public class UDPSendDemo {
public static void main(String[] args) throws IOException {
DatagramSocket ds = new DatagramSocket();
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line;
while ((line = br.readLine()) !=null){
byte[] bytes = line.getBytes();
DatagramPacket dp = new DatagramPacket(bytes, bytes.length,
InetAddress.getByName("192.168.168.1"), 12345);
ds.send(dp);
if("886".equals(line)){
break;
}
}
ds.close();
br.close();
System.out.println("send socket closed ");
}
}
UDP接收端代码
public class UDPReceiveDemo {
public static void main(String[] args) throws IOException {
DatagramSocket ds = new DatagramSocket(12345);
while (true){
byte[] bytes = new byte[1024];
DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
ds.receive(dp);
String data = new String(dp.getData(), 0, dp.getLength());
System.out.println("data is ,"+data);
if("886".equals(data)){
break;
}
}
ds.close();
System.out.println("receive socket closed");
}
}
运行结果
发送端
接收端
TCP
TCP通信协议是一种可靠的网络协议,他在通信的两端各建立一个Socket对象,从而在通行的两端形成网络虚拟链路,一旦建立了虚拟网络链路,两端的程序就可以通过虚拟链路进行通信。
TCP协议的特点是
1、面向连接的:使用TCP协议通信的双方必须先建立连接,然后才能开始数据的读写,TCP连接是全双工的,即双方的数据读写可以通过一个连接进行。完成数据交换之后,通信双方都必须断开连接以释放资源。TCP协议的这种连接是一对一的,所以基于广播和多播(目标是多个主机地址)的应用程序不能使用TCP服。
2流式服务:TCP的字节流服务的表现形式就体现在,发送端执行的写操作数和接收端执行的读操作次数之间没有任何数量关系,当发送端应用程序连续执行多次写操作的时,TCP模块先将这些数据放入TCP发送缓冲区中。当TCP模块真正开始发送数据的时候,发送缓冲区中这些等待发送的数据可能被封装成一个或多个TCP报文段发出。
若想更加详细的去看计算机网络知识,请看这位大佬的计算机网络文章。
案例一
客户端发送数据,服务端接收数据并显示在控制台上,当客户端发送终止命令时候时,客户端和服务端都要终止服务。
客户端
public class ClientDemo {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("192.168.152.1", 10001);
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
String line;
while ((line=br.readLine())!=null){
//如果不用socket.getOutPutStream来写的话,我们是否可以用bufferedWrite来写呢。
// OutputStream os = socket.getOutputStream();
// os.write(line.getBytes());
bw.write(line,0,line.length());
bw.newLine();
bw.flush();
if ("999".equals(line)){
break;
}
}
System.out.println("发送客户端停止命令,客户端开始停止");
br.close();
bw.close();
socket.close();
}
}
服务端
public class ServerDemo {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(10001);
Socket accept = ss.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(accept.getInputStream()));
String line;
String str=null;
while (true){
while ((line=br.readLine())!=null){
str=line;
System.out.println(line);
}
if(str.equals("999")){
break;
}
}
System.out.println("接收到停止命令,开始释放服务端资源");
br.close();
ss.close();
}
}
运行结果:
客户端
服务端
案例二
客户端从txt文件中读取数据,将读取的数据发到服务端,服务端将内容读取后重行生成一个文件,并将接收到的内容写入文件中。
服务端线程类
public class ServerThread implements Runnable {
private Socket accept;
public ServerThread(Socket accept) {
this.accept = accept;
}
@Override
public void run() {
BufferedReader br=null;
BufferedWriter bw=null;
BufferedWriter bwServer=null;
try {
br = new BufferedReader(new InputStreamReader(accept.getInputStream()));
bw = new BufferedWriter(new FileWriter(Thread.currentThread().getName() + "copy.java"));
String line;
while ((line=br.readLine())!=null){
bw.write(line);
bw.newLine();
bw.flush();
}
bwServer = new BufferedWriter(new OutputStreamWriter(accept.getOutputStream()));
bwServer.write(Thread.currentThread().getName() + "文件上传成功");
System.out.println(Thread.currentThread().getName()+"文件上传成功");
bwServer.newLine();
bwServer.flush();
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
br.close();
bw.close();
bwServer.close();
accept.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
服务端主类
public class Server02Demo {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(10001);
while (true){
Socket accept = ss.accept();
new Thread(new ServerThread(accept)).start();
}
}
}
客户端类
public class Client02Demo {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("192.168.152.1",10001);
BufferedReader br = new BufferedReader(new FileReader("reader&writer\\Client.txt"));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
String line;
while ((line = br.readLine())!=null){
bw.write(line);
bw.newLine();
bw.flush();
}
socket.shutdownOutput();
BufferedReader brClient = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String data = brClient.readLine();
System.out.println("服务器的反馈是:"+data);
brClient.close();
br.close();
bw.close();
socket.close();
}
}
运行结果
服务端测试结果
客户端测试结果
运行结果符合预期,本章案例结束。