对setsocketopt()的解析

本文介绍了如何使用setsockopt函数禁用TCP中的Negle算法,详细解析了setsockopt函数的参数,包括套接字名、协议类型、协议选项、选项值缓冲及字节大小,并提供了一个禁用Negle算法的示例。

今天在看怎么禁用TCP中的negle算法,学习到了setsockopt函数。下面分享一下setsockopt函数的调用和参数详解:

int Err=setsockopt(int sockfd,int level,int optname,const void* optval,socklen_t optlen);

第一个参数就是套接字名sockfd;

第二个参数是使用的协议,有以下三种:

SOL_SOCKET 通用套接字;

IPPROTO_IP IP协议;

IPPROTO_TCP TCP协议;

第三个参数是协议里的选项;

通用套接字里面的有好多好多,我大致的看了一遍,都没怎么用到过,以后用到了我在改博客更新。

IP协议选项有下面几个:

IP_HDRINCL  在数据报中包含IP首部

IP_OPTIONS  IP首部选项

IP_TOS     服务类型

IP_TTL      生存时间

TCP协议两个:

TCP_MAXSEG   TCP最大数据段的大小;

TCP_NODELAY   TCP的不使用negle算法;

第四个参数  返回选项值的缓冲;

第五个参数  选项值的字节大小;

现在写一个,禁用negle算法的例子:

const char chOpt=1;
int Err;
Err=setsockopt(sockfd,IPPRO_TCP,TCP_NODELAY,&chOpt,sizeof(char));
if(Err==-1)
   perror("setsockopt error!");

+

