linux下socket常见问题整理

1. socket不能立即关闭的问题

每次修改了源代码并再次编译运行时,常遇到下面的错误:

Cann't bind server socket !
Address already in use

解决方法为使用setsockopt函数设置SO_REUSEADDR,示例代码如下:

int reuse = 0;
struct sockaddr_in cliaddr, servaddr;
listenfd = socket(PF_INET, SOCK_STREAM,0);
if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
{
    perror("setsockopet error\n");
    return -1;
}

2. 关于tcp客户端非正常掉线的问题

开启探测属性,在一段时间内没有数据往来,则发送探测包,若探测包收得不到响应,则重发一定次数,若还未得到响应则认为链路断开,示例代码如下:

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/tcp.h>

int keepAlive = 1; // 开启keepalive属性
int keepIdle = 60; // 如该连接在60秒内没有任何数据往来,则进行探测 
int keepInterval = 5; // 探测时发包的时间间隔为5 秒
int keepCount = 3; // 探测尝试的次数.如果第1次探测包就收到响应了,则后2次的不再发.

setsockopt(rs, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepAlive, sizeof(keepAlive));
setsockopt(rs, SOL_TCP, TCP_KEEPIDLE, (void*)&keepIdle, sizeof(keepIdle));
setsockopt(rs, SOL_TCP, TCP_KEEPINTVL, (void *)&keepInterval, sizeof(keepInterval));
setsockopt(rs, SOL_TCP, TCP_KEEPCNT, (void *)&keepCount, sizeof(keepCount));
ioctl(s, FIONBIO, &non_blocking);/*设置非堵塞*/

3. socket客户端关闭检测

方式1:当使用 select()函数测试一个socket是否可读时,如果select()函数返回值为1,且使用recv()函数读取的数据长度为0 时,就说明该socket已经断开,示例代码:

if(FD_ISSET(net->desfd,&tempset)) {
    char recvbuf[1024] = {0};
    int ret = read(net->desfd, recvbuf, 1024);
    if (ret == -1)
        ERR_EXIT("readline error");
    else if (ret == 0) { //客户端关闭
        printf("client %d close \n",net->desfd);
        FD_CLR(net->desfd, &mset);
        client[i] = -1;
        close(net->desfd);
    }
}

方式2:用getsockopt来判断,示例代码:

#include <linux/types.h>
#include <asm/byteorder.h>
#include <linux/config.h>
#include <linux/skbuff.h>
#include <linux/ip.h>
#include <net/sock.h>

int SocketConnected(int sock)
{
    if (sock <= 0)
        return 0;
    struct tcp_info info;
    int len = sizeof(info);
    getsockopt(sock, IPPROTO_TCP, TCP_INFO, &info, (socklen_t *) & len);
    if ((info.tcpi_state == TCP_ESTABLISHED)) {
        //myprintf("socket connected\n"); 
        return 1;
    } else {
        //myprintf("socket disconnected\n"); 
        return 0;
    }
}

4. 关于指定客户端ip的问题

对于服务器来说,设置指定ip地址的访问,主要是通过accept函数返回的客户端的ip和端口号来判断,若不是所设定的则进行关闭操作。

客户端在连接时,也可指定自己的ip地址(同服务器),在connet连接之前通过bind绑定。

cln->srcaddr.sin_family = AF_INET;
cln->srcaddr.sin_port = htons(5555);
cln->srcaddr.sin_addr.s_addr = inet_addr("192.166.0.222");
bind(cln->srcfd, (struct sockaddr *)&(cln->srcaddr), sizeof(cln->srcaddr))

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值