TCP
TCP 的编程流程:
sever(服务器端):
socket(创建一个标识)
bind(用端口号和IP地址命名)
listen(监听)
accept(接收数据)
recv/send(发送数据)
client(客户端):
socket
/*bind */(可有可无)已知服务器的名称,通讯时服务器自然就知道了客户端的名称
connect(发起连接)
recv/send(发送数据)
close
服务器端编程流程中具体的函数类型:
int socket(int domain(协议簇 AF_INET),int type(选择SOCK_STREAM(tcp)还是SOCK_DGRAM(udp)协议), int protocol(tcp下的哪个))
int bind(int sockfd (创建的套接字),const struct sockaddr*addr指定IP地址和端口号,socklen_t addrlen长度)
struct sockaddr_in{
sa_family_t sin_family;//地址簇
u_int16_tsin_port; //端口号(网络字节序,大端模式)
struct in_addrsin_addr;//IPv4
}
struct in_addr{
u_int32_ts_addr;//IP地址最终的表示
}
int listen(int sockfd,int size);//创建的套接字,创建队列的大小
创建一个文件监听描述队列
int accept(intsockfd,struct sockaddr*addr,int *addrlen)
返回值:从监听中获取到的和客户端连接的文件描述符
addr::记录客户端的IP地址和端口号
客户器端编程流程中具体的函数类型
socket send/recv close
int connect(intsockfd, struct sockaddr*addr,int addrlen)
addr::要连接的服务器的IP地址和端口号
相关代码:
//ser.c
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<assert.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<srpa/inet.h>
void main()
{
int sockfd = socket(AF_INET,SOCK_STREAM,0);
assert(socket != -1);
struct sockaddr_in ser,cli;
ser.sin_family = AF_INET;
ser.sin_port = htons(6000);
ser.sin_addr.s_addr =inet_addr("127.0.0.1");
int res = bind(sockfd,(struct sockaddr*)&ser,sizeof(ser));
assert(res != -1);
listen(sockfd,5);
while(1)
{
int len = sizeof(cli);
int c = accept(sockfd,(struct sockaddr*)&cli,&len);//从队列里取一个链接
assert(c != -1);
while(1)
{
char buff[128]={0};
int n = recv(c,buff,127,0);
if(n<=0)break;
printf("recv::%s\n",buff);
send(c,"i know",strlen("i know"),0);
}
close(c);
}
close(sockfd);
}
//cli.c
void main()
{
int sockfd = socket(AF_INET,SOCK_STREAM,0);
assert(sockfd != -1);
struct sockaddr_in ser,cli;
ser.sin_family = AF_INET;
ser.sin_port = htons(6000)
ser.sin_addr.s_addr = inet_addr("127.0.0.1");
int res = connect(sockfd,(struct sockaddr*)&ser,sizeof(ser));
assert(res!=-1);
send(sockfd,"hello world",strlen("hello world"),0);
charbuff[128]={0};
recv(sockfd,buff,127,0);
printf("recv::%s\n",buff);
close(sockfd);
}
注:
如果出现断言时出错,IP地址不对或端口号被占用(小于1024不能用,大于1024已经被占用)或无权限使用。
TCP三次握手创建连接过程
TCP四次挥手断开连接的过程
1.客户端向服务器发起FIN断开连接请求,
2.服务器端向客户端发送ACK回馈表示接收到断开连接的请求
3.如果这个时候服务器端没处理完数据,则需要一段时间处理数据,直到处理完以后才向客户端发送FIN断开连接的操作 如(1)
TCP也可能三次挥手,这种情况下服务器不需要有处理数据的时间,在向客户端发送ACK回馈时,同时发送断开连接的操作 如(2)
4.客户端接收到服务器断开连接的请求后向服务器发送一个ACK表示知道已经断开连接