网络编程

端口号是用两个字节(16位的二进制数)表示的,它的取值范围是0~65535,其中,0~1023之间的端口号用于一些知名的网络服务和应用,用户的普通应用程序需要使用1024以上的端口号,从而避免端口号被另外一个应用或服务所占用。
package com.igeek_01;/*** @author Lynn* @create 2020-12-16-10:20*/import java.net.InetAddress;import java.net.UnknownHostException;/*** 凡是.net包下的内容都是关于网络的api*/public class IPDemo {public static void main(String[] args) throws UnknownHostException {//获取本地IP地址InetAddress localhost=InetAddress.getLocalHost();System.out.println(localhost);//Lynn/192.168.2.184//获取字符串类型的IPString hostname=localhost.getHostName();System.out.println(hostname);//LynnString hostAddress=localhost.getHostAddress();System.out.println(hostAddress);//192.168.2.184//获取其他IP地址InetAddress byName=InetAddress.getByName("Lynn");System.out.println(byName);//Lynn/192.168.2.184}}
UDP

发送和接收均可以使用的Socket类:
DatagramSocket
数据打包的相关类:
DatagramPacket
- 使用UDP接收数据的步骤:
1、建立接收端;
public DatagramSocket(int port): 指定程序端口号,方便发送端寻找
2、建立数据包,用于接收数据;
public DatagramPacket(byte[] buf, int length)
3、调用Socket的接收方法;
4、解析数据 ;
public byte[] getData(): 获取数据报包中的数据
public int getLength(): 获取数据报包中的数据长度
public InetAddress getAddress(): 获取发送方的IP
public int getPort(): 获取发送方的端口号
5、关闭Socket。
案例1
```java package com.igeek_02;
import java.io.IOException; import java.net.*;
/**
- UDP是一个传输协议 *
当前的服务器端用于接收数据 */ public class UDPService { public static void main(String[] args) throws IOException {
//建立连接DatagramSocket ds=new DatagramSocket(123);//建立数据包,用于接收数据byte[] bytes=new byte[1024];DatagramPacket dp=new DatagramPacket(bytes, bytes.length);//调用socket方法接收数据ds.receive(dp);//解析数据--针对数据包进行解析InetAddress sendAddress=dp.getAddress();String sendIP=sendAddress.getHostAddress();int sendPort=dp.getPort();//端口号//获取数据包中的数据byte[] data=dp.getData();int length=dp.getLength();//将字节数组转换成字符串--String的构造函数String s = new String(data, 0, length);//输出System.out.println("接收到来自"+sendIP+"的,端口号为"+sendPort+"的数据"+ s);//关闭ds.close();
} }
java package com.igeek_02;
/**
- @author Lynn
- @create 2020-12-16-11:21 */
import java.net.*;
/**
发送端 */ public class UDPSend { public static void main(String[] args) throws Exception, UnknownHostException {
//建立连接DatagramSocket ds=new DatagramSocket();//创建数据String s="I Love Java";//数据打包byte[] data=s.getBytes();//将字符串转化为字节数组int length= data.length;InetAddress address=InetAddress.getByName("192.168.2.184");int port=123;//必须与接收端的一致DatagramPacket dp=new DatagramPacket(data,length,address,port);//调用方法进行发送ds.send(dp);//关闭连接ds.close();
案例2
```java package com.igeek_03;
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress;
/**
- UDP是一个传输协议 *
当前的服务器端用于循环接收数据 */ public class UDPService { public static void main(String[] args) throws IOException {
//建立连接DatagramSocket ds=new DatagramSocket(123);//反复接收数据while (true){//建立数据包,用于接收数据byte[] bytes=new byte[1024];DatagramPacket dp=new DatagramPacket(bytes, bytes.length);//调用socket方法接收数据ds.receive(dp);//解析数据--针对数据包进行解析InetAddress sendAddress=dp.getAddress();String sendIP=sendAddress.getHostAddress();int sendPort=dp.getPort();//端口号//获取数据包中的数据byte[] data=dp.getData();int length=dp.getLength();//将字节数组转换成字符串--String的构造函数String s = new String(data, 0, length);//输出System.out.println("接收到来自"+sendIP+"的,端口号为"+sendPort+"的数据:"+ s);}/*//关闭ds.close();*/
} }
java package com.igeek_03;
/**
- @author Lynn
- @create 2020-12-16-11:21 */
import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Scanner;
/**
发送端 */ public class UDPSend { public static void main(String[] args) throws Exception, UnknownHostException {
//建立连接DatagramSocket ds=new DatagramSocket();//循环发送while (true){//创建数据--灵活的数据Scanner sc=new Scanner(System.in);System.out.println("请输入数据:");String s=sc.next();//数据打包byte[] data=s.getBytes();//将字符串转化为字节数组int length= data.length;InetAddress address=InetAddress.getByName("192.168.2.184");int port=123;//必须与接收端的一致DatagramPacket dp=new DatagramPacket(data,length,address,port);//调用方法进行发送ds.send(dp);/*//关闭连接ds.close();*/}
练习
```java package Test01;
/**
- @author Lynn
- @create 2020-12-16-20:19 */
import java.io.IOException; import java.net.*; import java.util.Scanner;
/**
- 一、 项目需求:请用户完成一个UDP接收端作为模拟网络聊天室的操作。
- 1:创建UDP传输下的聊天室发送端UDPSend类
- 2: 创建UDP传输下的聊天室接收端 Room类
- 1.2. 操作步骤描述
- 建立项目目录:day14作业_Test2_1
- 创建UDPSend类,并包含main()方法;
- 在该main方法中
- a、建立UDP的Socket服务;
- b、将要发送的数据封装到数据包中;
- c、通过UDP的Socket服务将数据包发送出去;
- d、关闭Socket服务
- 创建Room类 使用UDP接收端实现网络聊天效果
- 该类中写main方法 步骤如下
- a、建立UDP的Socket服务,因为要接收数据,所以必须明确一个端口号;
- 添加while(ture)循环,不断的循环接收内容
- b、创建数据包,用于存储接收到的数据,方便用数据包对象的方法解析这些数据;
- c、使用UDP的Socket服务的receive方法接收数据并存储到数据包中;
d、通过数据包的方法解析这些数据; */ public class UDPSend { public static void main(String[] args) throws IOException { //建立UDP的Socket服务 DatagramSocket datagramSocket=new DatagramSocket();
//将数据存放到数据包 //循环发送 while (true){ Scanner sc=new Scanner(System.in); System.out.println(“请输入数据:”); String s=sc.next();
//打包数据 byte[] bytes=s.getBytes();//将字符串转换为字节数组 int length= bytes.length; InetAddress inetAddress=InetAddress.getByName(“192.168.2.184”); int port=8888; DatagramPacket dp=new DatagramPacket(bytes,length,inetAddress,port);
//发送 datagramSocket.send(dp);
///关闭服务 datagramSocket.close();/ }
} }
java package Test01;
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException;
/**
- @author Lynn
@create 2020-12-16-20:38 */ public class Room { public static void main(String[] args) throws IOException {
//建立连接DatagramSocket ds=new DatagramSocket(8888);//不断循环接收数据while (true){//创建数据包接收数据byte[] bytes=new byte[1024];DatagramPacket dp=new DatagramPacket(bytes, bytes.length);//接收数据包ds.receive(dp);//解析数据InetAddress sendAddress=dp.getAddress();String sendIP= sendAddress.getHostAddress();int port=dp.getPort();//存入byte[] data=dp.getData();int length= dp.getLength();//将字节数组转换为字符串String s=new String(data,0,length);System.out.println("接收到来自"+sendIP+"的,端口号为:"+port+"的数据:"+s);}
网络模型
网络模型是计算机网络通讯规范,一般符合以下规则:
OSI(Open System Interconnection开放系统互连)参考模型;
TCP/IP参考模型。
TCP协议
案例1
```java package com.igeek_04;
/**
- @author Lynn
- @create 2020-12-16-14:23 */
import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket;
/**
当前案例演示客户端发送信息,服务器端接收信息 */ public class Server { public static void main(String[] args) throws Exception {
//建立服务器端ServerSocket serverSocket=new ServerSocket(8888);//当前是服务器端,所以先获取IO流的同时需要等待客户端发送数据过来Socket socket= serverSocket.accept();//建立连接之后,通过Socket中的IO流进行数据传输InputStream inputStream = socket.getInputStream();//读取的是一个字节int read = inputStream.read();System.out.println((char)read);//关闭--两个都要关闭socket.close();serverSocket.close();
} }
java package com.igeek_04;
/**
- @author Lynn
- @create 2020-12-16-14:29 */
import java.io.IOException; import java.io.OutputStream; import java.net.Socket;
/**
- 客户端 *1.建立客户端
- 2.连接后,通过socket中的流进行传输
3.关闭 */ public class Client { public static void main(String[] args) throws Exception {
//建立客户端Socket socket=new Socket("127.0.0.1",8888);//建立连接后开始传输OutputStream outputStream=socket.getOutputStream();//输出数据outputStream.write(97);//关闭outputStream.close();
案例2—演示跟同桌的初步信息传输
```java package com.igeek_05;
/**
- @author Lynn
- @create 2020-12-16-14:23 */
import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; import java.util.Scanner;
/**
当前案例演示客户端发送信息,服务器端接收信息 */ public class Server { public static void main(String[] args) throws Exception {
//建立服务器端ServerSocket serverSocket=new ServerSocket(8888);//当前是服务器端,所以先获取IO流的同时需要等待客户端发送数据过来Socket socket= serverSocket.accept();//建立连接之后,通过Socket中的IO流进行数据传输InputStream inputStream = socket.getInputStream();//反复读取客户端发送的数据int read=-1;while ((read=inputStream.read())!=-1){System.out.print((char)read);}//接收客户端数据后要返回一个o给客户端while (true){OutputStream outputStream=socket.getOutputStream();Scanner sc=new Scanner(System.in);System.out.println("请输入数据:");String content=sc.next();outputStream.write(content.getBytes());//将字符串转化为字节传输}
/*//关闭--两个都要关闭socket.close();serverSocket.close();*/}
}
```javapackage com.igeek_05;/*** @author Lynn* @create 2020-12-16-14:29*/import java.io.InputStream;import java.io.OutputStream;import java.net.Socket;import java.util.Scanner;/*** 客户端*1.建立客户端* 2.连接后,通过socket中的流进行传输* 3.关闭** 改进:* 客户端发送一个字符串:I Love Java信息,接收服务器端返回的一个字母o的响应** void shutdownoutput():禁止输出流,告知对方*/public class Client {public static void main(String[] args) throws Exception {//建立客户端Socket socket=new Socket("192.168.2.181",8888);//建立连接后开始传输OutputStream outputStream=socket.getOutputStream();//输出数据while (true){Scanner sc=new Scanner(System.in);System.out.println("请输入数据:");String content=sc.next();outputStream.write(content.getBytes());//将字符串转换为字节数组//告诉服务器,不需要发送数据了socket.shutdownOutput();//获取服务器端的响应InputStream inputStream= socket.getInputStream();byte[] bytes=new byte[1024];int len=-1;while ((len= inputStream.read(bytes))!=-1){String s=new String(bytes,0,len);System.out.print(s);}/*//关闭outputStream.close();*/}}}
练习1
package Test02;/*** @author Lynn* @create 2020-12-16-20:48*/import java.io.IOException;import java.io.InputStream;import java.net.ServerSocket;import java.net.Socket;/*** 一、 需求说明:使用TCP编写一个网络程序,设置服务器程序监听端口为8002,当于客户端建立后,向客户端发送”hello world”,客户端将信息输出* 2.2. 操作步骤描述* 1. 建立项目:day14作业_Test2_2* 2. 创建TCPServer类,包含main()方法* 使用ServerSocket创建服务器对象,监听8002端口,调用accept()方法等待客户端连接,当于客户端连接上之后,获取输出流对象,输出”hello world”* 3. 创建TCPClient类,包含main()方法* 使用Socket创建客户端对象,指定服务器IP和端口号,与服务器端建立连接后,获取输入流对象,读取数据,并打印.*/public class TCPServer {public static void main(String[] args) throws IOException {//创建服务器对象,建立连接ServerSocket serverSocket=new ServerSocket(8002);//调用accept方法Socket socket= serverSocket.accept();//获取socket的io流InputStream in= socket.getInputStream();//读取数据byte[] bytes=new byte[1024];int len=-1;while ((len=in.read(bytes))!=-1){String s=new String(bytes,0,len);System.out.println(s);}// in.close();socket.close();serverSocket.close();}}
package Test02;import java.io.IOException;import java.io.OutputStream;import java.net.Socket;/*** @author Lynn* @create 2020-12-16-20:49*/public class TCPClient {public static void main(String[] args) throws IOException {//建立连接Socket socket=new Socket("192.168.2.184",8002);//获取流对象OutputStream out= socket.getOutputStream();//输入数据String s="hello world";byte[] bytes=s.getBytes();out.write(bytes);out.close();socket.close();}}
案例3—文件上传
package com.igeek_06;/*** @author Lynn* @create 2020-12-16-15:13*/import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.ServerSocket;import java.net.Socket;/*** 文件上传,服务器端接收到客户端文件中的数据,向服务器端的另一个文件中写出* 接收到文件内容,写到某个文件中** 这里的数据是文件中的内容*/public class Server {public static void main(String[] args) throws Exception {//建立服务器端ServerSocket serverSocket=new ServerSocket(8888);//获取流Socket socket = serverSocket.accept();//建立连接以后获取socket的流InputStream inputStream=socket.getInputStream();//获取到上传文件的内容,要有一个文件FileOutputStream fos=new FileOutputStream("面向对象堂测答案-copy.docx");//反复使用一个字节读取int len=-1;while ((len= inputStream.read())!=-1){//一次读取一个字节,最终这个文件接受了所有的上传数据fos.write(len);}//关闭IO流fos.close();//给客户端返回一个响应OutputStream out= socket.getOutputStream();String content="o";out.write(content.getBytes());//关闭socketsocket.close();serverSocket.close();}}
package com.igeek_06;/*** @author Lynn* @create 2020-12-16-15:13*/import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.Socket;/*** 上传文件* 读取文件内容,发送给服务器端*/public class Client {public static void main(String[] args) throws Exception {//建立客户端Socket socket=new Socket("localhost",8888);//建立连接后,获取socket的流OutputStream out= socket.getOutputStream();//获取文件对象FileInputStream fis=new FileInputStream("面向对象堂测答案.docx");//读取文件内容int len=-1;while ((len= fis.read())!=-1){//输出数据给服务器out.write(len);}//关闭流fis.close();//告知服务器,不再发送数据socket.shutdownOutput();//获取输入流,接收服务器端的响应InputStream in= socket.getInputStream();int read= in.read();System.out.println((char)read);socket.close();}}
练习2
/*** @author Lynn* @create 2020-12-16-21:08*/import java.io.*;import java.net.ServerSocket;import java.net.Socket;/*** 一、 需求说明:我们来做一个“文件上传案例”,有以下要求:* 将项目中的一个图片,通过客户端上传至服务器* 1.2. 操作步骤描述* 1,创建服务器,等待客户端连接* 2,创建客户端Socket,连接服务器* 3,获取Socket流中的输出流,功能:用来把数据写到服务器* 4,创建字节输入流,功能:用来读取数据源(图片)的字节* 5,把图片数据写到Socket的输出流中(把数据传给服务器)* 6,客户端发送数据完毕,结束Socket输出流的写入操作,告知服务器端* 7,获取Socket的输入流* 8,创建目的地的字节输出流* 9,把Socket输入流中的数据,写入目的地的字节输出流中* 10,获取Socket的输出流, 作用:写反馈信息给客户端* 11,写反馈信息给客户端* 12,获取Socket的输入流 作用: 读反馈信息* 13,读反馈信息*/public class Server {public static void main(String[] args) throws IOException {//创建服务器,建立连接ServerSocket serverSocket=new ServerSocket(8888);//调用socket的接收方法Socket socket=serverSocket.accept();//接收socket的IO流InputStream inputStream= socket.getInputStream();//创建字节输出流FileOutputStream fos=new FileOutputStream("jackson2-1.jpg");//读取流中的内容int len=-1;while ((len= inputStream.read())!=-1){fos.write(len);}fos.close();//服务端接收到数据后给客户端一个响应OutputStream out= socket.getOutputStream();String s="over";out.write(s.getBytes());serverSocket.close();socket.close();}}
import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.Socket;/*** @author Lynn* @create 2020-12-16-21:08*/public class Socker {public static void main(String[] args) throws IOException {//创建连接Socket socket=new Socket("127.0.0.1",8888);//获取流OutputStream outputStream= socket.getOutputStream();//读取文件内容FileInputStream fis=new FileInputStream("jackson2.jpg");int len=-1;while ((len= fis.read())!=-1){outputStream.write(len);}fis.close();//告知服务器不再发送数据了socket.shutdownOutput();//客户端接收服务端的响应InputStream inputStream= socket.getInputStream();int length=-1;while ((length= inputStream.read())!=-1){System.out.print((char)length);}socket.close();}}
