1、概述
- 计算机之间通过传输介质、通信设施和网络通信协议互联,实现资源共享和数据传输。而我们的网络编程就是使用程序使互联网的两个(或多个)计算机之间进行数据传输。当然java语言,为了实现两个计算机之间的数据传输,提供了一系列的接口,使得开发人员可以方便的实现。
2、OSI与TCP/IP模型
模型对比
- TCP/IP支持跨层封装 ;但OSI不支持
- TCP/IP仅仅支持IP网络协议 ;OSI支持多种网络层协议
- TCP是面向连接的可靠的传输协议
- UDP是非面向连接的不可靠的传输协议
TCP/IP模型中的协议剖析
该模型中几个主要的协议术语及其作用
TCP(传输控制协议):通过使用一个校验码检验数据是否发生错误,在接收和转发中都使用计算校验和,并同时对数据进行加密
UDP(用户数据报协议):UDP使用底层的互联网协议来传送报文,同IP一样提供不可靠的无连接数据包传输服务。它不提供报文到达确认、排序、及流量控制等功能
FTP(文件传输协议):让用户连接上一个远程计算机(这些计算机上运行着FTP服务器程序)察看远程计算机有哪些文件,然后把文件从远程计算机上拷到本地计算机,或把本地计算机的文件送到远程计算机去。
SMTP(邮件消息传输协议):SMTP是一种提供可靠且有效电子邮件传输的协议。它是建立在FTP文件传输服务上的一种邮件服务,主要用于传输系统之间的邮件信息并提供来信有关的通知。
SMTP重要的特性之一是它能跨越网络传输邮件,也即“SMTP邮件中继”。使用SMTP,可实现相同网络上处理机之间的邮件传输,也可以通过中继器或网关实现某处理机与其它网络之间的邮件传输。具有域名服务系统(DNS)功能的邮件交换服务器还可以用来识别出传输邮件的下一跳IP地址。
3、IP
- IP(网际协议) :提高网络可扩展性,为主机提供一种无连接的数据传输服务
- 唯一定位一台网络上的计算机
127.0.0.1
为本机地址localhost
4、端口(port)
端口表示计算机的一个程序的进程
不同的进程有不同的端口号,并且端口号不能重复(单个协议下)
端口号范围限制为 0 ~ 65535
端口分类
公有端口 0 ~ 1023
- HTTP :80
- HTTPS :443
- FTP : 21
- Telnet :23
程序注册端口: 1024 ~ 49151 分配用户或程序
- Tomcat :8080
- MySQL :3306
- Oracle :1521
动态私有 49152 ~ 65535
netstat -ano #查看所有端口 netstat -ano|findstr "8080" # 查看指定端口 tasklist|findstr "8696" # 查看指定端口的进程 ctrl + shift +ESC # 调用任务管理器
5、TCP实现聊天
客户端(Client)
获取服务端的地址与端口号
连接服务器端口,建立socket连接
发送信息(IO流)
关闭资源
Socket socket = null; OutputStream os = null; try { //首先要知道服务端的地址和端口号 InetAddress serverIp = InetAddress.getByName("127.0.0.1"); int port = 9999; //建立socket连接 socket = new Socket(serverIp,9999); //发送信息 os = socket.getOutputStream(); os.write("我们已经成为好友,可以开始聊天".getBytes()); } catch (Exception e) { e.printStackTrace(); }finally { if (os != null){ try { os.close(); } catch (IOException e) { e.printStackTrace(); } } if (socket != null){ try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } }
服务端(Server)
建立socket服务器端口
调用端口的accept方法,等待用户端连接
读取用户信息(IO流)的inputStream
建立管道流,把数据从字节流转换为字符流
关闭资源
ServerSocket serverSocket = null; Socket socket = null; InputStream is = null; ByteArrayOutputStream baos = null; try { //给一个服务端的地址 serverSocket = new ServerSocket(9999); //等待客户端接入 socket = serverSocket.accept(); //读取客户端信息 is = socket.getInputStream(); //管道流 baos = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len; while ((len=is.read(buffer))!= -1){ baos.write(buffer,0,len); } System.out.println(baos.toString()); } catch (IOException e) { e.printStackTrace(); }finally { //关闭资源 if(baos !=null){ try { baos.close(); } catch (IOException e) { e.printStackTrace(); } } if (is !=null){ try { is.close(); } catch (IOException e) { e.printStackTrace(); } } if (socket != null){ try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } if (serverSocket != null){ try { serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } }
6、TCP实现文件上传
服务端(Server)
public static void main(String[] args) throws Exception { //创建服务 ServerSocket serverSocket = new ServerSocket(9000); //监听客户端连接 Socket socket = serverSocket.accept(); //获取输入流 InputStream is = socket.getInputStream(); //此处写文件路径最好使用绝对路径,否则会报错 File file = new File("G://IDEA_Project/FIST/src/receive.jpg"); //文件输出 FileOutputStream fos = new FileOutputStream(file); byte[] buffer = new byte[1024]; int len; while ((len = is.read(buffer))!=-1){ fos.write(buffer,0,len); } //通知客户端接收完毕 OutputStream os = socket.getOutputStream(); os.write("服务端接收完毕,你可以断开连接".getBytes()); //关闭资源 (后创建先关闭原则) fos.close(); is.close(); socket.close(); serverSocket.close(); }
客户端(client)
public static void main(String[] args) throws Exception { //创建一个socket连接 Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 9000); //建立一个输出流 OutputStream os = socket.getOutputStream(); //此处写文件路径最好使用绝对路径,否则会报错 File file = new File("G://IDEA_Project/FIST/src/lld.jpg"); //读取文件 FileInputStream fis = new FileInputStream(file); //写入文件 byte[] buffer = new byte[1024]; int len; while ((len= fis.read(buffer)) !=-1){ os.write(buffer,0,len); } //通知服务器,我已经结束啦 socket.shutdownOutput(); //确认服务端接收完毕,才断开连接 InputStream is = socket.getInputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buffer2 =new byte[1024]; int len2; while ((len2 = is.read(buffer2)) != -1){ baos.write(buffer2,0,len2); } System.out.println(baos.toString()); //关闭资源 (后创建先关闭原则) baos.close(); is.close(); fis.close(); os.close(); socket.close(); }
7、UDP实现消息的发送
客户端
public static void main(String[] args) throws Exception { //建立一个socket DatagramSocket socket = new DatagramSocket(); //建立数据包 String msg = "Hello,Server!"; //发送目的地 InetAddress localhost = InetAddress.getByName("localhost"); int port =9090; //数据,数据长度的起始,目的地信息 DatagramPacket packet = new DatagramPacket(msg.getBytes(), 0, msg.getBytes().length, localhost, port); //发送包 socket.send(packet); //关闭流 socket.close(); }
服务端
public static void main(String[] args) throws Exception { //开放端口 DatagramSocket socket = new DatagramSocket(9090); //接收数据包 byte[] buffer = new byte[1024]; DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length); //接收包 socket.receive(packet); //打印输出目的端地址及数据内容 System.out.println(packet.getAddress().getHostName()); System.out.println(new String(packet.getData(), 0, packet.getLength())); //关闭流 socket.close(); }
8、UDP实现循环发送
Sender端
```java
public static void main(String[] args) throws Exception {//建立端口 DatagramSocket socket = new DatagramSocket(8888); //数据,通过控制台输入数据 BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
while (true){
String data = reader.readLine();
byte[] datas = data.getBytes();
DatagramPacket packet = new DatagramPacket(datas,0,datas.length,new InetSocketAddress("localhost",6666));
socket.send(packet);
if (data.equals("bye")){
break;
}
}
socket.close();
}
+ **Receive端**
```java
public static void main(String[] args) throws Exception {
DatagramSocket socket = new DatagramSocket(6666);
while (true){
byte[] container = new byte[1024];
DatagramPacket packet = new DatagramPacket(container, 0, container.length);
//阻塞式接收
socket.receive(packet);
byte[] data = packet.getData();
String receiveData = new String(data, 0, data.length);
System.out.println(receiveData);
if (receiveData.equals("bye")){
break;
}
}
//关闭流
socket.close();
}
- 实际示例:
- 在线咨询:通信双方既是发送方,也是接收方