List of the journal

About Socket, read my several articles enough (1)


In the previous article, we gave a brief introduction to the definition of a socket and the simple usage of TCP in a socket.

This article will focus on HTTP.

What is the HTTP

HTTP -> Hyper Text Transfer Protocol is a stateless connection based on TCP/IP

features

stateless

Stateless means that, in the standard case, each request made by the client is independent and the server does not directly obtain the context of the user’s conversation through the standard HTTP protocol itself.

Here, many people may have questions, we usually use HTTP is not such ah, the server can identify the identity of our request ah, to login how to do ah?

For example, cookie/session is agreed by both the server and client. Each request is filled by the client, and the server queries its own record (database, memory) after obtaining it, determines the identity of the client, and returns the corresponding value.

On the other hand, this feature has nothing to do with the HTTP protocol itself, since the server does not get the corresponding state from the protocol itself.

Statelessness can also be understood as two consecutive HTTP requests sent from the same client to the server, and the server cannot obtain the relationship between the two requests from the HTTP protocol itself

There is no connection

Connectionless means that the server disconnects from the client after responding to the client’s request

structure

HTTP is a hypertext transfer protocol, which, as its name implies, transmits text in a certain format, so let’s talk about the format of this protocol

One of the most important separators in HTTP is CRLF(Carriage Return line-feed), which is the \ R Carriage Return + \ N Line Feed character used for identification

Request the Request

Above is the request format

The request line

GET/HTTP / 1.1 \ r \ n

The first line, also called the request line, is used to tell the server what type of request the client is calling, the path of the requested resource, and the type of request protocol

The request type is what we call GET, POST, and so on, at the beginning of the request

Request resource path is provided to the server’s internal addressing path, to tell the server what the client wants to access resources, in the browser to www.jianshu.com/p/6cfbc63f3… /p/6cfbc63f3a2b

HTTP/1.1 is currently the most popular request protocol type and may be replaced by HTTP/2.0 in the near future

Note:

  1. The link used is an HTTPS link, but the content is the same as HTTP, so using this link as an example, SSL will be covered in the next few articles

  2. The different contents of the request line need to be separated by “” Spaces

  3. The CRLF separator needs to be added to the end of the request line

Request Headers

After the request line, all the way to the body of the request, we call the request header.

The length of the request header is not fixed, and we can put an infinite amount of content into the request header.

But the format of the request header is fixed, and we can think of it as a key-value pair.

Format:

key: value\r\n
Copy the code

What is commonly referred to as a cookie is one of the request headers

The definition and function of some commonly used HTTP header: blog.csdn.net/philos3/art…

Note:

When all the headers are finished (i.e. we want to send the body), we need to add an extra blank line (CRLF) to tell the server that the header is finished

Request Body Request Body

If we don’t use the header that much, the body is something that almost every developer must touch.

Normally, when we make a POST request, the parameters that we upload are right here.

How does the server get the full Body we uploaded? In other words, how does the server know that our body has been transferred?

Let’s think about what we would do if we needed to implement this protocol.

  • Special bytes can be specified as termination characters, and when a specified character is read, the reading is considered complete

  • The sender must know the size of the data to be sent, so it tells the receiver directly that the receiver only needs to stop receiving the data when it receives the specified size

  • Sender also don’t know the size of the data (or he needs to take a big cost to know the size of the data), just tell the receiver first, I also don’t know how many now, when to send, really tells the receiver when sending, “how much did you want to send me the”, finally tell the receiver, “I give out”, the receiving party to stop receiving. ‘

You may have other ideas, but congratulations, you can implement similar reception methods yourself.

Currently, the server relies on the above three methods to receive:

  • Convention special bytes:

After the client sends the data, it calls to close the socket connection. The server begins to parse the data after receiving the closed request, and returns the result, and finally closes the connection

  • Determine the data size:

The client gives the content-Length field in the request header, the server parses the corresponding data and accepts the body. When the body data reaches the specified Length, the server parses the data and returns the result

  • Indeterminate data size (Http/1.1 available)

The client gives the transfer-encoding: chunked header in the request header and then starts preparing to send the data

Each piece of data is sent in a specific format,

Format for:

  1. Line length:

The text at the beginning of each piece of data is the hexadecimal length of the data actually sent in that piece plus the CRLF separator

  1. Line data:

Real sent data plus CRLF separator

Ex. :

12\r\n // Length row 12 in hexadecimal is 18 in hexadecimal It is a chunk data\r\n // Data row CRLF is the separatorCopy the code

The concluding paragraph:

Used to tell the server that data has been sent and to start parsing or storing data.

The closing paragraph is fixed in format

0\r\n
\r\n 
Copy the code

Currently, not many clients use this approach.

At this point, how do I tell the server how much data I should receive is done

And then it’s time to tell the server, what exactly is the data

Also the header definition :Content-Type

Content-type Introduction: blog.csdn.net/qq_23994787…

At this point, the basic format of the Request is covered

In Response to the Response

The corresponding structure

In fact, Response and Request are the same in terms of protocol, but they are different implementations of the Http protocol.

Response line

HTTP / 1.1 200 OK \ r \ n

The first line, also called the response line, is used to tell the client the status of the current request. It consists of the request protocol type, server status code, and corresponding status description

The request protocol type is used to tell the client what protocol the server is using so that the client can process it later.

The server status code is an important return value that informs the server of the outcome of the client request.

Status code is very many, but for our development generally used is the following status code

Status code Corresponding Status Description meaning Customer operations
200 OK Indicates that the request was successfully processed by the server There is no
400 Bad Request This indicates that there is a problem with the client request that the server cannot recognize until the client modifies it Modifying request Parameters
401 Unauthorized The current request requires permission verification, and the client must submit the corresponding permission information in the header of the next request Modify the Header and submit the corresponding information
403 Forbidden The current request was rejected by the server (firewall blocking or other reasons). Wait some time and then initiate again, no other solution
404 Not Found The service cannot find the resource (most common error code) Modify the resource Request path in Request
405 Method Not Allowed The client currently requested method is not allowed Modify request method
408 Request Timeout Client Request timeout (the server did not parse all requests within the allowed time) Resending the request
500 Internal Server Error Server error (possibly failure to handle exceptions during operation) Contact the backend developer to solve the problem (anyone who says this is a client problem, talk to him)

Complete error code refer to the url: baike.baidu.com/item/HTTP state…

Response HeadersResponse Body

These are the same as their counterparts in the Request, so I don’t have to go over them


Now that we’ve covered HTTP-related properties in the feature and structure sections, the main content of this article is pretty much over, and I’m going to cover some other HTTP-related topics

Cross domain

As mobile developers, we don’t know a lot about this, and we rarely use it, but I need to explain it here. Because now we have arrived at the front end of the era, in case we need to step into the front end, understanding cross-domain, at least for us to solve a lot of things.

This article will not explain in detail how to solve cross-domain, only why cross-domain occurs

What is cross-domain

When we talk about cross domains, we need to talk about what is a domain

What is a domain

As we saw in the previous tutorial on sockets, there are at least two things you need to know to set up a TCP/IP connection

  1. Host address of the other party
  2. The other party’s house number (port)

These are the only two things we can rely on to establish a TCP/IP connection, where host tells us how to find each other, and port tells us which port we should connect to.

The server application is always listening on this port, so that the server can respond directly to the corresponding message when a connection comes in

Moving on, when we talk about servers, we usually refer to server applications, such as Tomcat, Apache, etc., which usually start with a specified port bound (usually not both ports). So, as a client, you can use host+port to identify a specific server application

From this, the concept of a domain is generated, which is host + port

For example: http://127.0.0.1:8056/

This url belongs to the domain 127.0.0.1+8056 or 127.0.0.1:8056

Localhost :8056 is the same field as 127.0.0.1:8056.

They do not belong to the same domain and are strictly specified because their host representation is different, so no.

Cross domain

Now that we know about domains, we have cross-domains, where one domain accesses another domain.

We can see from the HTTP protocol that the server does not enforce any domain, that is, the server does not care which domain the access comes from, and as a client, we do not have such a domain.

So what exactly is cross-domain?

So that’s where cross-domain comes in, the website that we visit every day, it’s actually HTML code, and the server sends it to the browser, and the browser renders it and displays it to us.

