Socket发送HTTP/1.1请求

为了同志们的革命事业,同志们幸苦了。霍霍。

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);

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值