winsock学习笔记(三)

PS:这几篇学习笔记都是在windows dev center上学习的东西,大部分是翻译。传送门:http://msdn.microsoft.com/en-us/library/windows/desktop/ms738545(v=vs.85).aspx#winsock.advanced_winsock_samples


服务端:
  • Initialize Winsock.(初始化winsock)
  • Create a socket.(创建套接字)
  • Bind the socket.(绑定套接字)
  • Listen on the socket for a client.(监听套接字,等待客户端连接)
  • Accept a connection from a client.(接受客户端连接)
  • Receive and send data.(接受和发送数据或消息)
  • Disconnect.(断开连接)
1、Create a socket:

#define DEFAULT_PORT "27015"

struct addrinfo *result = NULL, *ptr = NULL, hints;

ZeroMemory(&hints, sizeof (hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;

// Resolve the local address and port to be used by the server
iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
if (iResult != 0) {
    printf("getaddrinfo failed: %d\n", iResult);
    WSACleanup();
    return 1;
}
SOCKET ListenSocket = INVALID_SOCKET;
 
   
// Create a SOCKET for the server to listen for client connections

ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
 
   
if (ListenSocket == INVALID_SOCKET) {
    printf("Error at socket(): %ld\n", WSAGetLastError());
    freeaddrinfo(result);
    WSACleanup();
    return 1;
}

**代码基本跟创建客户端socket的时候一样,唯一值得注意的是,hints.ai_flags设置为AI_PASSIVE,当这个位被置位时候,通常在getaddrinfo函数中的第一个参数,也即是地址名设置为NULL,这样就会返回一个通配地址。网上也有资料说系统会将主机自己的地址填充进去。像我自己这样测试之后打印出来是0.0.0.0。
**这里要拓展一下,返回的result结构中一个属性是sockaddr*结构指针类型的ai_addr。它包含了两个属性,一个是AF_Family,一个是14个字节的char数组,填充了使用网络字节顺序的地址和端口号。sockaddr的类型随着AF_Family的值而变,当其值为AF_INET使,可用sockaddr_in结构强制转换。然后可以通过两个函数inet_ntoa((sockaddr_in*)ai_addr->sin_addr)和ntohs((sockaddr_in*)ai_addr->sin_port)将网络字节顺序的数据转化为机器字节顺序的输出。一般来说,编程的时候我们不使用sockaddr结构,这个是给操作系统用的。做法是使用sockaddr_in对我们使用的信息进行填充,然后强制转化为sockaddr结构,当做参数传入bind,accept等函数。


2、 Bind a socket:
C++:
// Setup the TCP listening socket
    iResult = bind( ListenSocket, result->ai_addr, (int)result->ai_addrlen);
    if (iResult == SOCKET_ERROR) {
        printf("bind failed with error: %d\n", WSAGetLastError());
        freeaddrinfo(result);
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }

对于服务端socket来说,必须将地址和端口号和你的socket绑定起来,才能进行下一步的对其进行监听。由于绑定之后,由getaddrinfo所返回的result结构我们不再需要,所以可以用freeaddrinfo释放对应的资源。


3、 Listen to a socket:
C++:
if ( listen( ListenSocket, SOMAXCONN ) == SOCKET_ERROR ) {
    printf( "Listen failed with error: %ld\n", WSAGetLastError() );
    closesocket(ListenSocket);
    WSACleanup();
    return 1;
}

Listen函数的第二个参数比较值得研究,它是表示还没连接的在缓冲池中的客户端数。具体的情况可以看看网上一篇博客上的分析,写的很好。传送门:http://blog.csdn.net/ordeder/article/details/21551567  有时候这个参数设置得很小但是客户端连接依旧没有问题,这是因为操作系统从缓冲池中取出然后处理的时间太短,所以很少出现同时几个客户端都在连接的情况。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值