网络三要素
IP地址, 端口号, 网络协议
ip地址
表示网络中设备的唯一标识
ipv4: 由4个字节组成,采用点分十进制表示法
举例:192.168.66.202
ipv6: 由16个字节组成,采用冒分十六进制表示法
举例:fb34:66:77:ac:3f
常用的命令:
ipconfig: 查看本机的ip地址
ping: 检测网络和指定的ip是否连通
端口号
表示某一台主机上应用程序的表示,是一个[0,65535]范围内的整数.
0~1023的端口号可能会被占用,建议使用1024之后的端口号。
网络协议
网络中数据传输的规则
UDP: 面向无连接的,不安全的协议,每次传输64KB的数据
TCP: 面向有连接,安全的协议,传输数据的大小没有限制。
InetAddress类
public static InetAddress getByName(String host)
在给定主机名的情况下确定主机的 IP 地址。
public String getHostAddress()
返回 IP 地址字符串(以文本表现形式)举例:"192.168.83.44"
public String getHostName()
获取此 IP 地址的主机名。
举例
public class InetAddress0 {
public static void main(String[] args) throws UnknownHostException {
//确认IP地址或主机名称
InetAddress byName = InetAddress.getByName("192.168.83.133");
//获取IP地址
String hostAddress = byName.getHostAddress();
System.out.println("IP地址:"+hostAddress);
//获取主机名称
String hostName = byName.getHostName();
System.out.println("主机名:"+hostName);
}
}
UDP通信
UDP发送端
UDP: 面向无连接的,不安全的协议,每次传输64KB的数据
1.创建DatagramSocket对象(码头)
2.创建DatagramPacket对象(包裹) 需要制定ip地址和端口号
3.调用send方法,发送数据(把包裹交给码头)
4.调用close方法,释放资源(关闭码头)
举例
//发送端
public class Receiver {
public static void main(String[] args) throws IOException {
//创建DatagramSocket对象(找码头)
DatagramSocket ds = new DatagramSocket(9999);
//创建DatagramPacket对象(空包裹)
byte[] bytes = new byte[1024];
DatagramPacket dp = new DatagramPacket(bytes,bytes.length);
while (true) {
//接收数据(把接收到的数据装到包裹里)
ds.receive(dp);
//解析包裹(拆包)
byte[] data = dp.getData();
int length = dp.getLength();
//通过数组和长度转换为一个字符串
String s = new String(data,0,length);
//获取IP地址并打印结果
InetAddress address = dp.getAddress();
System.out.println(address+"....."+s);
}
//释放资源(交钱走人)
//ds.close();
}
}
//接收端
public class Sender {
public static void main(String[] args) throws IOException {
//创建DatagramSocket对象(码头)
DatagramSocket ds = new DatagramSocket();
//创建DategramPacket读写(包裹)
//需要发送的数据
//Scanner sc = new Scanner(System.in);
String[] arr = {
"你问我爱你有多深,我爱你有几分",
"我的情也真,我的爱也真",
"月亮代表我的心",
"你问我爱你有多深,我爱你有几分",
"我的情不移,我的爱不变",
"轻轻的一个吻,已经打动我的心",
"深深的一段情,教我思念到如今",
"你问我爱你有多深,我爱你有几分",
"你去想一想,你去看一看",
"月亮代表我的心",
"轻轻的一个吻,已经打动我的心",
"深深的一段情,教我思念到如今",
"你问我爱你有多深,我爱你有几分",
"你去想一想,你去看一看",
"月亮代表我的心",
"你去想一想,你去看一看",
"月亮代表我的心"};
//int a=0;
//while (a<arr.length){
//发送的信息
//System.out.println("请输入你要发的数据:");
byte[] bytes=null;
for (int i = 0; i < arr.length; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
bytes = arr[i].getBytes();
//byte[] bytes = sc.next().getBytes();
//IP地址
InetAddress ip = InetAddress.getByName("127.0.0.1");//主机本机的IP地址
//端口号
int port = 9999;
DatagramPacket dp = new DatagramPacket(bytes,bytes.length,ip,port);
//发送包裹
ds.send(dp);
}
//释放资源
//ds.close();
//a++;
//}
}
}
三种通信方式
单播: 一个发送端 发给 一个接收端
使用DatagramSocket进行发送和接收
组播: 一个发送端 发给 多个接收端(一组)
//创建MulticastSocket对象
MulticastSocket ms=new MulticastSocket(10000);
//把当前地址加入组: 组播地址:224.0.1.0
ms.joinGroup(InetAddress.getByName(“224.0.1.0”));
广播: 一个发送端 发给 所有接收端
//广播地址:255.255.255.255
使用DatagramSocket进行发送和接收
TCP通信
TCP: 面向有连接,安全的协议,传输数据的大小没有限制。
1.创建Socket对象指定服务端ip地址和端口号
2.调用socket.getOutputStream()方法请求服务端
3.释放资源close();`
//客户端
public class Client {
public static void main(String[] args) throws IOException {
//创建Socket对象(客户端对象),指定服务端的ip地址和端口号
Socket socket = new Socket("127.0.0.1",10086);
//先发送数据个服务端(请求)
OutputStream out = socket.getOutputStream();
String[] arr = getStrings();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out));
for (int i = 0; i < arr.length; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
bw.write(arr[i]);
bw.newLine();
bw.flush();
}
//给服务器一个结束标记,告诉服务器写完了
socket.shutdownOutput();
InputStream in = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String line;
while ((line=br.readLine())!=null){
System.out.println(line);
}
//释放资源
socket.close();
bw.close();
br.close();
// for (int i = 0; i < arr.length; i++) {
// try {
// Thread.sleep(1000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// byte[] bytes = arr[i].getBytes();
// out.write(bytes);
// }
//在接收服务端返回的数据(响应)
/* InputStream in = socket.getInputStream();
byte[] by = new byte[1024];
int len = in.read(by);
String s = new String(by,0,len);
System.out.println("服务端返回的数据:"+s);*/
}
private static String[] getStrings() {
String[] arr = {
"你问我爱你有多深,我爱你有几分",
"我的情也真,我的爱也真",
"月亮代表我的心",
"你问我爱你有多深,我爱你有几分",
"我的情不移,我的爱不变",
"轻轻的一个吻,已经打动我的心",
"深深的一段情,教我思念到如今",
"你问我爱你有多深,我爱你有几分",
"你去想一想,你去看一看",
"月亮代表我的心",
"轻轻的一个吻,已经打动我的心",
"深深的一段情,教我思念到如今",
"你问我爱你有多深,我爱你有几分",
"你去想一想,你去看一看",
"月亮代表我的心",
"你去想一想,你去看一看",
"月亮代表我的心"};
return arr;
}
}
//服务端
public class Server {
public static void main(String[] args) throws IOException {
//创建ServerSocket对象
ServerSocket server = new ServerSocket(10086);
//使用accept方法,监听客户端(那个客户端连接就获取那个客户端对象)
Socket socket = server.accept();//阻塞
//在通过Socket的getInputStream方法获取输入流,读取数据
InputStream in = socket.getInputStream();
// int a = 0;
// while ((a = in.read()) != -1) {
// byte[] bt = new byte[1024];
// int len = in.read(bt);
// String s = new String(bt, 0, len);
//
// System.out.println("服务器接收的数据:" + s);
// }
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String line;
while ((line=br.readLine())!=null){
System.out.println(line);
}
//给服务器一个结束标记,告诉服务器读完了
socket.shutdownInput();
//在通过Socket的getOutputStream方法获取输出流,写出数据
OutputStream out = socket.getOutputStream();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out));
bw.write("接收成功");
bw.newLine();
bw.flush();
//释放资源
socket.close();
server.close();
bw.close();
br.close();
}
}
图片上传多线程案例
//客户端
public class Client {
public static void main(String[] args) throws IOException {
//创建socket对象
Socket socket = new Socket("127.0.0.1",6666);
//本地流 用来读取本地文件
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("E:\\图片\\QQ图片20180829091757.jpg"));
//BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("E:\\图片\\超智能足球\\ca384066d01609243c2839d2d80735fae7cd342b.jpg")));
//网络流 写进服务器
//BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
BufferedOutputStream bot = new BufferedOutputStream(socket.getOutputStream());
int len;
while ((len = bis.read())!=-1){
bot.write(len);
}
//告诉服务端数据写完了
socket.shutdownOutput();
//获取服务端返回的数据
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String s = br.readLine();
System.out.println(s);
//释放资源
socket.close();
}
}
//线程启动
public class Server {
public static void main(String[] args) throws IOException {
//创建服务端ServerSocket对象,绑定端口号
ServerSocket socket = new ServerSocket(6666);
while (true) {
//监听客户端
Socket accept = socket.accept();
new Thread(new ServerRunnable(accept)).start();
}
//socket.close();
}
}
//服务端
public class ServerRunnable implements Runnable{
private Socket accept;
public ServerRunnable(Socket accept) {
this.accept = accept;
}
@Override
public void run() {
try {
//从客户端读取数据 网络中的流
BufferedInputStream bis = new BufferedInputStream(accept.getInputStream());
//BufferedReader br = new BufferedReader(new InputStreamReader(accept.getInputStream()));
//把网络中的流写入本地 本地流
String s = UUID.randomUUID().toString();
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("C:\\Users\\ZhangXM\\Desktop\\File\\"+s+".jpg"));
//BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("C:\\Users\\ZhangXM\\Desktop\\File\\"+s+".jpg")));
int len;
while((len = bis.read())!=-1){
bos.write(len);
}
bos.close();
//往客户端返回提示信息
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(accept.getOutputStream()));
bw.write("上传成功");
bw.newLine();
bw.flush();
bw.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
accept.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}