1、概述
指的就是IO技术和网络技术的综合。
网络参考模型:OSI、TCP\IP参考模型
网络通讯要素:IP地址、端口号(用于标识进程的逻辑地址,不同进程的标识)、传输协议(通讯的规则)。
package net.ip;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class IPdemo {
public static void main(String[] args) throws UnknownHostException {
//ip地址对象 InetAddress
//获取本地主机地址对象
//没有构造方法,不能new对象
//InetAddress ip = InetAddress.getLocalHost();
//获取其他主机地址对象
InetAddress ip = InetAddress.getByName("www.baidu.com");
System.out.println(ip.getHostAddress()+":"+ip.getHostName());
}
}
2、域名解析
3、端口
端口:物理端口
软件应用程序的数字表示:逻辑端口
4、传输协议TCP&UDP
传输控制协议、数据报文包协议
UDP(寄快递)、对讲机:
1、面向无连接
2、不管对方在不在
3、包只能放64k的数据
4、速度快,不可靠
TCP(保证对方在)、打电话:
1、面向有连接
2、三次握手
3、可靠,但是速度慢
5、网络编程Socket
socket:插座 IP+端口。
编写网络程序,先要有插座。针对不同的协议,有不同的插座。
in和out走的是管道。
6、UDP-发送端与接收端
通过查阅文档,了解到用于UDP传输协议的对象是DatagramSocket
通过UDP协议发送一段文本数据
1、先建立udp的socket,具备发送或者接收功能。
2、将数据封装到数据包中,数据包对象是DatagramPacket
3、使用socket对象的send方法,将数据包发送出去
4、关闭资源
package UDP;
import java.io.IOException;
import java.net.*;
public class UDP_send {
public static void main(String[] args) throws IOException {
System.out.println("udp发送端运行");
//1、先建立udp的socket,具备发送或者接收功能。
DatagramSocket ds = new DatagramSocket();
//2、将数据封装到数据包中,数据包对象是DatagramPacket
String text = "hello";
byte[] buf = text.getBytes();
DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("10.69.36.52"),10000);
//3、使用socket对象的send方法,将数据包发送出去
ds.send(dp);
//4、关闭资源
ds.close();
}
}
接收端:
1、现有udp 插座socket服务,接收端一定要明确端口,否则接收不到数据。
2、接收数据。之前,先将数据存储到数据包对象中,数据包对象才可以解析。
3、先定义数据包
4、通过数据包对象获取数据包中的各项内容。发送端IP、端口、数据等
5、关闭资源
package UDP;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class UDP_receive {
public static void main(String[] args) throws IOException {
System.out.println("udp-receive");
DatagramSocket ds = new DatagramSocket(10000); //如果不输入端口,则是随机分配端口
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf, buf.length);
ds.receive(dp); //此方法在接收到数据包前一致阻塞
String ip = dp.getAddress().getHostAddress();
int port = dp.getPort();
String text = new String(dp.getData(), 0, dp.getLength());
System.out.println(text);
ds.close();
}
}
键盘录入:
package UDP;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.*;
public class upd_send2 {
public static void main(String[] args) throws IOException {
System.out.println("发送端启动");
DatagramSocket ds = new DatagramSocket();
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
String line = null;
while ((line = bf.readLine()) != null) {
if("over".equals(line)){
break;
}
byte[] buf =line.getBytes();
DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("10.69.36.52"),10000);
ds.send(dp);
}
ds.close();
}
}
package UDP;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class udp_receive2 {
public static void main(String[] args) throws IOException {
System.out.println("接收端启动");
DatagramSocket ds = new DatagramSocket(10000);
while (true) {
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf, buf.length);
ds.receive(dp); //此方法在接收到数据包前一致阻塞
String ip = dp.getAddress().getHostAddress();
int port = dp.getPort();
String text = new String(dp.getData(), 0, dp.getLength());
System.out.println("ip= "+ip+" port = "+port+text);
}
//ds.close();
}
}
在一个程序里面实现既能收,又能发。
package UDP;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
public class chatDemo {
public static void main(String[] args) throws SocketException {
//发送端的socket 接收端的socket
DatagramSocket sendSocket = new DatagramSocket();
DatagramSocket receiveSocket = new DatagramSocket(10002);
send send = new send(sendSocket);
receive receive = new receive(receiveSocket);
//创建线程并开启
Thread t1 = new Thread(send);
Thread t2 = new Thread(receive);
t1.start();
t2.start();
}
}
//发送任务
class send implements Runnable{
private DatagramSocket ds;
public send(DatagramSocket ds){
super();
this.ds = ds;
}
@Override
public void run(){
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
String line = null;
try {
while ((line = bf.readLine()) != null) {
byte[] buf =line.getBytes();
DatagramPacket dp = new DatagramPacket(buf,buf.length, InetAddress.getByName("10.69.36.52"),10002);
ds.send(dp);
if ("over".equals(line)) {
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
ds.close();
}
}
//接收任务
class receive implements Runnable{
private DatagramSocket ds;
public receive(DatagramSocket ds){
super();
this.ds = ds;
}
@Override
public void run() {
while (true) {
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf, buf.length);
try {
ds.receive(dp); //此方法在接收到数据包前一致阻塞
} catch (IOException e) {
e.printStackTrace();
}
String ip = dp.getAddress().getHostAddress();
int port = dp.getPort();
String text = new String(dp.getData(), 0, dp.getLength());
System.out.println("ip= "+ip+" port = "+port+text);
if(text.equals("over")){
System.out.println(ip+"....离开聊天室");
}
}
}
}
使用广播的方法:
发送的IP地址改为广播地址即可
7、TCP
TCP也分两端,一个叫客户端,一个叫服务端。
TCP客户端用的就是Socket对象。服务端用的是ServerSocket对象。
客户端运行:
package TCP;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
public class TCP_client {
public static void main(String[] args) throws IOException {
//需求:通过Tcp传输,将数据发送给服务器
Socket socket = new Socket(InetAddress.getByName("DESKTOP-IG0R9HM").getHostAddress(),10003);//如果无参,则创建的是未连接的socket,所以要明确服务器端的地址和端口
byte[] buf = new byte[1024];
OutputStream os = socket.getOutputStream();
os.write("你好,tcp".getBytes());
socket.close();
}
}
服务器端:
package TCP;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class TCP_Server {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(10003);
Socket s = ss.accept();
InputStream is = s.getInputStream();
byte[] buf = new byte[1024];
int len = is.read(buf);
String text = new String(buf,0,len);
System.out.println(text);
System.out.println("客户端地址是:"+s.getInetAddress().getHostAddress());
s.close();
ss.close();
}
}
tcp在传输过程中,两端都有可能处于等待状态。
并发访问的时候,出的问题。
第一个客户端如果连接,没有发数据,或者发完没有结束,那么accept方法会处于阻塞状态。
package TCP;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class TCP_server2 {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(10004);
Socket s = ss.accept();
InputStream ip = s.getInputStream();
byte[] buf = new byte[1024];
int len = ip.read(buf);
String reveive = new String(buf, 0, len);
System.out.println(reveive);
OutputStream op = s.getOutputStream();
op.write("这里是服务器端".getBytes());
System.out.println(s.getInetAddress().getHostAddress()+"已连接");
s.close();
// ss.close(); 如果不断获取客户端,则不用关服务器
}
}
package TCP;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
public class TCP_client2 {
public static void main(String[] args) throws IOException {
Socket s = new Socket(InetAddress.getByName("DESKTOP-IG0R9HM").getHostAddress(), 10004);
OutputStream op = s.getOutputStream();
op.write("这里是客户端".getBytes());
InputStream is = s.getInputStream();
byte[] buf = new byte[1024];
int len = is.read(buf);
String reveive = new String(buf,0,len);
System.out.println(reveive);
s.close();
}
}
8、频繁的客户端和服务端的通信
需求:客户端通过键盘录入发送数据到服务端,服务端将接受的数据显示到屏幕上的同时,将这些数据转成大写发回给客户端。当客户端录入的是over时,结束。
客户端:
1、创建Socket,明确地址和端口。
2、源:键盘录入,获取需要转换的数据 。
3、目的:socket输出流。
4、源:socket 读取流,读取客户端发回来的大写数据
5、目的:客户端显示器,将大写数据显示出来。
6、频繁的读写操作
7、关闭资源
package TCP;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
public class client_uplow {
public static void main(String[] args) throws IOException {
System.out.println("客户端运行");
//1、创建Socket,明确地址和端口。
Socket s = new Socket(InetAddress.getByName("DESKTOP-IG0R9HM").getHostAddress(),10004);
//2、源:键盘录入,获取需要转换的数据 。
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
//3、目的:socket输出流。
OutputStream op = s.getOutputStream();
//都是字符数据,为了便于操作,使用额外功能,转换,同时提高效率。
//BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(op));
//也可以使用打印流
PrintWriter pw = new PrintWriter(s.getOutputStream());
//4、源:socket 读取流,读取客户端发回来的大写数据
//InputStream is = s.getInputStream();
BufferedReader bufr = new BufferedReader(new InputStreamReader(s.getInputStream()));
//5、目的:客户端显示器,将大写数据显示出来。
String receiver = null;
while ((receiver = bf.readLine())!= null){
//将读取键盘的数据发送到服务端
pw.println(receiver);
pw.flush();
//读取服务端返回的数据
String up = bufr.readLine();
System.out.println(up);
if("over".equals(receiver)){
break;
}
}
//7、关闭资源
s.close();
}
}
服务端:
1、创建服务端socket,监听一个端口。
2、源:socket输入流,读取客户端数据。
3、将数据转换成大写
4、目的:socket输出流,发送给客户端数据。
5、频繁的读写操作
6、关闭资源
package TCP;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class Server_uplow {
public static void main(String[] args) throws IOException {
System.out.println("服务端运行");
// 1、创建服务端socket,监听一个端口。
ServerSocket ss = new ServerSocket(10004);
while (true){
Socket s = ss.accept();
System.out.println(s.getInetAddress().getHostAddress()+"...已连接");
// 2、源:socket输入流,读取客户端数据。
BufferedReader brIn = new BufferedReader(new InputStreamReader(s.getInputStream()));
//3、将数据转换成大写
PrintWriter out = new PrintWriter(s.getOutputStream());
// 4、目的:socket输出流,发送给客户端数据。
String line = null;
while ((line = brIn.readLine())!= null){
if("over".equals(line)){
break;
}
System.out.println(line);
//将读取到的字母数据转成大写
out.println(line.toUpperCase());
out.flush();
}
// 5、频繁的读写操作
// 6、关闭资源
s.close();
}
}
}
9、上传文本文件
客户端
package TCP;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
public class upload_client {
public static void main(String[] args) throws IOException {
System.out.println("客户端运行");
Socket s = new Socket(InetAddress.getByName("DESKTOP-IG0R9HM"), 10008);
//读取文本文件
BufferedReader bf_read = new BufferedReader(new FileReader("F:\\javatest\\list.txt"));
PrintWriter out = new PrintWriter(s.getOutputStream());
BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));
String line = null;
while ((line = bf_read.readLine())!= null){
out.println(line);
out.flush();
String re = bufIn.readLine();
System.out.println(re);
}
out.println("over");
System.out.println("发送over成功");
s.close();
}
}
服务器端
package TCP;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class upload_server {
public static void main(String[] args) throws IOException {
System.out.println("服务端启动");
ServerSocket ss = new ServerSocket(10008);
Socket s = ss.accept();
//获得服务器端的读取流
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
//获取服务器端的输出流
PrintWriter pw = new PrintWriter(s.getOutputStream());
BufferedWriter bw = new BufferedWriter(new FileWriter("F:\\javatest\\tempfile\\receive.txt"));
String line = null;
while ((line = br.readLine())!= null){
if("over".equals(line)){
break;
}
System.out.println(line);
pw.println(line);
bw.write(line);
bw.newLine();
pw.flush();
bw.flush();
}
bw.close();
s.close();
ss.close();
}
}
这里说一下碰到的问题
在服务器端的程序里面。在频繁读取的过程中,只考虑到了pw.println,但是没有考虑到,pw获取的是socket的输出流,并不是文件的输出流,写入的过程还需要bw来进行写入。所以碰到的问题就是,客户端已经发送完毕,服务器端也接收到了,但是就是没有写入到文件中。
字符流能不能复制媒体文件?
不能,每次读取字节都需要查表,有的查表查不到,编码表会将查不到的就用未知的字符(固定的)替代。所以传输过去就会出现问题。所以复制图片,部分是有问题的。
10、上传图片-客户端
服务器端:
package TCP;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class pic_upload_Server {
public static void main(String[] args) throws IOException {
System.out.println("服务端运行");
ServerSocket ss = new ServerSocket(10007);
//获取客户端
while (true) {
Socket s = ss.accept();
System.out.println(s.getInetAddress().getHostAddress() + "...已连接");
//读取图片数据
InputStream isIn = s.getInputStream();
//写数据
FileOutputStream fos = new FileOutputStream("F:\\javatest\\2.jpg");
byte[] buf = new byte[1024];
int len = 0;
while ((len = isIn.read(buf)) != -1) {
fos.write(buf, 0, len);
}
//给客户端一个回复信息
OutputStream os = s.getOutputStream();
os.write("上传成功".getBytes());
fos.close();
s.close();
}
}
}
客户端:
package TCP;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
public class pic_upload_client {
public static void main(String[] args) throws IOException {
System.out.println("客户端运行");
//1、创建socket
Socket s = new Socket(InetAddress.getByName("DESKTOP-IG0R9HM"), 10007);
//2、读取源图片
FileInputStream fis = new FileInputStream("F:\\javatest\\1.jpg");
//3、目的
OutputStream os = s.getOutputStream();
//4、读写操作
byte[] buf = new byte[1024];
int len = 0;
while ((len = fis.read(buf)) != -1) {
os.write(buf,0,len);
}
//告诉服务器端图片数据发送完毕
s.shutdownOutput();
//读取上传成功字样
InputStream in = s.getInputStream();
byte[] bufin = new byte[1024];
int lenin = in.read(bufin);
System.out.println(new String(bufin,0,lenin));
fis.close();
s.close();
}
}
注意一个函数
s.shutdownOutput();
注意一个问题:如果服务器没有关,再上传一次,那么就会出现图片的重名的问题。
有一个编号很常见,那就是你上传的时间,这个基本不会产生冲突。
或者命名为用户的IP。
package TCP;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class pic_upload_Server {
public static void main(String[] args) throws IOException {
System.out.println("服务端运行");
ServerSocket ss = new ServerSocket(10007);
//获取客户端
while (true) {
Socket s = ss.accept();
String ip = s.getInetAddress().getHostAddress();
System.out.println(ip + "...已连接");
//读取图片数据
InputStream isIn = s.getInputStream();
//写数据
File dir = new File("F:\\javatest\\mypic");
if (!dir.exists()) {
dir.mkdir();
}
File pic = new File(dir, ip + ".jpg");
FileOutputStream fos = new FileOutputStream(pic);
byte[] buf = new byte[1024];
int len = 0;
while ((len = isIn.read(buf)) != -1) {
fos.write(buf, 0, len);
}
//给客户端一个回复信息
OutputStream os = s.getOutputStream();
os.write("上传成功".getBytes());
fos.close();
s.close();
}
}
}
或者使用下面的方式:
package TCP;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class pic_upload_Server {
public static void main(String[] args) throws IOException {
System.out.println("服务端运行");
ServerSocket ss = new ServerSocket(10007);
//获取客户端
while (true) {
Socket s = ss.accept();
String ip = s.getInetAddress().getHostAddress();
System.out.println(ip + "...已连接");
//读取图片数据
InputStream isIn = s.getInputStream();
//写数据
File dir = new File("F:\\javatest\\mypic");
if (!dir.exists()) {
dir.mkdir();
}
//为了避免覆盖,通过给重名的文件进行编号。
int count = 1;
File pic = new File(dir, ip + "(" + count + ")" + ".jpg");
if (pic.exists()) {
count++;
pic = new File(dir,ip + "(" + count + ")" + ".jpg");
}
FileOutputStream fos = new FileOutputStream(pic);
byte[] buf = new byte[1024];
int len = 0;
while ((len = isIn.read(buf)) != -1) {
fos.write(buf, 0, len);
}
//给客户端一个回复信息
OutputStream os = s.getOutputStream();
os.write("上传成功".getBytes());
fos.close();
s.close();
}
}
}
有一个问题就是:
客户端多次上传,但是后面的并没有存储。问题出在if上,只是判断了一次。所以应该改成while,只要存在就++。
package TCP;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class pic_upload_Server {
public static void main(String[] args) throws IOException {
System.out.println("服务端运行");
ServerSocket ss = new ServerSocket(10007);
//获取客户端
while (true) {
Socket s = ss.accept();
String ip = s.getInetAddress().getHostAddress();
System.out.println(ip + "...已连接");
//读取图片数据
InputStream isIn = s.getInputStream();
//写数据
File dir = new File("F:\\javatest\\mypic");
if (!dir.exists()) {
dir.mkdir();
}
//为了避免覆盖,通过给重名的文件进行编号。
int count = 1;
File pic = new File(dir, ip + "(" + count + ")" + ".jpg");
while (pic.exists()) {
count++;
pic = new File(dir,ip + "(" + count + ")" + ".jpg");
}
FileOutputStream fos = new FileOutputStream(pic);
byte[] buf = new byte[1024];
int len = 0;
while ((len = isIn.read(buf)) != -1) {
fos.write(buf, 0, len);
}
//给客户端一个回复信息
OutputStream os = s.getOutputStream();
os.write("上传成功".getBytes());
fos.close();
s.close();
}
}
}
还有一个问题:并发上传的问题。
通过多线程来解决
每个客户端都需要单独一个线程来处理
package TCP;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class pic_upload_Server {
public static void main(String[] args) throws IOException {
System.out.println("服务端运行");
ServerSocket ss = new ServerSocket(10007);
//获取客户端
while (true) {
Socket s = ss.accept();
//要想实现多个客户端并发上传,服务器端必须启动多个线程来完成。
new Thread(new uploadpic(s)).start(); //新线程,线程里面得有任务,任务里面得有客户端。
//new Thread(new 类的对象).start 对应的类里面应该有重写run方法。
}
}
}
package TCP;
import java.io.*;
import java.net.Socket;
public class uploadpic implements Runnable {
private Socket s;
public uploadpic(Socket s) {
this.s = s;
}
public void run(){
try{
String ip = s.getInetAddress().getHostAddress();
System.out.println(ip + "...已连接");
//读取图片数据
InputStream isIn = s.getInputStream();
//写数据
File dir = new File("F:\\javatest\\mypic");
if (!dir.exists()) {
dir.mkdir();
}
//为了避免覆盖,通过给重名的文件进行编号。
int count = 1;
File pic = new File(dir, ip + "(" + count + ")" + ".jpg");
while (pic.exists()) {
count++;
pic = new File(dir,ip + "(" + count + ")" + ".jpg");
}
FileOutputStream fos = new FileOutputStream(pic);
byte[] buf = new byte[1024];
int len = 0;
while ((len = isIn.read(buf)) != -1) {
fos.write(buf, 0, len);
}
//给客户端一个回复信息
OutputStream os = s.getOutputStream();
os.write("上传成功".getBytes());
fos.close();
s.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
11、常见的客户端和服务端原理(浏览器、tomcat)
客户端:
浏览器、QQ等。
服务端:
Tomcat服务器:对外提供web资源的服务。默认端口为8080.
服务器:对外提供服务的机器。
底层所使用的网络传输通讯机制。
访问方式:浏览器中:输入http://主机地址:8080/自己的应用程序名称/具体的资源名称;
12、浏览器发送的HTTP请求消息
了解浏览器都做了什么事情?
客户端:浏览器
服务端:自定义的服务端myServer
package HTTP;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class myServer {
public static void main(String[] args) throws IOException {
//自定义server服务端,获取浏览器的信息。并反馈信息。
System.out.println("服务端启动");
ServerSocket ss = new ServerSocket(9090);
Socket s = ss.accept();
System.out.println(s.getInetAddress().getHostAddress()+"...已连接。");
InputStream is = s.getInputStream();
byte[] buf = new byte[1024];
int len = is.read(buf);
String text = new String(buf, 0, len);
System.out.println(text);
//回馈数据
PrintWriter pw = new PrintWriter(s.getOutputStream(), true);
pw.println("<font color = 'red' size = 7>欢迎访问</font>");
s.close();
ss.close();
}
}
在浏览器界面输入本地地址:9090,就可以看到服务器返回的欢迎访问消息。并且服务器端会收到来自浏览器的http请求消息。
GET / HTTP/1.1 //请求行 访问资源的路径 HTTP协议版本
//属性信息,通过键值对来表示
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/17.17134
Accept-Language: zh-CN
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Upgrade-Insecure-Requests: 1
Accept-Encoding: gzip, deflate
Host: 10.69.36.52:9090
Connection: Keep-Alive
空行
请求体
HTTP的请求消息:请求头+请求体,中间有空行(专门区分头和体的)。
13、模拟浏览器&HTTP的应答消息
package HTTP;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.Socket;
public class browser {
public static void main(String[] args) throws IOException {
//模拟一个浏览器,发送之前IE发送的HTTP消息
Socket s = new Socket("10.69.36.52",9090);
//把IE的信息发送给服务端
PrintWriter out = new PrintWriter(s.getOutputStream(),true);
out.println("GET / HTTP/1.1");
out.println("User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/17.17134");
out.println("Accept-Language: zh-CN");
out.println("Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
out.println("Upgrade-Insecure-Requests: 1");
out.println("Accept-Encoding: gzip, deflate");
out.println("Host: 10.69.36.52:9090");
out.println("Connection: clsoe");
out.println(); //空行
//读取服务端的数据
InputStream is = s.getInputStream();
byte[] buf = new byte[1024];
int len = is.read(buf);
String text = new String(buf, 0, len);
System.out.println(text);
s.close();
}
}
服务器如果是tomcat。则会收到tomcat服务器返回的数据
服务器端HTTP应答消息:
HTTP/1/1 200 OK //应答行 http协议版本 应答状态码
Server:Apache-Coyote/1.1
Accept-Ranges:bytes
Etag:W/"67-1374891778953"
Last-Modified:Sat,27 Jul 2013 02:22:34 GMT
Content-Type:text/html //内容类型
Content-Length:467 //内容长度
Data:Sun,01..
Connection:close
空行
应答体
14、URL对象
类 URL
代表一个统一资源定位符。
package URL;
import java.net.MalformedURLException;
import java.net.URL;
public class urlDemo {
public static void main(String[] args) throws MalformedURLException {
String str_url = "http://10.69.36.52:9090/?name=liudong&age=25";
//将URL地址封装成对象
URL url = new URL(str_url);
System.out.println("协议:" + url.getProtocol());
System.out.println("主机:" + url.getHost());
System.out.println("端口:"+url.getPort());
System.out.println("路径:"+url.getPath());
System.out.println("文件:"+url.getFile());
System.out.println("getQuery:"+url.getQuery());
}
}
URL有一个特殊的方法,openConnection();获取url的连接
该方法返回一个URLconnection对象,它表示到URL所引用的远程对象的连接。
都不用使用Socket对象了,因为已经封装。
package URL;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
public class urlDemo {
public static void main(String[] args) throws IOException {
String str_url = "http://10.69.36.52:9090";
//将URL地址封装成对象
URL url = new URL(str_url);
/* System.out.println("协议:" + url.getProtocol());
System.out.println("主机:" + url.getHost());
System.out.println("端口:"+url.getPort());
System.out.println("路径:"+url.getPath());
System.out.println("文件:"+url.getFile());
System.out.println("getQuery:"+url.getQuery());*/
//获取指定资源的连接对象 //封装了Socket
URLConnection conn = url.openConnection();
// System.out.println(conn);
InputStream is = conn.getInputStream();
byte[] buf = new byte[1024];
int len = is.read(buf);
String text = new String(buf, 0, len);
System.out.println(text);
}
}
15、HTTP1.0和HTTP1.1的区别
当我们访问有图片的网站时,它不止有一次请求。随后还会有对图片的请求。
http1.1就是传说中的keep-alive。
16、CS和BS
常见的网络架构:
C/S:client/server
特点:
1、程序员需要开发客户端和服务端
2、维护较为麻烦
3、将一部分运算转移到客户端来完成,减轻服务器端的压力
B/S:browser/server
特点:
1、程序员只需要开发服务端,客户端使用系统已有的浏览器即可
2、维护很简单,只需要维护服务端
3、所有的运算都在服务端
4、带宽问题和安全问题
目前流行B/S网络架构。