TCP状态转换
三次握手完成
SYN_SENT:connet();
LISTEN:
四次挥手过程:
主动关闭方:
FIN_WAIT_1
FIN_WAIT_2
TIME_WAIT
被动关闭方:
CLOSE_WAIT:
LASK_ACK:
端口复用
半关闭
多路复用技术 select函数介绍
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set exceptfds, struct timevaltimeout);
nfds:文件描述符号
readfds:读事件
writefds:–写时间
exceptfds:–输入输出参数, 表示异常事件
timeout:–超时时间
-----NULL:永久阻塞
-----0:不阻塞 不管有没有时间发生 都立刻返回
----- >0:阻塞时长 没超过时长一直阻塞 在时长内有事件发生就立刻返回 超过时长就立刻返回
return:<0失败 ------->0发生事件的文件描述符有多少个
void FD_CLR(int fd, fd_set *set);
说明:从Set中清楚fd
int FD_ISSET(int fd, fd_set *set);
说明:fd是否在set里面
void FD_SET(int fd, fd_set *set);
说明:将fd添加到集合当中
void FD_ZERO(fd_set *set);
说明:清空set
#include <stdio.h>
#include <ctype.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <stdlib.h>
#define SERV_PORT 6666
int main(int argc, char *argv[])
{
CFLAGS = -lpthread -m32 -Wall -g makefile 5
int listenfd,connectfd;
char buf[BUFSIZ];
int n = 0;
socklen_t clie_addr_len;//传出地址的大小
listenfd = socket(AF_INET,SOCK_STREAM,0);
//端口复用setsockopt
int opt = 1;
setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
//定义地址
struct sockaddr_in serv_addr,clie_addr;
//初始化
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(SERV_PORT);
bind(listenfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr));
listen(listenfd,128);
//两个集合 一个监听 一个备份
fd_set rset,allset;
//清零第2个集合 将lfd添加到监听集合
int ret,maxfd = 0;
maxfd = listenfd;
FD_ZERO(&allset);
FD_SET(listenfd,&allset);
while(1)
{
rset = allset;
ret = select(maxfd+1,&rset,NULL,NULL,NULL);
if (ret<0)
{
perror("select");
}
if(FD_ISSET(listenfd,&rset))
{
connectfd = accept(listenfd,(struct sockaddr*)(&clie_addr),&clie_addr_len);
FD_SET(connectfd,&allset);
if (maxfd<connectfd)
{
maxfd = connectfd;
}
if (ret == 1)
{
continue;
}
}
for (int i = listenfd; i < maxfd+1 ; ++i)
{
if(FD_ISSET(i,&rset))
{
n = read(i,buf,sizeof(buf));
if (n==0)
{
close(i);
FD_CLR(i,&allset);
}
for (int j = 0; j < n; ++j)
{
buf[j] = toupper(buf[j]);
}
write(i,buf,n);
write(STDOUT_FILENO,buf,n);
}
}
}
//调用select函数
// 每次循环重新调用select函数
// 添加
//返回值大于0;有请求 ;
//调用connect连接
close(listenfd);
return 0;
}