TCP套接字编程
TCP的三次握手,四次挥手图解
三次握手:
1.确认目的设备存在于网络上;
2.确认目的设备有活动的服务,并且正在源客户端要使用的目的端口号上接受请求;
3.通知目的设备源客户端想要在该端口号上建立通信会话。
过程:
1. 客户端向服务器发送包含初始序列值的数据段,开启通信会话;
2. 服务器发送包含确认值的数据段,其值等于收到的序列值加 1,并加上其自身的同步序列值。该值比序列号大 1,因为 ACK 总是下一个预期字节或二进制八位数。通过此确认值,客户端可以将响应和上一次发送到服务器的数据段联接起来;
3. 发送带确认值的客户端响应,其值等于接受的序列值加 1。这便完成了整个建立连接的过程。
四次挥手:
1. 当客户端的数据流中没有其它要发送的数据时,它将发送带 FIN 标志设置的数据段;
2. 服务器发送 ACK 信息,确认收到从客户端发出的请求终止会话的 FIN 信息;
3. 服务器向客户端发送 FIN 信息,终止从服务器到客户端的会话;
4. 客户端发送 ACK 响应信息,确认收到从服务器发出的 FIN 信息。
注:FIN(表示结束) ACK(表示确认)
TCP通信的具体步骤:
● 服务器端流程
1 创建套接字(socket)
2 服务绑定(bind)
3 服务侦听(listen)
4 处理新到连接(accept)
5 数据收发(recv\send)
6 套接字关闭(close)
● 客户端流程
① 客户端套接字创建(socket)
② 发起连接 (connect)
③ 数据发收(send\recv)
图解:
程序:
文件1:utili.h
#include<unistd.h>
#include<stdio.h>
#include<string.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#define SERVER_PORT 9090
#define SERVER_IP "192.168.2.252"
#define LISTEN_QUEUE 5
#define BUFFER_SIZE 255
文件2:Ser.cpp
#include"utili.h"
int main()
{
int sockSer = socket(AF_INET, SOCK_STREAM, 0);//返回套接字的描述符
if(sockSer == -1) //判断
{
perror("socket");
return -1;
}
struct sockaddr_in addrSer, addrCli;
addrSer.sin_family = AF_INET; //协议、地址族
addrSer.sin_port = htons(SERVER_PORT); //端口
addrSer.sin_addr.s_addr = inet_addr(SERVER_IP);
//IP地址
int yes = 1;
setsockopt(sockSer, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
socklen_t len = sizeof(struct sockaddr);
int res = bind(sockSer,(struct sockaddr*)&addrSer, len); //绑定套接字
if(res == -1)//判断
{
perror("bind");
close(sockSer);
return -1;
}
res = listen(sockSer, LISTEN_QUEUE);//帧听
if(res == -1)
{
perror("listen");
close(sockSer);
return -1;
}
int sockConn;
sockConn = accept(sockSer, (struct sockaddr*)&addrCli, &len);//处理到新连接
if(sockConn == -1)
{
printf("Server Accept Client Connect Fail.\n");
close(sockSer);
return -1;
}
else
{
printf("Server Accept Client Connect OK.\n");
printf("Client IP:> %s\n",inet_ntoa(addrCli.sin_addr));
printf("Client PORT:>%d\n",ntohs(addrCli.sin_port));
}
char sendbuf[BUFFER_SIZE];
char recvbuf[BUFFER_SIZE];
while(1)
{
printf("Ser:>");
scanf("%s",sendbuf);
send(sockConn, sendbuf, strlen(sendbuf)+1, 0);//发送数据
recv(sockConn, recvbuf, BUFFER_SIZE, 0);//接收数据
printf("CLi:>%s\n",recvbuf);
}
close(sockSer);//关闭服务器端
return 0;
}
文件3:Cli.cpp
#include"utili.h"
int main()
{
int sockCli = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in addrSer;
addrSer.sin_family = AF_INET;
addrSer.sin_port = htons(SERVER_PORT);
addrSer.sin_addr.s_addr = inet_addr(SERVER_IP);
struct sockaddr_in addrCli;
addrCli.sin_family = AF_INET;
addrCli.sin_port = htons(7070);
addrCli.sin_addr.s_addr = inet_addr("192.168.3.252");
socklen_t len = sizeof(struct sockaddr);
bind(sockCli, (struct sockaddr*)&addrCli, len);
int res = connect(sockCli, (struct sockaddr*)&addrSer, len);
if(res == -1)
{
printf("Client Connect Server Fail.\n");
close(sockCli);
return -1;
}
else
{
printf("Client Connect Server OK.\n");
}
char sendbuf[BUFFER_SIZE];
char recvbuf[BUFFER_SIZE];
while(1)
{
recv(sockCli, recvbuf, BUFFER_SIZE, 0);
printf("Ser:>%s\n",recvbuf);
printf("Cli:>");
scanf("%s",sendbuf);
send(sockCli, sendbuf, strlen(sendbuf)+1, 0);
}
close(sockCli);//关闭客户端
return 0;
}