/* Copyright(c) 2008-2025 Shenzhen TP-LINK Technologies Co.Ltd * * file http_server.c * brief 使用多线程实现的http server接口 * * author Ban Qilu * version 1.0.0 * data 08Aug25 * * history \arg 1.0.0, 08Aug25, Ban Qilu, Creat the file. */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* INCLUDE_FILES */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <errno.h> #include <sys/wait.h> #include <signal.h> #include "../include/http_server.h" #include "../include/http_resp.h" /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* DEFINES */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* TYPES */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* EXTERN_PROTOTYPES */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* LOCAL_PROTOTYPES */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* VARIABLES */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ static int l_server_fd = -1; static int l_child_process_count = 0; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* LOCAL_FUNCTIONS */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * fn static int handle_task(TASK* in_task) * brief 处理http任务请求. * * param[in] in_task 需要处理的任务. * * return 任务处理状态. * retval OPT_SUCCESS 任务处理成功. * OPT_FAILED 任务处理失败. * */ static int handle_task(TASK* in_task) { char rcv_buf[1024] = {'\0'}; char file_path[256] = {'\0'}; HTTP_REQ_INFO req_info = {'\0', '\0', '\0'}; int len; if (NULL == in_task) { return OPT_FAILED; } len = recv(in_task->cliend_fd, rcv_buf, sizeof(rcv_buf), 0); prase_req_info(rcv_buf, &req_info); get_file_path(&req_info, file_path); send_resp(in_task->cliend_fd, file_path); close(in_task->cliend_fd); return OPT_SUCCESS; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* PUBLIC_FUNCTIONS */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* GLOBAL_FUNCTIONS */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * fn void handle_signal(int sig) * brief 终止信号处理函数,检测到停止信号(Ctrl+C)后关闭服务端socket, 关闭所有进程. * * param[in] sig 检测到的信号. * * return * */ void handle_signal(int sig) { if (SIGINT == sig || SIGTERM == sig) { printf("\nhttp server shutting down......\n"); if (l_server_fd != -1) { close(l_server_fd); l_server_fd = -1; } if (l_child_process_count > 0) { kill(-getpid(), SIGTERM); while ((waitpid(-1, NULL, WNOHANG)) > 0) { l_child_process_count--; } } exit(EXIT_SUCCESS); } } /* * fn void handle_sigchld(int sig) * brief SIGCHLD信号处理函数. * * param[in] sig 检测到的信号. * * return * */ void handle_sigchld(int sig) { int saved_errno = errno; while ((waitpid(-1, NULL, WNOHANG)) > 0) { l_child_process_count--; } errno = saved_errno; } /* * fn void set_signal_handlers() * brief 设置server的信号检测, 启动时使用. * */ void set_signal_handlers() { struct sigaction sa; signal(SIGINT, handle_signal); signal(SIGTERM, handle_signal); /* 设置SIGCHLD处理 */ sa.sa_handler = handle_sigchld; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART || SA_NOCLDSTOP; if (-1 == sigaction(SIGCHLD, &sa, NULL)) { perror("Sigaction failed.\n"); exit(EXIT_FAILURE); } signal(SIGPIPE, SIG_IGN); } /* * fn int start_http_server() * brief 服务器启动接口, 初始化socket、bind、listen, 在主循环中accept后创建子进程处理task. * * return 启动状态. * retval OPT_SUCCESS 启动成功. * OPT_FAILED 启动失败. */ int start_http_server() { int client_fd, sock_opt; struct sockaddr_in server_addr; TASK task; socklen_t addr_len; pid_t pid; int ret, i; /* socket */ l_server_fd = socket(AF_INET, SOCK_STREAM, 0); if (-1 == l_server_fd) { perror("Create socket error.\n"); exit(EXIT_FAILURE); } /* 允许端口重用 */ sock_opt = 1; ret = setsockopt(l_server_fd, SOL_SOCKET, SO_REUSEADDR, &sock_opt, sizeof(sock_opt)); if (-1 == ret) { perror("Setsocketopt error.\n"); exit(EXIT_FAILURE); } /* bind */ server_addr.sin_family = AF_INET; server_addr.sin_port = htons(SERVER_PORT); server_addr.sin_addr.s_addr = inet_addr(SERVER_IP_ADDR); ret = bind(l_server_fd, (const struct sockaddr*)&server_addr, sizeof(server_addr)); if (-1 == ret) { perror("Bind error.\n"); exit(EXIT_FAILURE); } /* listen */ ret = listen(l_server_fd, MAX_CONN_REQ); if (-1 == ret) { perror("Listen error.\n"); exit(EXIT_FAILURE); } /* 主循环接受连接并加入任务 */ addr_len = sizeof(server_addr); while (1) { client_fd = accept(l_server_fd, (struct sockaddr*)&server_addr, &addr_len); if (client_fd < 0) { perror("Accept failed"); continue; } if (l_child_process_count >= MAX_CHILD_PROCESS) { printf("Too many child process, rejecting connection.\n"); close(client_fd); continue; } pid = fork(); if (pid < 0) { perror("Fork failed.\n"); close(client_fd); } else if (pid > 0) /* 父进程 */ { close(client_fd); l_child_process_count++; } else { close(l_server_fd); task.cliend_fd = client_fd; handle_task(&task); } } close(l_server_fd); return OPT_SUCCESS; } 代码问题
08-10
/* Copyright(c) 2008-2025 Shenzhen TP-LINK Technologies Co.Ltd * * file http_server.c * brief 使用多线程实现的http server接口 * * author Ban Qilu * version 1.0.0 * data 08Aug25 * * history \arg 1.0.0, 08Aug25, Ban Qilu, Creat the file. */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* INCLUDE_FILES */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <errno.h> #include "../include/http_server.h" #include "../include/http_resp.h" /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* DEFINES */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* TYPES */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* EXTERN_PROTOTYPES */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* LOCAL_PROTOTYPES */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* VARIABLES */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ static int l_server_fd; static int l_child_process_count = 0; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* LOCAL_FUNCTIONS */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * fn static int handle_task(TASK* in_task) * brief 处理http任务请求. * * param[in] in_task 需要处理的任务. * * return 任务处理状态. * retval OPT_SUCCESS 任务处理成功. * OPT_FAILED 任务处理失败. * */ static int handle_task(TASK* in_task) { char rcv_buf[1024] = {'\0'}; char file_path[256] = {'\0'}; HTTP_REQ_INFO req_info = {'\0', '\0', '\0'}; int len; if (NULL == in_task) { return OPT_FAILED; } len = recv(in_task->cliend_fd, rcv_buf, sizeof(rcv_buf), 0); prase_req_info(rcv_buf, &req_info); get_file_path(&req_info, file_path); send_resp(in_task->cliend_fd, file_path); close(in_task->cliend_fd); return OPT_SUCCESS; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* PUBLIC_FUNCTIONS */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* GLOBAL_FUNCTIONS */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * fn void handle_signal(int sig) * brief 信号处理函数,检测到停止信号(Ctrl+C)后关闭线程池并关闭服务端socket. * * param[in] sig 检测到的信号. * * return * */ void handle_signal(int sig) { int i; printf("\nl_thread_pool.shutdown.\n"); close(l_server_fd); } /* * fn int start_http_server() * brief 服务器启动接口, 初始化socket、bind、listen, 在主循环中accept后创建子进程处理task. * * return 启动状态. * retval OPT_SUCCESS 启动成功. * OPT_FAILED 启动失败. * */ int start_http_server() { int client_fd, sock_opt; struct sockaddr_in server_addr; TASK task; socklen_t addr_len; pid_t pid; int ret, i; /* socket */ l_server_fd = socket(AF_INET, SOCK_STREAM, 0); if (-1 == l_server_fd) { perror("Create socket error.\n"); exit(EXIT_FAILURE); } /* 允许端口重用 */ sock_opt = 1; ret = setsockopt(l_server_fd, SOL_SOCKET, SO_REUSEADDR, &sock_opt, sizeof(sock_opt)); if (-1 == ret) { perror("Setsocketopt error.\n"); exit(EXIT_FAILURE); } /* bind */ server_addr.sin_family = AF_INET; server_addr.sin_port = htons(SERVER_PORT); server_addr.sin_addr.s_addr = inet_addr(SERVER_IP_ADDR); ret = bind(l_server_fd, (const struct sockaddr*)&server_addr, sizeof(server_addr)); if (-1 == ret) { perror("Bind error.\n"); exit(EXIT_FAILURE); } /* listen */ ret = listen(l_server_fd, MAX_CONN_REQ); if (-1 == ret) { perror("Listen error.\n"); exit(EXIT_FAILURE); } /* SIGCHLD信号处理 */ /* 主循环接受连接并加入任务 */ addr_len = sizeof(server_addr); while (1) { client_fd = accept(l_server_fd, (struct sockaddr*)&server_addr, &addr_len); if (client_fd < 0) { perror("Accept failed"); continue; } if (l_child_process_count >= MAX_CHILD_PROCESS) { printf("Too many child process, rejecting connection.\n"); close(client_fd); continue; } pid = fork(); if (pid < 0) { perror("Fork failed.\n"); close(client_fd); } else if (pid > 0) /* 父进程 */ { close(client_fd); l_child_process_count++; } else { close(l_server_fd); task.cliend_fd = client_fd; handle_task(&task); } } return OPT_SUCCESS; } int main() { signal(SIGINT, handle_signal); /* 启动服务器 */ start_http_server(); return 0; } 分析代码问题并优化
08-10
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值