展示自己、证明自己
分类: C/C++
2014-04-12 10:11:25
OK,闲话少扯,我们进入主题,下面结合一个简单的TCP服务端与客户端代码,借助tcpdump命令来分析一下TCP建立连接时的三次握手过程(Three-way handshake process)。
服务端代码如下:
/**
* server.c
*
* TCP server program, it is a simple example only.
*
* Writen By: Zhou Jianchun
* Date: 2011.08.12
*
* Compiled With: gcc -o client client.c
* Tested On: Ubuntu 11.04 LTS
*
* gcc version: 4.5.2
*
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define SERVER_PORT 20000
#define LENGTH_OF_LISTEN_QUEUE 10
#define BUFFER_SIZE 255
#define WELCOME_MESSAGE "welcome to our server."
int main(int argc, char **argv)
{
int server_fd, client_fd;
struct sockaddr_in server_addr, client_addr;
if((server_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("create socket error, exit!\n");
exit(1);
}
bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVER_PORT);
server_addr.sin_addr.s_addr = htons(INADDR_ANY);
if(bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0)
{
printf("bind to port %d failed, exit!\n", SERVER_PORT);
exit(1);
}
if(listen(server_fd, LENGTH_OF_LISTEN_QUEUE) < 0)
{
printf("failed to listen, exit!\n");
exit(1);
}
while(1)
{
char buf[BUFFER_SIZE];
long timestamp;
socklen_t length = sizeof(client_addr);
client_fd = accept(server_fd, (struct sockaddr*)&client_addr, &length);
if(client_fd <0)
{
printf("call accept error, break from while loop!\n");
break;
}
strcpy(buf, WELCOME_MESSAGE);
printf("connect from client: IP: %s, Port: %d\n", (char *)inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
timestamp = time(NULL);
strcat(buf, "timestamp on server:");
strcat(buf, ctime(×tamp));
send(client_fd, buf, BUFFER_SIZE, 0);
close(client_fd);
close(server_fd);
return 0;
}
}
代码逻辑十分简单,服务端程序启动后监听在20000端口,等待外部连接,客户端启动后连接过来,服务端发送一串字符串信息给客户端,然后退出,客户端在读取完信息后也退出。
运行程序之前先在另一个终端下输入如下命令:
tcpdump 'port 20000' -i lo -S
待两端程序退出后可以看到该命令输出如下信息:下面我们逐条进行分析:
1.客户端通过49493端口向服务端的20000端口发送一个SYN同步请求包,展开第一次握手,其中Flags [S]表求数据包的类型为SYN, 即同步请求包,seq字段标识数据包序列号。
2.服务端发送ACK确认包,同时附代一个SYN请求包,在确认客户端同步请求的同时 向客户端发送同步请求,其中Flags [S.]中的点号表示这是个确认包(ACK),S表示它同时又是一个SYN请求包。因为TCP是双工通信协议,连接建立之后双方可以同时收发数据,所以双 方都发送了SYN包请求同步。
3.客户端发送ACK包确认服务端的SYN同步请求,可以看到此时Flags中只有一个小数点,表示这个包只是用来做确认的。
到此为止,三次握手过程就结束了,双方如果都收到了ACK包,则都进入到ESTABLISHED状态,表明此时可以进行数据发送了。
4.服务端向客户端发送一个数据包,包中的内容就是一个字符串,可以看到此时的Flags标识中有个字母P,意为PUSH DATA,就是发送数据的意思。
至此TCP三次握手过程的分析就结束了,由于本人水平有限,博客中的不妥或错误之处在所难免,殷切希望读者批评指正。同时也欢迎读者共同探讨相关的内容,如果乐意交流的话请留下您宝贵的意见,谢谢。