支持组通信的socket包装
Risun 2004-06-18
这几天在看IP组播,WinSock2虽然支持组播,但是没有提供独立的socket,编程非常不便,花了半下午的时间,学习了winsock2支持组播的部分api,包装了一个MulticastSocket类,可直接用于组播,尚未在多台及机器上测试。
源码如下:
MulticastSocket.h:
//=================================================================
/* MulticastSocket.h
* MulticastSocket: send and receive data gram to and from a group
* though the same port
* Risun
* yzy9508@hotmail.com
* 2004-06-18
*/
//=================================================================
#ifndef MULTICASTSOCKET_H_
#define MULTICASTSOCKET_H_
#include <winsock2.h>
class MulticastSocket
{
private:
SOCKADDR_IN my_addr;
SOCKADDR_IN group_addr;
SOCKET socket;
public:
int create( int port );
int close();
int joinGroup( char group[] );
int send( const char *out_buf, const int &buf_len, int *send_len);
int receive( char *in_buf, const int &buf_len, int *rec_len );
};
#endif //MULTICASTSOCKET_H_
MulticastSocket.cpp
#include "MulticastSocket.h"
#include <stdio.h>
#define traceWSAErr(fun_name) printf ("in function: %s , Err: %d\n", fun_name, WSAGetLastError())
int MulticastSocket::create( int port )
{
int ret;
DWORD cbRet;
socket = WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP,
(LPWSAPROTOCOL_INFO)NULL, 0, WSA_FLAG_OVERLAPPED
| WSA_FLAG_MULTIPOINT_C_LEAF | WSA_FLAG_MULTIPOINT_D_LEAF);
if ( socket == INVALID_SOCKET ) {
traceWSAErr("MulticastSocket::create");
return SOCKET_ERROR;
}
// 设置套接字为可重用端口地址
bool bFlag = TRUE;
ret = setsockopt(socket, /* socket */
SOL_SOCKET, /* socket level */
SO_REUSEADDR, /* socket option */
(char *)&bFlag, /* option value */
sizeof (bFlag)); /* size of value */
if ( ret == SOCKET_ERROR )
{
traceWSAErr("MulticastSocket::create");
return ret;
}
// 将套接字绑扎到用户指定端口及默认的接口
my_addr.sin_family = PF_INET;
my_addr.sin_port = htons( port );
my_addr.sin_addr.s_addr = INADDR_ANY;
ret = bind( socket, (struct sockaddr FAR *)&my_addr, sizeof(struct sockaddr) );
if ( ret == SOCKET_ERROR )
{
traceWSAErr("MulticastSocket::create");
return ret;
}
// 设置多址广播数据报传播范围(TTL)
int nIP_TTL = 1; // 在本子网中传播。如果要跨路由器,则路由器必须支持IGMP协议
ret = WSAIoctl ( socket, /* socket */
SIO_MULTICAST_SCOPE, /* IP Time-To-Live */
&nIP_TTL, /* input */
sizeof (nIP_TTL), /* size */
NULL, /* output */
0, /* size */
&cbRet, /* bytes returned */
NULL, /* overlapped */
NULL ); /* completion routine */
if ( ret == SOCKET_ERROR )
{
traceWSAErr("MulticastSocket::create");
return ret;
}
// 允许内部回送(LOOPBACK)。Windows 95不支持改选项
bFlag = TRUE;
ret = WSAIoctl ( socket, /* socket */
SIO_MULTIPOINT_LOOPBACK, /* LoopBack on or off */
&bFlag, /* input */
sizeof (bFlag), /* size */
NULL, /* output */
0, /* size */
&cbRet, /* bytes returned */
NULL, /* overlapped */
NULL); /* completion routine */
if ( ret == SOCKET_ERROR )
{
traceWSAErr("MulticastSocket::create");
return ret;
}
return 0;
}
int MulticastSocket::close()
{
if ( socket == INVALID_SOCKET )
closesocket( socket );
return 0;
}
int MulticastSocket::joinGroup( char group[] )
{
int ret = 0;
int len;
len = sizeof( group_addr );
ret = WSAStringToAddress ( group, /* address string */
AF_INET, /* address family */
NULL, /* protocol info structure */
(LPSOCKADDR)&group_addr, /* socket address string */
&len); /* length of socket structure */
group_addr.sin_port = my_addr.sin_port;
if ( ret == SOCKET_ERROR )
{
traceWSAErr("MulticastSocket::joinGroup");
return ret;
}
// 加入到指定多址广播组,指定为既作发送者又作接收者
// 在IP multicast中,返回的套接字描述符和输入的套接字描述符相同。
SOCKET new_socket;
new_socket = WSAJoinLeaf ( socket, /* socket */
(PSOCKADDR)&group_addr, /* multicast address */
sizeof (group_addr), /* length of addr struct */
NULL, /* caller data buffer */
NULL, /* callee data buffer */
NULL, /* socket QOS setting */
NULL, /* socket group QOS */
JL_BOTH); /* do both: send *and* receive */
if ( new_socket == INVALID_SOCKET )
{
traceWSAErr("MulticastSocket::joinGroup");
return ret;
}
//closesocket( new_socket );
return ret;
}
int MulticastSocket::send( const char *out_buf, const int &buf_len, int *send_len )
{
int ret = 0;
DWORD cb_ret;
WSABUF wsa_buf;
wsa_buf.len = buf_len;
wsa_buf.buf = const_cast<char *>( out_buf );
ret = WSASendTo ( socket, /* socket */
&wsa_buf, /* output buffer structure */
1, /* buffer count */
&cb_ret, /* number of bytes sent */
0, /* flags */
(struct sockaddr*)&group_addr, /* destination address */
sizeof(struct sockaddr), /* size of addr structure */
NULL, /* overlapped structure */
NULL); /* overlapped callback function */
if ( ret == SOCKET_ERROR )
{
traceWSAErr("MulticastSocket::send");
return ret;
}
*send_len = cb_ret;
return 0;
}
int MulticastSocket::receive( char *in_buf, const int &buf_len, int *dat_len )
{
int ret = 0;
DWORD cb_ret, dFlag;
WSABUF wsa_buf;
wsa_buf.len = buf_len;
wsa_buf.buf = in_buf;
dFlag = 0;
int addr_len = sizeof(my_addr);
ret = WSARecvFrom ( socket, /* socket */
&wsa_buf, /* input buffer structure */
1, /* buffer count */
&cb_ret, /* number of bytes recv'd */
&dFlag, /* flags */
(struct sockaddr *)& my_addr, /* source address */
&addr_len, /* size of addr structure */
NULL, /* overlapped structure */
NULL); /* overlapped callback function */
if ( ret == SOCKET_ERROR )
{
traceWSAErr("MulticastSocket::receive");
return ret;
}
* dat_len = cb_ret;
return 0;
}
posted on 2004-06-18 16:48 哲学 艺术 程序 人生 阅读(710) 评论(0) 编辑 收藏 举报