SOCKET设置的参数

SO_REUSEPORT
先讲TIME_WAIT的概念。
    主动关闭的Socket端会进入TIME_WAIT状态,并且持续2MSL时间长度,MSL就是maximum segment lifetime(最大分节生命期),这是一个IP数据包能在互联网上生存的最长时间,超过这个时间将在网络中消失。MSL在RFC 1122上建议是2分钟,而源自berkeley的TCP实现传统上使用30秒,因而,TIME_WAIT状态一般维持在1-4分钟。
    TIME_WAIT状态存在的理由:
1)可靠地实现TCP全双工连接的终止
    在进行关闭连接四路握手协议时,最后的ACK是由主动关闭端发出的,如果这个最终的ACK丢失,服务器将重发最终的FIN,因此客户端必须维护状态信息允许它重发最终的ACK。如果不维持这个状态信息,那么客户端将响应RST分节,服务器将此分节解释成一个错误(在java中会抛出connection reset的SocketException)。因而,要实现TCP全双工连接的正常终止,必须处理终止序列四个分节中任何一个分节的丢失情况,主动关闭的客户端必须维持状态信息进入TIME_WAIT状态。

2)允许老的重复分节在网络中消逝 
    TCP分节可能由于路由器异常而“迷途”,在迷途期间,TCP发送端可能因确认超时而重发这个分节,迷途的分节在路由器修复后也会被送到最终目的地,这个原来的迷途分节就称为lost duplicate。在关闭一个TCP连接后,马上又重新建立起一个相同的IP地址和端口之间的TCP连接,后一个连接被称为前一个连接的化身(incarnation),那么有可能出现这种情况,前一个连接的迷途重复分组在前一个连接终止后出现,从而被误解成从属于新的化身。为了避免这个情况,TCP不允许处于TIME_WAIT状态的连接启动一个新的化身,因为TIME_WAIT状态持续2MSL,就可以保证当成功建立一个TCP连接的时候,来自连接先前化身的重复分组已经在网络中消逝。
    新的SCTP协议通过在消息头部添加验证标志避免了TIME_WAIT状态。

SO_REUSEADDR可以用在以下四种情况下。
    (摘自《Unix网络编程》卷一,即UNPv1)
    1、当有一个有相同本地地址和端口的socket1处于TIME_WAIT状态时,而你启动的程序的socket2要占用该地址和端口,你的程序就要用到该选项。
    2、SO_REUSEADDR允许同一port上启动同一服务器的多个实例(多个进程)。但每个实例绑定的IP地址是不能相同的。在有多块网卡或用IP Alias技术的机器可以测试这种情况。
    3、SO_REUSEADDR允许单个进程绑定相同的端口到多个socket上,但每个socket绑定的ip地址不同。这和2很相似,区别请看UNPv1。
    4、SO_REUSEADDR允许完全相同的地址和端口的重复绑定。但这只用于UDP的多播,不用于TCP。

SO_BROADCAST

设置成广播,例子如下:

//发送端程序

#include <stdio.h>

#include <winsock.h>

int main(int argc, char* argv[])

{

    WSADATA wsaData;          //指向WinSocket信息结构的指针

    SOCKET sockListener;

    SOCKADDR_IN sin,saUdpServ;

    BOOL fBroadcast = TRUE;

    char sendBuff[1024];

    int nSize;

    int ncount=0;

    if(WSAStartup(MAKEWORD( 1, 1 ), &wsaData )!=0)//进行WinSocket的初始化

    {

        printf("Can't initiates windows socket!Program stop.\n");//初始化失败返回-1

        return -1;

    }

    sockListener=socket(PF_INET,SOCK_DGRAM,0);

    setsockopt ( sockListener,SOL_SOCKET,SO_BROADCAST,

        (CHAR *)&fBroadcast,sizeof ( BOOL ));

    sin.sin_family = AF_INET;

    sin.sin_port = htons(0);

    sin.sin_addr.s_addr = htonl(INADDR_ANY);

    if(bind( sockListener, (SOCKADDR *)&sin, sizeof(sin))!=0)

    {

        printf("Can't bind socket to local port!Program stop.\n");//初始化失败返回-1

        return -1;

    }

    saUdpServ.sin_family = AF_INET;

    saUdpServ.sin_addr.s_addr = htonl ( INADDR_BROADCAST );

    saUdpServ.sin_port = htons (7001);//发送用的端口,可以根据需要更改

    nSize = sizeof ( SOCKADDR_IN );

    while(1)

    {

        sprintf(sendBuff,"Message %d",ncount++);

        sendto ( sockListener,sendBuff,lstrlen (sendBuff),0,(SOCKADDR *) &saUdpServ,sizeof ( SOCKADDR_IN )); printf("%s\n",sendBuff);

    }

return 0;

}

/

//接收

#include <stdio.h>

#include <winsock.h>

#include <conio.h>

int main(int argc, char* argv[])

{

    WSADATA wsaData; SOCKET sockListener;SOCKADDR_IN sin,saClient;char cRecvBuff[1024];int nSize,nbSize;int iAddrLen=sizeof(saClient);

    if(WSAStartup(MAKEWORD( 1, 1 ), &wsaData )!=0)//进行WinSocket的初始化

    {

        printf("Can't initiates windows socket!Program stop.\n");return -1;

    }

    sockListener=socket(AF_INET, SOCK_DGRAM,0);sin.sin_family = AF_INET;  sin.sin_port = htons(7001);//发送端使用的发送端口,可以根据需要更改

    sin.sin_addr.s_addr = htonl(INADDR_ANY);

    if(bind( sockListener, (SOCKADDR FAR *)&sin, sizeof(sin))!=0)

    {

        printf("Can't bind socket to local port!Program stop.\n");  return -1;

    }

    while(1)

    {

        nSize = sizeof ( SOCKADDR_IN );

        if((nbSize=recvfrom (sockListener,cRecvBuff,1024,0,(SOCKADDR FAR *) &saClient,&nSize))==SOCKET_ERROR)

        {

            printf("Recive Error");break;

        }

        cRecvBuff[nbSize] = '\0';   printf("%s\n",cRecvBuff);

    }

    return 0;

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山西茄子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值