windows网络编程socket选项与广播的实现

3/8/2017来源:ASP.NET技巧人气:2873

调用getsockopt和setsocketopt可以查看和设置socket中的一些选项,比如socket是否处于监听状态,是否允许广播,是否允许路由选择等等。 1.getsockopt() int getsockopt(SOCKET s,int level,int optname, char* optval, int* optlen) s:要查看的套接字 level:选项的级别,有SOL_SOCKET,ipPROTO_TCP等 optname是要查看的选项的名称 optval接受查看选项的结果 optlen optval的长度 比如以下例子,在listen监听之前分别查看套接字的监听情况(optname=SO_ACCEPTCONN)
// test.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <stdio.h>
#include "winsock2.h"
#include <stdlib.h>

#pragma comment(lib,"ws2_32.lib")

int main()
{
	WSADATA wsa;
	if (WSAStartup(MAKEWord(2, 2), &wsa) != NO_ERROR)
	{
		printf("startup failed\n");
	}
	SOCKET listensocket;
	sockaddr_in server;
	int retval, optlen;
	if ((listensocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
	{
		printf("socket error\n");
	}
	hostent *phost;
	u_short port = 9901;
	server.sin_family = AF_INET;
	server.sin_port = htons(port);
	server.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
	if (bind(listensocket, (sockaddr*)&server, sizeof(sockaddr)) == SOCKET_ERROR)
	{
		printf("%d",GetLastError());
		printf("bind error\n");
	}
	optlen = sizeof(int);
	getsockopt(listensocket, SOL_SOCKET, SO_ACCEPTCONN, (char*)&retval, &optlen);
	printf("%ld\n", retval);
	if (listen(listensocket, 3) == SOCKET_ERROR)
	{
		printf("listen error\n");
	}
	getsockopt(listensocket, SOL_SOCKET, SO_ACCEPTCONN, (char*)&retval, &optlen);
	printf("%ld\n", retval);
	return 0;
}







执行结果如下:
监听之前为0,监听之后为1




2.setsockopt(SOCKET s,int level,int optname, const char* optval, int* optlen)
五个参数的意义和getsockopt的意义很相近,只是第3个参数在这里表示要被设置的选项,第四个参数表示要设置的值,需要强制转换为字符指针。
当我们需要实现UDP广播的时候,需要将socket设置为允许广播,即
bool setopt = true;
retval = setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char*)&setopt, sizeof(bool));然后将目的IP地址设为INADDR_BOARDCAST就行了。
完整代码如下:
// test.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <stdio.h>
#include "winsock2.h"
#include <stdlib.h>

#pragma comment(lib,"ws2_32.lib")

int main()
{
	WSADATA wsa;
	int retval = WSAStartup(MAKEWORD(2, 2), &wsa);
	if (retval == SOCKET_ERROR)
	{
		printf("start up failed\n");
	}
	SOCKET s;
	s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	if (s == INVALID_SOCKET)
	{
		printf("socket failed\n");
	}
	bool setopt = true;
	retval = setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char*)&setopt, sizeof(bool));
	if (retval == SOCKET_ERROR)
	{
		printf("setsocketopt failed\n");
	}
	sockaddr_in fromaddr;
	fromaddr.sin_family = AF_INET;
	fromaddr.sin_port = htons(9000);
	fromaddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
	retval = bind(s, (sockaddr*)&fromaddr, sizeof(sockaddr));
	if (retval == SOCKET_ERROR)
	{
		printf("bind failed\n");
	}
	sockaddr_in toaddr;
	toaddr.sin_family = AF_INET;
	toaddr.sin_port = htons(9001);
	toaddr.sin_addr.S_un.S_addr = htonl(INADDR_BROADCAST);
	char buf[] = { "this is a boardcast" };
	retval = sendto(s, buf, sizeof(buf), 0, (sockaddr*)&toaddr, sizeof(toaddr));
	if (retval == SOCKET_ERROR)
	{
		printf("sendto failed\n");
	}
	WSACleanup();
	closesocket(s);
	return 0;
}