有几点设置:
1, 设置了端口重复使用
2, 设置了FD阻塞
3, 每一个TCP请求都会开启一个线程去读FD
4, 每个FD都设置了5秒的超时时间, 如果5秒还没有数据, 则回收相关资源退出
代码如下:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/time.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <fcntl.h>
// 线程回调
void *callFunc(void *arg)
{
pthread_detach(pthread_self());
int *fdPtr = (int *)arg;
int ret = 0;
unsigned char readMsg[1024];
int readMsgLen = sizeof(readMsg);
memset(readMsg, 0x00, readMsgLen);
if ((ret = read(*fdPtr, readMsg, readMsgLen)) == -1)
{
if (errno == EAGAIN)
{
printf("timeout error.\n");
}
goto END;
}
else if (ret == 0)
{
printf("client fd closed.\n");
goto END;
}
printf("recv msg: %s.\n", readMsg);
END:
close(*fdPtr);
free(fdPtr);
pthread_exit(NULL);
}
int recvTimeout(int fd, long long ms)
{
struct timeval tv;
tv.tv_sec = ms/1000;
tv.tv_usec = (ms%1000)*1000;
if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1)
{
printf("setsockopt SO_RCVTIMEO: %s", strerror(errno));
return -1;
}
return 0;
}
int setBlock(int fd)
{
int flags = 0;
if ((flags = fcntl(fd, F_GETFL)) == -1)
{
printf("fcntl F_GETFL failed. errMsg: %s.", strerror(errno));
return -1;
}
flags &= ~O_NONBLOCK;
if (fcntl(fd, F_SETFL, flags) == -1)
{
printf("fcntl F_SETFL failed. errMsg: %s", strerror(errno));
return -1;
}
return 0;
}
int binding(int sockFD)
{
struct sockaddr_in addr;
memset(&addr, 0x00, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_port = htons(1093);
addr.sin_addr.s_addr = inet_addr("192.168.0.3");
if (bind(sockFD, (struct sockaddr*)(void*)(&addr), sizeof(struct sockaddr_in)) != 0)
{
printf("bind failed, errMsg: %s.\n", strerror(errno));
return -1;
}
return 0;
}
int main()
{
int sockFD = 0;
if ((sockFD = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
printf("socket, errMsg: %s.\n", strerror(errno));
return -1;
}
int val = 0;
if (setsockopt(sockFD, SOL_SOCKET, SO_REUSEADDR, (void *)&val, sizeof(int)) == -1)
{
printf("set SO_REUSEADDR failed, errMsg: %s.\n", strerror(errno));
return -1;
}
if (binding(sockFD))
{
return -1;
}
if (listen(sockFD, 512))
{
printf("listen failed, errMsg: %s.\n", strerror(errno));
return -1;
}
printf("start tcp server success.\n");
char errMsg[1024];
memset(errMsg, 0x00, sizeof(errMsg));
for(;;)
{
int *fdPtr = (int *)malloc(sizeof(int));
if (NULL == fdPtr)
{
sprintf(errMsg, "malloc failed.");
goto END;
}
if ((*fdPtr = accept(sockFD, NULL, NULL)) == -1)
{
sprintf(errMsg, "accept failed. errMsg: %s.", strerror(errno));
goto FREE;
}
printf("listen success. fd: %d\n", *fdPtr);
// 设置阻塞和超时时间
if (setBlock(*fdPtr) == -1 || recvTimeout(*fdPtr, 5000) == -1)
{
goto CLOSE;
}
pthread_t pid;
if (pthread_create(&pid, NULL, callFunc, (void *)fdPtr))
{
sprintf(errMsg, "pthread_create failed.");
goto CLOSE;
}
continue;
CLOSE:
close(*fdPtr);
FREE:
free(fdPtr);
END:
printf("%s\n", errMsg);
}
return 0;
}
结果如下: