Netwroking知识点总结

677 阅读5分钟

1. Basic properties of TCP and UDP


UDP is a connectionless procotol that is built on the top of IPv4 and IPv6. It dicide the destination address and port and send your data packet. However, the network makes no garantee about whether the packets will arrive. Packets may be dropped if the network is congested. Packets may be duplicated or arrive out of order. Between two distant data-centers it's tipical to see 3% packet loss. A typical case for UDP is when receiving up to date data is more important than receiving all of the data.

TCP is a connection-based protocol that is built on the top od IPv4 or IPv6. TCP creates a pipe between two machines. Under most conditions , bytes sent from one machine will eventuanlly arrive at the other end without duplication or data loss. TCP will automaticlly manage resending packets, ignoring duplicate packets, re-arranging out-of-order packets and changing the rate at which packets are sent. **TCP's three way handshake is known as SYN, SYN-ACK, ACK.**Most services on the internet today use TCP because it hids the complixity of lower, packet-level nature of the Internet.

2. Purpose and properties of each TCP server call


socket

To create a endpoint for networking communication. A new socket by itself is not particularly useful, though we've specified either a packet or stream-based connections it is not bound to a particular network interface or port. Instead socket returns a network descriptor that can be used with later calls to bind, listen and accept.

bind

The bind call associates an abstract socket with and actual network interface and port. It is possible to call bind on a TCP client however it's unusally unnecessary to specify the outgoing port.

listen

The listen call specifies the queue size for the number of incoming, unhandled connections.

accept

Once the server socket has been initialized the server calls accept to wait for new connections. Unlike socket bind and listen, this call will block. i.e. if there are no new connections, this call will block and only return when a new client connects. The return TCP sockets is associated with a particular tuple (client IP, client port, server IP, server port) and will be used for future incoming and outgoing TCP packets that match this tuple. Note that accept call returns a new file descriptor. This file descriptor is specific to a particular client. It is common programming mistake to use the original server socket descriptor for server I/O and then wonder why networking code has failed.

3. Correct order of the “big 4” TCP server calls.


socket->bind->listen->accept

4. What is DNS, and what is its purpose?


DNS is a system called Domain Name Service which can convert alphabetic names into numeric IP addresses. If a machine does hold the answer locally then it sends a UDP packet to a local DNS server. This server in turn may query other upstream DNS server. But it is not safe because DNS requests are not encrypted and susceptible to "man-in-the-midde" attacks.

5. POSIX calls required to create a TCP client


Server code example