Browser development programmers in the development, also don’t know what to do this web page, but they are for safety sake, can’t give web pages and the client (socket) the same permissions, so they restrict certain operations, in the domain of some of the requested action in each other’s web server does not add allowed to access the domain, Access operations will not be performed, and these operations have a significant impact on browser security.

So that’s where cross-domain comes in.

Cross-domain is a client-side operation from beginning to end, and in some ways, it has nothing to do with the server, because the server has no way of knowing whether a request is coming from a web page or not (if the client doesn’t cooperate), so it can’t prohibit it

For our mobile terminal, after understanding cross-domain, we can at least say that cross-domain has nothing to do with us

Socket implements simple HTTP requests

In fact, if an article does not have the support of the code, only the pure concept of exposition, after all, it still feels shortcomings, this article will make some small improvements on the basis of the code of the previous article.

Here is the HTTP tutorial of Cainiaotuo.com as the test of this article (www.runoob.com/http/http-t…). (IP: 47.246.3.228:80)

// MARK: -create Create
let socketFD = Darwin.socket(AF_INET.SOCK_STREAM.0)

func converIPToUInt32(a: Int, b: Int, c: Int, d: Int) -> in_addr {
    return Darwin.in_addr(s_addr: __uint32_t((a << 0) | (b << 8) | (c << 16) | (d << 24)))}// MARK: -connect Connect
var sock4: sockaddr_in = sockaddr_in()

sock4.sin_len = __uint8_t(MemoryLayout.size(ofValue: sock4))
// Converts IP to UInt32
sock4.sin_addr = converIPToUInt32(a: 47, b: 246.c: 3, d: 228)
// Since the memory byte is the opposite of the network communication byte, we need to switch the size of the port we connect to is 80
sock4.sin_port = CFSwapInt16HostToBig(80)
// Setting sin_family to AF_INET indicates an IPv4 connection
sock4.sin_family = sa_family_t(AF_INET)
// Swift is more complex than OC
let pointer: UnsafePointer<sockaddr> = withUnsafePointer(to: &sock4, {$0.withMemoryRebound(to: sockaddr.self, capacity: 1, {$0})})

var result = Darwin.connect(socketFD, pointer, socklen_t(MemoryLayout.size(ofValue: sock4)))
guardresult ! = -1 else {
    fatalError("Error in connect() function code is \(errno)")}// Assemble text protocol access rookie tutorial Http tutorial
let sendMessage = "GET/HTTP/HTTP - tutorial. HTTP / 1.1 HTML \ r \ n"
    + "Host: www.runoob.com\r\n"
    + "Connection: keep-alive\r\n"
    + "USer-Agent: Socket-Client\r\n\r\n"
// Convert to binary
guard let data = sendMessage.data(using: .utf8) else {
    fatalError("Error occur when transfer to data")}// Convert pointer
let dataPointer = data.withUnsafeBytes({UnsafeRawPointer($0)})

let status = Darwin.write(socketFD, dataPointer, data.count)

guardstatus ! = -1 else {
    fatalError("Error in write() function code is \(errno)")}// Set 32Kb byte storage to prevent overflow
let readData = Data(count: 64 * 1024)

let readPointer = readData.withUnsafeBytes({UnsafeMutableRawPointer(mutating: $0)})
// Records how many bytes are currently read
var currentRead = 0

while true {
    // Read socket data
    let result = Darwin.read(socketFD, readPointer + currentRead, readData.count - currentRead)

    guard result >= 0 else {
        fatalError("Error in read() function code is \(errno)")}// Sleep is called less frequently
    sleep(2)
    if result == 0 {
        print("No new data")
        continue
    }
    // Record the latest read data
    currentRead += result
    / / print
    print(String(data: readData, encoding: .utf8) ?? "")}Copy the code

Code examples are available on Github at github.com/chouheiwa/S…

conclusion

The more we learn, the less we know. Every step we take now is learning.

Side note: Drawing is so laborious, it’s all done by PPT

Note: this article is original, if you want to reprint, please contact the author

Reference:

Novice tutorial

Baidu encyclopedia