一,TCP的编程流程
二,TCP的特点(面向连接,可靠的,流式服务)
可靠的体现在
1,应答确认,超时重传
2,去重
在超时重传后可能会受到多个相同的数据,此时会去重; TCP具有去重的能力根据序号只保留一份,删除重复的数据;
3,乱序重排(先发的不一定以先到)
根据序号进行排序;
4,滑动窗口
流量的控制,怕你发送的过快对方来不及处理
三,在connect()之后进行三次握手,在close()之后进行四次挥手;
四,多进程的tcp协议代码(注意处理僵死进程)
如果是多线程或多进程的方式创建客户端没想让你创建成千上万个客户端 网络里的每一个小问题都可能会问你 并发(Concurrent),在操作系统中,是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行。 并行(Parallel),当系统有一个以上CPU时,当一个CPU执行一个进程时,另一个CPU可以执行另一个进程,两个进程互不抢占CPU资源,可以同时进行,这种方式我们称之为并行(Parallel)。 复制了引用计数加一了 通用的方法一但子进程结束就会发送SIGCHLD这个信号,这时候用该函数处理一下 不通用的方法:只能在liunx上进行不能在uliunx上进行;
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<signal.h>
#include<sys/wait.h>
#include<unistd.h>
#include<netinet/in.h>
void fun(int sig)
{
wait(NULL);
}
int main()
{
signal(SIGCHLD,fun);
int sockfd=socket(AF_INET,SOCK_STREAM,0);
assert(sockfd!=-1);
struct sockaddr_in saddr,caddr;
memset(&saddr,0,sizeof(saddr));
saddr.sin_family=AF_INET;
saddr.sin_port=htons(6000);
saddr.sin_addr.s_addr=inet_addr("127.0.0.1");
int res=bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
assert(res!=-1);
res=listen(sockfd,5);
assert(res!=-1);
while(1)
{
int len=sizeof(caddr);
int c=accept(sockfd,(struct sockaddr*)&caddr,&len);
if(c<0)
{
continue;
}
printf("accept c=%d",c);
pid_t pid=fork();
if(pid==-1)
{
printf("fork child err");
close(c);
continue;
}
}
if(pid==0)
{
while(1)
{
char buff[128]={0};
int n=recv(c,buff,127,0);
if(n<=0)
{
break;
}
printf("child read:%s\n",buff);
send(c,"ok",2,0);
}
printf("client close\n")
close(c);
exit(0);
}
close(c);
}
}
六,tcp状态转移过程图
1,三次握手不能成为2次握手
(自己关机或者被别人攻击)
2,四次挥手可以成为3次挥手
3,TIME_WAIT存在的意义(重要)
可靠的终止TCP连接
保证让迟来的TCP报文段有足够的时间被识别并丢弃
发送的FIN没有收到(可能存在丢失的情况)ack没有收到再次发送一次FIN 客户端发送数据报文是陆陆续续的到达有可能还有没有到达的报文(先发的不一定先到)等待他的到达然后丢弃(因为不丢弃的话下一次连接就会发送但是这个是发给上一个进程的你现在发给它的下一个进程是不合适的)
七,用netstat -natp命令查看tcp链接的状态
1,协议
2,接收缓冲区字节数
3,发送缓冲区字节数
4,连接状态
5,进程ID号
natp是参数 n是ip地址来表示主机 a是显示监听套接字 t是显示tcp链接 p是显示进程的pid
6,在cli.c加上睡眠查看tcp连接的中间状态
|