当我们使用socket通信时,有时需要关闭服务器,再重新开启
需要绑定的是同一个端口号
那么问题来了:当迅速关闭再重新创建socket之后bind会出错
根据网上资料,socket关闭后释放端口号需要一段延时
解决办法:采用socket端口复用的选项
if((pTsCfg->server_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
TS_DBG("socket failed\n");
return CS_E_ERROR;
}
<strong> rc = setsockopt(pTsCfg->server_fd, SOL_SOCKET, SO_REUSEADDR,&on, sizeof(on));
if(rc<0)
{
close(pTsCfg->server_fd);
printf("set socket opt error\n");
return CS_E_ERROR;
}</strong>
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(pTerm_serv_cfg->proto_port);
ret = bind(pTsCfg->server_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
if(ret < 0){
TS_DBG("bind failed, ret %d, uart[%d], server fd %d, port %d,\n", ret,
pTerm_serv_cfg->uart_cfg.uart_id, pTsCfg->server_fd, serv_addr.sin_port);
ts_server_fd_close(pTsCfg);
return CS_E_ERROR;
}
/* only accept one client */
if(listen(pTsCfg->server_fd, 5) < 0){
close(pTsCfg->server_fd);
pTsCfg->server_fd = -1;
TS_DBG("listen failed\n");
return CS_E_ERROR;
}
解释:
#include <sys/socket.h>
int setsockopt( int socket, int level, int option_name,
const void *option_value, size_t option_len);
第一个参数socket是套接字描述符。第二个参数level是被设置的选项的级别,如果想要在套接字级别上设置选项,就必须把level设置为 SOL_SOCKET 。 option_name指定准备设置的选项,option_name可以有哪些取值,这取决于level,以linux 2.6内核为例(在不同的平台上,这种关系可能会有不同),在套接字级别上( SOL_SOCKET )SO_DEBUG,打开或关闭调试信息。
-
当option_value不等于0时,打开调试信息,否则,关闭调试信息。它实际所做的工作是在sock->sk->sk_flag中置 SOCK_DBG(第10)位,或清SOCK_DBG位。
- SO_REUSEADDR,打开或关闭地址复用功能。
当option_value不等于0时,打开,否则,关闭。它实际所做的工作是置sock->sk->sk_reuse为1或0。
- SO_DONTROUTE,打开或关闭路由查找功能。
当option_value不等于0时,打开,否则,关闭。它实际所做的工作是在sock->sk->sk_flag中置或清 SOCK_LOCALROUTE位。
- SO_BROADCAST,允许或禁止发送广播数据。
当option_value不等于0时,允许,否则,禁止。它实际所做的工作是在sock->sk->sk_flag中置或清 SOCK_BROADCAST位。
- SO_SNDBUF,设置发送缓冲区的大小。
发送缓冲区的大小是有上下限的,其上限为256 * (sizeof(struct sk_buff) + 256),下限为2048字节。该操作将sock->sk->sk_sndbuf设置为val * 2,之所以要乘以2,是防
止大数据量的发送,突然导致缓冲区溢出。最后,该操作完成后,因为对发送缓冲的大小 作了改变,要检查sleep队列,如果有进程正在等待写,将它们唤醒。
- SO_RCVBUF,设置接收缓冲区的大小。
接收缓冲区大小的上下限分别是:256 * (sizeof(struct sk_buff) + 256)和256字节。该操作将sock->sk->sk_rcvbuf设置为val * 2。
- SO_KEEPALIVE,套接字保活。
如果协议是TCP,并且当前的套接字状态不是侦听(listen)或关闭(close),那么,当option_value不是零时,启用TCP保活定时 器,否则关闭保活定时器。对于所有协议,该操
作都会根据option_value置或清 sock->sk->sk_flag中的 SOCK_KEEPOPEN位。