Wirehark agarra el protocolo de enlace de tres vías del tcp y cuatro paquetes ondulados
En primer lugar, todo el mundo necesita conectarse. El proceso de establecimiento de la conexión tcp es lo que necesitamos entender. Sólo después de la comprensión podemos transmitir datos.
Todo el mundo tiene que participar en el proceso de limpieza. El blog anterior a mí hablaba específicamente sobre cómo crearlo, y aquí solo hablo de la captura de paquetes. Enlace: https://blog.csdn.net/qq_45125250/article/details/108549338
Proceso de captura
- Abre el servidor
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
void handle_sigchld2(int signo)
{
int mypid;
while (( mypid = waitpid(-1, NULL, WNOHANG)) > 0){
printf("child %d terminated\n", mypid);
}
}
int main(){
int listen_fd,client_fd;
struct sockaddr_in serv_addr;
struct sockaddr_in cli_addr;
socklen_t socklen = sizeof(cli_addr);
char buf[1024];
int rv;
listen_fd = socket(AF_INET, SOCK_STREAM,0);
if(listen_fd < 0){
printf("creat socket_fd is failed:[%s]\n",strerror(errno));
return -1;
}
printf("create socket successful\n");
//将socket_in结构体清空为0
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(8899);
serv_addr.sin_addr.s_addr = htonl( INADDR_ANY);
if( bind(listen_fd, (struct sockaddr *)&serv_addr,sizeof(serv_addr))<0){
printf("bind is failed:[%s]\n",strerror(errno));
return -1;
}
printf("socket:[%d],bind on port:[%d]\n",listen_fd,8899);
listen(listen_fd,14);
signal(SIGCHLD, handle_sigchld2);
while(1){
client_fd = accept(listen_fd, (struct sockaddr *) &cli_addr, &socklen);
if(client_fd < 0) {
printf("Accept new client failure: %s\n", strerror(errno));
continue;
}
printf("Accept new client[%s:%d] successfully\n" ,inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port));
pid_t pid;
int status = -1;
pid = fork();
if( pid < 0 )
{
printf("fork() create child process failure: %s\n", strerror(errno));
close(client_fd);
continue;
}
else if( pid > 0 )
{
/* Parent process close client fd and goes to accept new socket client again */
waitpid(pid, &status, WNOHANG);
close(client_fd);
continue;
}
else{
char buf[1024];
/* Child process close the listen socket fd */
close(listen_fd);
printf("Child process start to commuicate with socket client...\n");
memset(buf, 0, sizeof(buf));
rv=read(client_fd, buf, sizeof(buf));
if( rv < 0 )
{
printf("Read data from client sockfd[%d] failure: %s\n", client_fd, strerror(errno));
close(client_fd);
exit(0);
}
printf("Read %d bytes data from Server: %s\n", rv, buf);
rv = write(client_fd,buf,sizeof(buf));
if(rv<0){
printf("write is failed:[%s]\n",strerror(errno));
close(client_fd);
exit(0);
}
close(client_fd);
exit(0);
}
}
close(listen_fd);
}
El código anterior es un servidor multiproceso escrito por mi propio servidor, que puede aceptar múltiples clientes, es decir, el lado del servidor creado por él, puerto: 8899,
y luego realizar las siguientes operaciones
gcc mul_fork.c -o mm
./mm
En este momento, verá esta información impresa
- Abra el cliente
- El segundo paso es abrir el cliente.La herramienta tcp que usé en el cliente
ingresa la ip y el puerto del servidor y hace clic en el enlace.Este proceso ya ha establecido un protocolo de enlace tcp de tres vías. El servidor imprimirá la siguiente información.
En este momento, todo el mundo sabe cómo establecer la comunicación tcp y podemos usar wirehark para capturar paquetes. - wirehark
romper wirehark
Haga clic en la red a la que está conectado, el cable de red que conecté directamente y soy un Ethernet 3. Después de hacer clic, la pantalla es sí.
En este momento estamos a punto de comenzar a capturar paquetes, primero configura el filtrado de información, es decir, solo captura los paquetes tcp de la ip y puerto de tu propio servidor.
Después de configurar, encendemos el servidor y dejamos que comience a escuchar.
Empiece a escuchar, usamos tcptool para conectarnos a nuestro servidor.
Estos son los tres paquetes tcp que aparecieron después de hacer clic en Conectar. El primer [SYN] es un paquete de conexión de solicitud, syn = 1, ack = 0. El segundo [SYN, ACK] es el paquete de respuesta del servidor, syn = 1 , ack = 1, el tercero es el paquete de respuesta [ACK] que el cliente enviará al servidor, syn = 0, ack = 1, en este momento nuestra conexión ha sido establecida.
Ahora hablaré sobre el contenido del paquete tcp. Puede ver la imagen que publiqué en la parte superior, que es la información contenida en tcp, y también podemos verla cuando capturamos el paquete.
Primero, explique un paquete de solicitud de conexión [SYN]
Al hacer clic en la primera línea, veremos que aparece la siguiente información:
El contenido de las dos representaciones es el mismo, pero los métodos de representación son diferentes.
Solo mire la parte azul. Esta parte es el contenido del paquete tcp. Lo anterior es el contenido del encabezado de red y el encabezado del enlace de datos. No nos importa aquí, solo la parte tcp.
Comparemos el contenido de las siguientes dos imágenes, la relación correspondiente es exactamente la misma.
adentro
源端口:fe 1e
目的端口: 22 c3
序号(seq):12 12 fb 2a
确认号(ack):00 00 00 00
数据偏移: 80
窗口:fa f0
校验和: 27 5b
紧急指针:00 00
可选项:就是后面的所有字节。12个字节。
Lo único de lo que no hablé arriba son las banderas: bit de bandera, lo mostraré por separado,
podemos ver lo que hay dentro,
保留位: 0
urgent : 0
ack : 0
push: 0
reset :0
syn : 0
fin : 0
Debido a que este es el primer paquete, syn: 1, ack: 0. Esto representa la solicitud de conexión, a continuación, hablaré sobre el segundo paquete, que el servidor envía al cliente.
El segundo paquete [SYN, ACK]
Como puede ver, syn = 1, ack = 1. Estamos viendo el segundo apretón de manos, es ack igual al primer paquete [SYN] request packet + 1. Lo
anterior seq = 12 12 fb 2a Nuestro servidor devuelve El paquete de confirmación es 12 12 fb 2b, que se suma por 1, por lo que es correcto.
La secuencia enviada por segunda vez es: bf 93 84 8c.
Entonces veamos si el paquete ACK devuelto por tercera vez es bf 93 84 8d
. Este es el caso. Por lo tanto, nuestra suposición está verificada.
Nota: El apretón de manos de tres vías se produce después de escuchar y antes de aceptar.