1.题目及解答
利用linux socket tcp 尝试发送长数据,在写的过程中,调用close,看看没发完的数据是否会继续发送;close之后TCP连接是否会断开,用两种方式查看,(1)netstat命令,(2)wireshark抓包工具,查看发送的数据能不能被抓到,查看三次握手和四次挥手发生的时间,(3)TCP client端的IP和port是由谁创建的?是多少?
修改的代码如所示:主要是用来交互信息的那部分,在客户端中初始化一段长数据,然后在写的过程中,调用close。
图 1 修改的代码
根据程序运行结果可以看到,预期发送的数据是102400bytes,但是服务器端实际接受的却只有14480bytes,说明close之后数据并未接收完全。
而根据抓包信息,通过计算观察,客户端其实已经发送了所有的数据,有三次握手但是并没有四次挥手,中间还有服务器试图和客户端重置连接,但由于最后客户端已经关闭,所有并没有完整的四次挥手。而利用netstat查看服务器端的端口8080发现也已经关闭。TCP client端的IP和port是由socket创建的,根据抓包信息,可以看到其值分别是192.168.61.129和38138。
2.源码
2.1服务端
#include <stdio.h>
#include <netdb.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/types.h>
#define MAX 102400
#define PORT 8080
#define SA struct sockaddr
// Function designed for chat between client and server.
void func(int sockfd)
{
char buff[MAX];
int n = 0;
memset(buff, 'a', MAX);
// read the message from client and copy it in buffer
n = read(sockfd, buff, sizeof(buff));
buff[n] = '\0';
// print buffer which contains the client contents
printf("Total bytes received actually: %d\nServer has exited\n", n);
}
// Driver function
int main()
{
int sockfd, connfd, len;
struct sockaddr_in servaddr, cli;
// socket create and verification
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1)
{
printf("socket creation failed...\n");
exit(0);
}
else
printf("Socket successfully created..\n");
bzero(&servaddr, sizeof(servaddr));
// assign IP, PORT
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(PORT);
// Binding newly created socket to given IP and verification
if ((bind(sockfd, (SA*)&servaddr, sizeof(servaddr))) != 0) {
printf("socket bind failed...\n");
exit(0);
}
else
printf("Socket successfully binded..\n");
// Now server is ready to listen and verification
if ((listen(sockfd, 5)) != 0)
{
printf("Listen failed...\n");
exit(0);
}
else
printf("Server listening..\n");
len = sizeof(cli);
// Accept the data packet from client and verification
connfd = accept(sockfd, (SA*)&cli, &len);
if (connfd < 0)
{
printf("server acccept failed...\n");
exit(0);
}
else
printf("server acccept the client...\n");
// Function for chatting between client and server
func(connfd);
// After chatting close the socket
close(sockfd);
}
2.2客户端
#include <netdb.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define MAX 102400
#define PORT 8080
#define SA struct sockaddr
void func(int sockfd)
{
char buff[MAX];
memset(buff, 'z', sizeof(buff));
while (write(sockfd, buff, sizeof(buff)) > 0)
close(sockfd);
printf("Expected total bytes sent: %d\nClient has exit\n", MAX);
}
int main()
{
int sockfd, connfd;
struct sockaddr_in servaddr, cli;
// socket create and varification
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
printf("socket creation failed...\n");
exit(0);
}
else
printf("Socket successfully created..\n");
bzero(&servaddr, sizeof(servaddr));
// assign IP, PORT
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr("192.168.61.131");
servaddr.sin_port = htons(PORT);
// connect the client socket to server socket
if (connect(sockfd, (SA*)&servaddr, sizeof(servaddr)) != 0) {
printf("connection with the server failed...\n");
exit(0);
}
else
printf("connected to the server..\n");
// function for chat
func(sockfd);
// close the socket
close(sockfd);
}