为了同志们的革命事业,同志们幸苦了。霍霍。
get
get请求http的实现
//建立socket
Socket socket = new Socket("127.0.0.1", Integer.parseInt("9965"));
//输出流
OutputStream outputStream = socket.getOutputStream();
StringBuffer sb = new StringBuffer();
//建立请求头
{
//请求方式、接口、数据、协议
sb.append("GET /er?id=123456 HTTP/1.1\r\n");
//HTTP/1.1 的必须头
sb.append("Host:localhost\r\n");
//换行
sb.append("\r\n");
}
//传数据
outputStream.write(sb.toString().getBytes());
outputStream.flush();
InputStream inputStream = socket.getInputStream();
int a2;
byte[] bytes2 = new byte[1024];
while ((a2 = inputStream.read(bytes2)) != -1) {
System.out.println("--------------------------");
System.out.println(new String(bytes2));
}
效果图片
post
post传输json
效果图片
post传输文件
传输文件使用到了multipart的协议,把文件 分成一段一段的进行 传输。
1准备工作 准备一个 txt文件 里面有 10个 a
2写一个接受文件的接口 返回文件名
String boundary = System.currentTimeMillis() + "";
Socket socket = new Socket("127.0.0.1", Integer.parseInt("9965"));
OutputStream chunkedOutputStream = null;
chunkedOutputStream = socket.getOutputStream();
StringBuffer sb = new StringBuffer();
sb.append("POST /xxxxxxxee HTTP/1.1\r\n");// 注意\r\n为回车换行
sb.append("Transfer-Encoding: chunked\r\n");
sb.append("Content-Type: multipart/form-data; boundary=" + boundary + "\r\n");
sb.append("Host: 127.0.0.1:9965\r\n");
sb.append("Connection: Keep-Alive\r\n");
sb.append("User-Agent: Apache-HttpClient/4.5.12 (Java/1.8.0_311)\r\n");
sb.append("Accept-Encoding: gzip,deflate\r\n");
sb.append("\r\n");
System.out.print(sb);
chunkedOutputStream.write(sb.toString().getBytes());
//System.out.print(sb.length());
StringBuilder stringBuilder = new StringBuilder();
//拼装文件头
{
//文件的 boundary 固定的
stringBuilder.append("--").append(boundary).append("\r\n");
//文件的名称信息
stringBuilder.append("Content-Disposition: form-data; name=\"file\"; filename=\"xxx.txt\"\r\n");
//文件流的编码信息 这个里是win的文件 所以是ISO-8859-1
stringBuilder.append("Content-Type: multipart/form-data; charset=ISO-8859-1\r\n");
stringBuilder.append("Content-Transfer-Encoding: binary\r\n");
stringBuilder.append("\r\n");
}
String s = "D:\\aaaaaaahujian\\qianzhang\\aaaa.txt";
File file = new File(s);
FileInputStream fileInputStream = new FileInputStream(file);
byte[] bytes = new byte[8];
int l;
byte[] bytes1 = new byte[8192];
int a = 0;
boolean isDiYi = true;
while ((l = fileInputStream.read(bytes)) != -1) {
if (isDiYi) {
String s1 = Integer.toHexString(stringBuilder.length() + l) + "\r\n";
System.arraycopy(s1.getBytes(), 0, bytes1, a, s1.getBytes().length);
a = a + s1.getBytes().length;
System.arraycopy(stringBuilder.toString().getBytes(), 0, bytes1, a, stringBuilder.toString().getBytes().length);
a = a + stringBuilder.toString().getBytes().length;
System.arraycopy(bytes, 0, bytes1, a, l);
a = a + l;
System.arraycopy("\r\n".getBytes(), 0, bytes1, a, "\r\n".getBytes().length);
a = a + "\r\n".getBytes().length;
isDiYi = false;
} else {
String s1 = Integer.toHexString(l) + "\r\n";
System.arraycopy(s1.getBytes(), 0, bytes1, a, s1.getBytes().length);
a = a + s1.getBytes().length;
chunkedOutputStream.write(bytes1, 0, a);
System.out.print(new String(bytes1, 0, a));
//System.out.println("=================");
chunkedOutputStream.flush();
bytes1 = new byte[8192];
// System.out.println(a);
// System.out.println(a + sb.length());
a = 0;
System.arraycopy(bytes, 0, bytes1, a, l);
a = a + l;
System.arraycopy("\r\n".getBytes(), 0, bytes1, a, "\r\n".getBytes().length);
a = a + "\r\n".getBytes().length;
}
}
System.out.print(new String(bytes1, 0, a));
chunkedOutputStream.write(bytes1, 0, a);
//发送文件的 结尾标识 boundary 是全局统一的
String s2 = Integer.toHexString(("\r\n--" + boundary + "--\r\n").length()) + "\r\n";
System.out.print(s2);
chunkedOutputStream.write(s2.getBytes());
//System.out.println("=================");
chunkedOutputStream.flush();
// System.out.println(a);
bytes1 = new byte[8192];
a = 0;
//http报文结束
System.arraycopy("\r\n".getBytes(), 0, bytes1, a, "\r\n".getBytes().length);
a = a + "\r\n".getBytes().length;
System.arraycopy(("--" + boundary + "--").getBytes(), 0, bytes1, a, ("--" + boundary + "--").getBytes().length);
a = a + ("--" + boundary + "--").getBytes().length;
System.arraycopy("\r\n".getBytes(), 0, bytes1, a, "\r\n".getBytes().length);
a = a + "\r\n".getBytes().length;
System.out.println(new String(bytes1, 0, a));
chunkedOutputStream.write(bytes1, 0, a);
chunkedOutputStream.flush();
System.out.println("上面就是上传文件的所打印的输出流============================================================");
InputStream inputStream = socket.getInputStream();
// 封装输入流is,并指定字符集
// 存放数据
StringBuffer sbf = new StringBuffer();
byte[] bytes2 = new byte[1024];
int a2;
while ((a2 = inputStream.read(bytes2)) != -1) {
System.out.println("--------------------------");
System.out.println(new String(bytes2));
sbf.append(new String(bytes2));
}
效果图
要是没有看懂 可以看看下面的这个 文件的 字符版本。
String s = "POST /xxxxxxxee HTTP/1.1\r\n" +
"Transfer-Encoding: chunked\r\n" +
"Content-Type: multipart/form-data; boundary=1681211230609\r\n" +
"Host: 127.0.0.1:9965\r\n" +
"Connection: Keep-Alive\n" +
"User-Agent: Apache-HttpClient/4.5.12 (Java/1.8.0_311)\r\n" +
"Accept-Encoding: gzip,deflate\r\n" +
"\r\n" +
"b6\r\n" +
"--1681211230609\r\n" +
"Content-Disposition: form-data; name=\"file\"; filename=\"xxx.txt\"\r\n" +
"Content-Type: multipart/form-data; charset=ISO-8859-1\r\n" +
"Content-Transfer-Encoding: binary\r\n" +
"\r\n" +
"aaaaaaaa\r\n" +
"2\r\n" +
"aa\r\n" +
"15\r\n" +
"\r\n" +
"--1681211230609--\r\n";
Socket socket = new Socket("127.0.0.1", Integer.parseInt("9965"));
OutputStream chunkedOutputStream = null;
chunkedOutputStream = socket.getOutputStream();
chunkedOutputStream.write(s.getBytes());
chunkedOutputStream.flush();
InputStream inputStream = socket.getInputStream();
int a2;
byte[] bytes2 = new byte[1024];
System.out.println("打印返回值");
while ((a2 = inputStream.read(bytes2)) != -1) {
System.out.println("--------------------------");
System.out.println(new String(bytes2));
}
文件的传输分析
读取8
读取1024
//get//post
CloseableHttpResponse execute = HttpClients.createDefault().execute(httpRequset);
new HttpClientBuilder();
build()
return new InternalHttpClient(
execChain, RedirectExec 请求执行链中负责的请求执行程序
connManagerCopy, PoolingHttpClientConnectionManager 从池中创建一个连接,而不是创建一个全新的连接
routePlannerCopy, DefaultRoutePlanner 任何Java系统属性,也没有系统或浏览器代理设置。
cookieSpecRegistryCopy, 对请求上下文做处理的 得工厂集合 Cookie规范提供商
authSchemeRegistryCopy, 认证方案提供者
defaultCookieStore, 这个接口表示{@link Cookie}的抽象存储对象。
defaultCredentialsProvider,
defaultRequestConfig != null ? defaultRequestConfig : RequestConfig.DEFAULT, 请求配置文件
closeablesCopy);
return execute(request, (HttpContext) null);
return doExecute(determineTarget(request), request, context);
//包装请求
final HttpRequestWrapper wrapper = HttpRequestWrapper.wrap(request, target);
//包装请求上下文
final HttpClientContext localcontext = HttpClientContext.adapt( context != null ? context : new BasicHttpContext());
//处理配置
config = ((Configurable) request).getConfig();
//如果配置是空 则根据参数生成配置
final HttpParams params = request.getParams();
//的属性名。 *对象,表示实际的目标身份验证状态。
// 翻译 *一个属性的名称{@link org.apache.http.config. config. config. html对象,表示 *实际的{@link AuthSchemeProvider}注册表。
//*一个属性的名称{@link org.apache.http.config. config. config. html对象,表示 实际的{@link CookieSpecProvider}注册表。
//*属性名{@link org.apache.http.client.CookieStore} *对象,表示实际的cookie存储。
//*一个提供者的属性名 对象,表示实际的凭证提供程序。
setupContext(localcontext);
return this.execChain.execute(route, wrapper, localcontext, execAware); RedirectExec
//发送数据
final CloseableHttpResponse response = requestExecutor.execute( currentRoute, currentRequest, context, execAware); RetryExec
return this.requestExecutor.execute(route, request, context, execAware); ProtocolExec
//取除开ip得url
rewriteRequestURI(request, route, context.getRequestConfig().isNormalizeUri());
//设置请求数据
context.setAttribute(HttpCoreContext.HTTP_TARGET_HOST, target);
context.setAttribute(HttpClientContext.HTTP_ROUTE, route);
context.setAttribute(HttpCoreContext.HTTP_REQUEST, request);
//执行请求得拦截器 添加请求头啊 处理请求数据啊等的 比如上传文件 要更改传输类型时
this.httpProcessor.process(request, context);
//从请求数据中设置请求头
request.addHeader(entity.getContentType())
response = requestExecutor.execute(request, managedConn, context); MainClientExec
//创建请求得链接池
final ConnectionRequest connRequest = connManager.requestConnection(route, userToken); PoolingHttpClientConnectionManager
return new Future<E>
//创建链接 的包装类
managedConn = connRequest.get(timeout > 0 ? timeout : 0, TimeUnit.MILLISECONDS);
managedConn = connRequest.get(timeout > 0 ? timeout : 0, TimeUnit.MILLISECONDS);
final HttpClientConnection conn = leaseConnection(future, timeout, timeUnit);
entry = future.get(timeout, timeUnit);
//route IP port
final E leasedEntry = getPoolEntryBlocking(route, state, timeout, timeUnit, this);
final C conn = this.connFactory.create(route); PoolingHttpClientConnectionManager.InternalConnectionFactory
return this.connFactory.create(route, config); ManagedHttpClientConnectionFactory
//返回链接的包装
return new LoggingManagedHttpClientConnection(
id,
log,
headerLog,
wireLog,
cconfig.getBufferSize(),
cconfig.getFragmentSizeHint(),
charDecoder,
charEncoder,
cconfig.getMessageConstraints(),
incomingContentStrategy,
outgoingContentStrategy,
requestWriterFactory,
responseParserFactory);
//设置socket
establishRoute(proxyAuthState, managedConn, route, request, context);
this.connManager.connect( managedConn, route, timeout > 0 ? timeout : 0, context);
this.connectionOperator.connect( conn, host, route.getLocalSocketAddress(), connectTimeout, resolveSocketConfig(host), context);
//创建 Socket对象
Socket sock = sf.createSocket(context); PlainConnectionSocketFactory
return new Socket();
//绑定到链接
conn.bind(sock); DefaultManagedHttpClientConnection
super.bind(socket); DefaultBHttpClientConnection
super.bind(socket);BHttpConnectionBase
this.socketHolder.set(socket);
//设置ip 端口 链接服务 tcp
sock = sf.connectSocket( connectTimeout, sock, host, remoteAddress, localAddress, context);
sock.connect(remoteAddress, connectTimeout);
//设置属性 http
context.setAttribute(HttpCoreContext.HTTP_CONNECTION, managedConn);
//设置链接处理器
final ConnectionHolder connHolder = new ConnectionHolder(this.log, this.connManager, managedConn);
response = requestExecutor.execute(request, managedConn, context); HttpRequestExecutor
HttpResponse response = doSendRequest(request, conn, context);
conn.sendRequestHeader(request);
getValidConnection().sendRequestHeader(request);
//创建 流
ensureOpen();
//输入流
this.inBuffer.bind(getSocketInputStream(socket));
//输出流
this.outbuffer.bind(getSocketOutputStream(socket));
//拼接请求头并写入流
//GET /er?jjj=000 HTTP/1.1
//Host: 127.0.0.1:9965
//Connection: Keep-Alive
//User-Agent: Apache-HttpClient/4.5.12 (Java/1.8.0_311)
//Accept-Encoding: gzip,deflate
this.requestWriter.write(request);
// GET /er?jjj=000 HTTP/1.1
writeHeadLine(message);
this.sessionBuffer.writeLine(this.lineBuf);添加数据 并在结尾换行
//处理 请求头
this.sessionBuffer.writeLine (lineFormatter.formatHeader(this.lineBuf, header));添加数据 并在结尾换行
//请求头后面添加换行
this.lineBuf.clear();
this.sessionBuffer.writeLine(this.lineBuf);添加空 并在结尾换行
//
onRequestSubmitted(request);
//
incrementRequestCount();
//post发送数据/
conn.sendRequestEntity((HttpEntityEnclosingRequest) request);
getValidConnection().sendRequestEntity(request);
final HttpEntity entity = request.getEntity();
final OutputStream outStream = prepareOutput(request); 这个输出流里面 包含了 socket 网络链接流
entity.writeTo(outStream);
this.multipart.writeTo(outstream);
this.doWriteTo(out, true);
//数据流 输出到 网卡 到你要的服务器
part.getBody().writeTo(out);
//发送数据
conn.flush();
getValidConnection().flush();
ensureOpen();
doFlush();
//发送
this.outbuffer.flush();
//得到结果
response = doReceiveResponse(request, conn, context);
//创建 并 设置 response
response = conn.receiveResponseHeader();
return getValidConnection().receiveResponseHeader();
//创建对象 并把返回值有多长也设置在这个里面 并标记状态 为以返回,
final HttpResponse response = this.responseParser.parse();
//打印日志
onResponseReceived(response);
//设置取结果的次数
incrementResponseCount();
return response;
//把返回值设置在 response
conn.receiveResponseEntity(response);
getValidConnection().receiveResponseEntity(response);
//取返回值
final HttpEntity entity = prepareInput(response);
//用 ensureOpen 方法产生的 流来创建 返回值。
final InputStream inStream = createInputStream(len, this.inBuffer);
return new ContentLengthInputStream(inBuffer, len);
//把返回值对象 设置到数据返回值中
response.setEntity(entity);