int main(int argc, char **argv){
    int s;
    int socket_fd = socket(AF_INET, SOCKET_STREAM, 0);
    struct addrinfo hints, *results;
    memset(hints, 0 , sizeof(addrinfo));
    hints.ai_family = AF_INET;
    hints.ai_sockettype = SOCKET_STREAM;
    hints.ai_flag = AI_PASSIVE;
    s = getaddrinfo(NULL, "1234", &hints, &result);
    if(s != 0){
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
        exit(1);
    }
    if(bind(socket_fd, result->ai_addr, result->ai_addrlen)!=0){
        perror("bind()");
        exit(1);
    }
    if(listen(socket_fd, 10)!=0){
        perror("listen()");
        exit(1);
    }
    struct socketaddr_in *result_addr = (struct socketaddr_in *)result->ai_addr;
    printf("Listening on file descriptor %d, port %d\n", socket_fd, ntohs(result_addr->sin_port));
    printf("Waiting for connection...\n");
    int client_fd = accept(socketd_fd, NULL, NULL);
    printf("Connection made: client_fd=%d\n",client_fd);
    char buffer[1000];
    int len = read(client_fd , buffer, sizeof(buffer) - 1);
    buffer[len] = '\0';
    printf("Read %d chars\n",len);
    printf("===\n");
    printf("%s\n",buffer);
    return 0;

6. Properties of UDP, TCP, IPv4, IPv6, privileged ports


IPv6 && IPv4

Internet protocol(IP) is the primary way to send packets of imformation from one machine to another machine. "IPv4" is the version 4 of the Internet Protocol that describe how to send packets throught a network from one machine to another. 95% of all packets on the Internet are using IPv4. A significant limition of IPv4 is that source and destination address are limited to 32 bits. Each IPv4 packet includes a very small header- typically 20 bytes, includes a source and destination address. Conceptually the source and destination address can be split into two: a network number(upper bits) and the lower bits represent a particular host number on that network. A newer packet protocol solves many of the limitation of IPv4. (e.g. makes routing table simpler and 128 bit address). A machine can have and an IPv6 address and an IPv4 address.

Port

To send a datagram to a host you need to specify the host address and port. The port is an unsigned 16 bit number. Only Process with super-user access can listen to ports <1024. Any process can listen on ports 1024 or higher.

7. Purpose and basic properties of sockets


int socket(int domain, int socket_type, int protocol);

Domain is deciding whether use IPv4 or IPv6. Socket_type decides to using TCP, UDP or others. protocol is an optional choice of protocol configuration, we just leave it 0 as default. This call creates a socket object in the kernel with which one can communicate with the outside world/network. You can use the result of getaddressinfo to fill in the socket parameters (ai_family, ai_sockettype), or provid them manually. The socket call returns an integer - a file descriptor -and, for TCP clients, you can use it like a regular file descriptor. i.e. you can use read and write to receive or send packets. TCP sockets are similar to pipes except that they allow full duplex communication. (you can send and receive data in both directions independently)

8. Be able to correctly choose when to use ntohs, ntohl, htons, htonl


  • h -> host
  • to -> to
  • n -> net
  • l -> unsigned long
  • s -> short

9. Correct setting up addrinfo hints struct for a TCP server or client


struct addrinfo hints;
struct addrinfo *result;
memset(&hints, 0 , sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_sockettype = SOCKET_DGRAM;
s = getaddrinfo(argv[1],argv[2],&hints,&result);
if(s!=0){
    fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
    exit(EXIT_FAILURE);
}

10. Purpose and properties of getaddrinfo


Purpose

The function getaddrinfo can convert a human readable domain name into an IPv4 or IPv6 address. In fact it will return a linked-list of addrinfo structs. Its purpose is determining the remote address of a remote host. Call freeaddrinfo to free the momory allocated for the linked-list of addrinfo struct. If getaddrinfo failed, use gai_strerror to get the equivalent short English error text.

11. Reading and writing to pipes (including blocking, SIGPIPE and detecting when no more bytes can be read)


Error Handler

POSIX will set a errno when a system call is failed. The initial number of errno is 0. But it will never reset to 0. But the errno might be changed, so it is better to store it inside a integer and save it back to errno.

if (-1 == sem_wait(&s)) {
   fprintf(stderr, "An error occurred!");
   fprintf(stderr, "The error value is %d\n", errno);
}
// Better, copy the value before making more system and library calls
if (-1 == sem_wait(&s)) {
   int errno_saved = errno;
   fprintf(stderr, "An error occurred!");
   fprintf(stderr, "The error value is %d\n", errno_saved);
}
void handler(int signal) {
   int errno_saved = errno;

   // make system calls that might change errno

   errno = errno_saved;
}

char* strerror(errno) can get the msg of this error.

strerror Gotchas is not thread safe, two thread cannot call it at the same time. sterror_r and perror is more thread safe.

当system call 被打断的时候会报错,可以通过检查EINTR来确定是不是真的报错

while ((-1 == (result = systemcall(...))) && (errno == EINTR)) { /* repeat! */}

SA_RESTART 可以resart但是不保证可以解决的全部问题

Close() 和shutdown()区别

如果close()链接依旧存在,只是关闭current socket id。如果shutdown的话,所有都无法连接。

如果re-run server code it don't work. 因为会有冷却时间,冷却时间过了之后才能用,可以设置REUSEPORT berofre bind 来重复使用

int optval = 1;
setsockopt(sock_fd, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval));

bind(sock_fd, ...);
  • 可以连接外部port,但是有些情况下不允许外部访问,需要explicitly, call bind before connect.

POSIX send the first SYN with connect