1.网络概述
OSI七层协议:物理层 数据链路层 网络层 传输层 会话层 表示层 应用层
IP TCP/UDP HTTP FTP POP3 SMTP telnet...
ip地址 - ipv4:用来标识网络中的不同主机的地址信息。 一共四位,每位0~255 。 127.0.0.1永远指向本机。主机在网络中的名称。
DNS服务器 -- 域名解析的公共服务器,可以将主机名翻译成对应的ip。
端口号 : 每一个机器具有很多个端口号 0~65535个 端口号就像我们计算机对外打开的一扇窗户,程序可以指定对应的端口号进行监听。外界访问时除了要通过ip地址找到当前机器以外,还要通过端口号,找到对应窗口,从而找到对应程序为这次请求服务。0~1024是系统自用的我们不能使用,另外一些常见的端口(80、8080、25、110)最好回避开
Hosts文件
TCP/IP 是一套协议族,包含了很多具体功能的协议,其中最重要的是IP协议、TCP协议、UDP协议。
IP协议:
UDP协议:
将数据及源和目的地封装为数据包,不需要建立连接
每个数据报的大小限制在64k内
因为无连接,是不可靠协议
不需要建立连接,速度快
应用场景:对连接速度要求高 数据传输是否可靠不重要的情况下 使用UDP 视频聊天
TCP协议:
建立连接,形成传输数据的通道
在连接中进行大数据量传输
三次握手,是可靠协议
必须先建立连接,效率会稍低
应用场景:对数据可靠性要求高,速度可以妥协的情况下 使用TCP 文件的传输
2.API介绍
static InetAddress getLocalHost() //用来获取本机IP信息
static InetAddress getByName(String host) //获取指定IP信息
String getHostAddress()
返回 IP 地址字符串(以文本表现形式)。
String getHostName()
获取此 IP 地址的主机名。
package com.zll.net;
import java.net.InetAddress;
public class InetAddressDemo1 {
public static void main(String[] args) throws Exception {
// InetAddress addr = InetAddress.getLocalHost();
// InetAddress addr = InetAddress.getByName("127.0.0.1");
InetAddress addr = InetAddress.getByName("www.baidu.com");
String ip = addr.getHostAddress();
String name = addr.getHostName();
System.out.println(ip+":"+name);
}
}
3.Socket编程 -- 套接字编程
本身是一种网络通信方式通信的过程中两头都是Socket
利用Socket可以实现UDP 和 TCP方式的通信。
4.UDP编程
DatagramSocket -- udp服务DatagramSocket()
void receive(DatagramPacket p)
从此套接字接收数据报包。
void send(DatagramPacket p)
从此套接字发送数据报包。
close();
Socket使用完后必须进行close的操作进行关闭。
DatagramPacket -- udp数据包
DatagramPacket(byte[] buf, int length, InetAddress address, int port)
InetAddress addr = dp.getAddress();//获取ip
int port = dp.getPort();//获取端口
int length = dp.getLength();//获取数据的长度
byte [] data = dp.getData();//获取具体的数据
UDP的简单通信:
package zll.material.java_base_homework;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class UDPReceiver {
public static void main(String[] args) throws Exception {
DatagramSocket ds = new DatagramSocket(9989);
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf , buf.length);
ds.receive(dp);//此方法是阻塞的,一直等到接受到数据包才会向下运行
InetAddress addr = dp.getAddress();
int port = dp.getPort();
int length = dp.getLength();
byte [] data = dp.getData();
System.out.println(addr+":"+port+":"+length+":"+new String(data));
ds.close();
}
}
package zll.material.java_base_homework;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/**
UDP发送者
*/
public class UDPSender {
public static void main(String[] args) throws Exception {
DatagramSocket ds = new DatagramSocket();
String str = "hello~udp!";
DatagramPacket dp = new DatagramPacket(str.getBytes(), str.getBytes().length, InetAddress.getByName("127.0.0.1"), 9989);
ds.send(dp);
ds.close();
}
}
群聊255.255.255.255 向这个ip发送的消息,就相当于是一个广播消息,整个网络都可以接受到
package zll.material.java_base_homework;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class ChatReceiver {
public static void main(String[] args) throws Exception {
DatagramSocket socket = new DatagramSocket(9999);
while(true){
DatagramPacket dp = new DatagramPacket(new byte[1024], 1024);
socket.receive(dp);
String ip = dp.getAddress().getHostAddress();
int port = dp.getPort();
String data = new String(dp.getData());
System.out.println("来自"+ip+"~"+port+":"+data);
}
}
}
package zll.material.java_base_homework;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class ChatSender {
public static void main(String[] args) throws Exception {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
DatagramSocket socket = new DatagramSocket();
while(true){
String line = reader.readLine();
DatagramPacket dp = new DatagramPacket(line.getBytes(), line.getBytes().length,InetAddress.getByName("255.255.255.255"),9999);
socket.send(dp);
}
}
}
多线程实现聊天
package zll.material.java_base_homework;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;
public class ChatByThread {
public static void main(String[] args) {
new Thread(new ReceiverThread()).start();
new Thread(new SenderThread()).start();
}
}
class SenderThread implements Runnable{
@Override
public void run() {
try {
DatagramSocket socket = new DatagramSocket();
Scanner scanner = new Scanner(System.in);
while(true){
System.out.println("请输入目标ip:");
String ip = scanner.nextLine();
System.out.println("请输入目标端口:");
int port = Integer.parseInt(scanner.nextLine());
System.out.println("请输入要发送的数据:");
String data = scanner.nextLine();
DatagramPacket dp = new DatagramPacket(data.getBytes(), data.getBytes().length,InetAddress.getByName(ip),port);
socket.send(dp);
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
class ReceiverThread implements Runnable{
@Override
public void run() {
try {
DatagramSocket socket = new DatagramSocket(9999);
while(true){
DatagramPacket dp = new DatagramPacket(new byte[1024],1024);
socket.receive(dp);
String ip = dp.getAddress().getHostAddress();
String name = dp.getAddress().getHostName();
int port = dp.getPort();
String data = new String(dp.getData());
System.out.println(ip+"~"+port+"~"+name+":"+data);
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
5.TCP编程
在TCP中分为客户端和服务器端。主动发出请求的称为客户端,被动等待请求的称为服务端。
一旦连接建立起来可以双向的进行数据的传输。
这种数据的传输是可靠的。
Socket:创建TCP的客户端
Socket连接后可以获取输出/输入的流,通过套接字以流的形式写出/读入数据。
ServerSocket:创建TCP的服务端
TCP双向传输数据
package com.zll.net.tcp;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo1 {
public static void main(String[] args) throws Exception {
ServerSocket ss = new ServerSocket(8899);
Socket socket = ss.accept();//此方法阻塞等待客户端的连接
InputStream in = socket.getInputStream();
byte [] bs = new byte[1024];
int len = in.read(bs);
String str = new String(bs,0,len);
System.out.println(str);
OutputStream out = socket.getOutputStream();
out.write("返回的数据".getBytes());
socket.close();
ss.close();
}
}
package com.zll.net.tcp;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class ClientDemo1 {
public static void main(String[] args) throws Exception {
Socket socket = new Socket("127.0.0.1",8899);
OutputStream out = socket.getOutputStream();
out.write("嘻嘻嘻哈哈哈嘿嘿嘿啦啦啦".getBytes());
byte[] bs = new byte[1024];
InputStream in = socket.getInputStream();
int len = in.read(bs);
String str = new String(bs,0,len);
System.out.println(str);
socket.close();
}
}
实现大小写转换服务器
package com.zll.net.tcp;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class ToUpperServer {
public static void main(String[] args) throws Exception {
ServerSocket ss = new ServerSocket(8877);
Socket socket = ss.accept();
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
while(true){
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line = reader.readLine();
if("over~".equals(line)){
break;
}
String ip = socket.getInetAddress().getHostAddress();
System.out.println("服务器收到:"+ip+"》"+line);
line = line.toUpperCase();
out.write(line.getBytes());
}
socket.close();
ss.close();
}
}
package com.zll.net.tcp;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;
public class ToUpperClient {
public static void main(String[] args) throws Exception {
Socket socket = new Socket("127.0.0.1",8877);
PrintStream print = new PrintStream(socket.getOutputStream());
InputStream in = socket.getInputStream();
Scanner scanner = new Scanner(System.in);
while(true){
System.out.println("输入要转换为大写的数据:");
String line = scanner.nextLine();
print.println(line);
if("over~".equals(line)){
break;
}
byte[] bs = new byte[1024];
int len = in.read(bs);
String str = new String(bs,0,len);
System.out.println(str);
}
socket.close();
}
}
文本文件上传(模拟)
package com.zll.net;
import java.io.BufferedReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Writer;
import java.net.ServerSocket;
import java.net.Socket;
public class UploadServer {
public static void main(String[] args) throws Exception {
ServerSocket ss = new ServerSocket(9988);
while(true){
Socket socket = ss.accept();
Thread thread = new Thread(new UploadThread(socket));
thread.start();
}
}
}
class UploadThread implements Runnable{
private Socket socket = null;
public UploadThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
InputStream in = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
Writer writer = new FileWriter("2.txt");
String line = null;
while((line = reader.readLine())!=null){
writer.write(line);
}
writer.close();
reader.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
package com.zll.net;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.Socket;
public class UploadClient {
public static void main(String[] args) throws Exception {
Socket socket = new Socket("127.0.0.1",9988);
OutputStream out = socket.getOutputStream();
Writer writer = new OutputStreamWriter(out);
BufferedReader reader = new BufferedReader(new FileReader("1.txt"));
String line = null;
while((line = reader.readLine())!=null){
writer.write(line);
}
reader.close();
writer.close();
socket.close();
}
}
图片文件的上传(模拟)
package com.zll.net;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 图片文件上传 服务器
*/
public class UploadServer2 {
public static void main(String[] args) throws Exception {
ServerSocket ss = new ServerSocket(9988);
while(true){
Socket socket = ss.accept();
new Thread(new UploadThread2(socket)).start();
}
}
}
class UploadThread2 implements Runnable{
private Socket socket = null;
private int i = 0;
public UploadThread2(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
InputStream in = socket.getInputStream();
OutputStream out = new FileOutputStream(socket.getInetAddress().getHostAddress()+"_"+(i++)+"_"+".jpg");
int i = -1;
while((i = in.read())!=-1){
out.write(i);
}
in.close();
out.close();
socket.close();
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
package com.tarena.net;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
/**
* 图片文件上传 客户端
*/
public class UploadClient2 {
public static void main(String[] args) throws Exception {
Socket socket = new Socket("127.0.0.1",9988);
OutputStream out = socket.getOutputStream();
InputStream in = new FileInputStream("2.jpg");
int i = -1;
while((i = in.read())!=-1){
out.write(i);
}
in.close();
out.close();
socket.close();
}
}