Windows下基于原始套接字的回射客户端的源码

SocketFrame.cpp:#include "StdAfx.h"#include "SocketFrame.h"#include "ws2tcpip.h"#include "mstcpip.h"CSocketFrame::CSocketFrame(void){}CSocketFrame::~CSocketFrame(void){}/*****************
摘要由CSDN通过智能技术生成

SocketFrame.cpp:

#include "StdAfx.h"
#include "SocketFrame.h"
#include "ws2tcpip.h"
#include "mstcpip.h"
CSocketFrame::CSocketFrame(void)
{
}

CSocketFrame::~CSocketFrame(void)
{
}
/********************************************************
函数名:set_address
输入参数:char * hname:主机名 or 点分十进制表示的IP地址
          char * sname:端口号
		  struct sockaddr_in * sap:以sockaddr_in结构存储的地址(输出参数)
          char * protocol:字符串形式描述的协议类型,如"tcp"
输出参数:0表示成功,1表示失败。
功能:根据给定的主机名或点分十进制表示的IP地址获得以sockaddr_in结构存储的地址
*********************************************************/
int CSocketFrame::set_address(char * hname, char * sname, struct sockaddr_in * sap, char * protocol)
{
	struct servent *sp;
	struct hostent *hp;
	char *endptr;
	unsigned short port;
	unsigned long ulAddr = INADDR_NONE;


    //对地址结构socketaddr_in初始化为0,并设置地址族为AF_INET
	memset( sap,0, sizeof( *sap ) );
	sap->sin_family = AF_INET;
	
	if ( hname != NULL )
	{
		//如果hname不为空,假定给出的hname为点分十进制表示的数字地址,转换地址为sockaddr_in类型
		ulAddr = inet_addr(hname);
		if ( ulAddr == INADDR_NONE || ulAddr == INADDR_ANY) {
			printf("inet_addr 函数调用错误,错误号: %d\n", WSAGetLastError());
			//调用错误,表明给出的是主机名,调用gethostbyname获得主机地址
			hp = gethostbyname( hname );
			if ( hp == NULL ) {
				printf("未知的主机名,错误号: %d\n", WSAGetLastError());
				return 1;
			}
			sap->sin_addr = *( struct in_addr * )hp->h_addr;
        }      
		else
			sap->sin_addr.S_un.S_addr=ulAddr;		
	}
	else
		//如果调用者没有指定一个主机名或地址,则设置地址为通配地址INADDR_ANY
		sap->sin_addr.s_addr = htonl( INADDR_ANY );
	//尝试转换sname为一个整数
	port = (unsigned short )strtol( sname, &endptr, 0 );
	if ( *endptr == '\0' )
	{
		//如果成功则转换为网络字节顺序
		sap->sin_port = htons( port );
	}
	else
	{
		//如果失败,则假定是一个服务名称,通过调用getservbyname获得端口号
		sp = getservbyname( sname, protocol );
		if ( sp == NULL ) {
			printf("未知的服务,错误号: %d\n", WSAGetLastError());
			return 1;
		}
		sap->sin_port = sp->s_port;
	}
	return 0;
}

/********************************************************
函数名:start_up
输入参数:无
输出参数:0:成功,1:失败
功能:初始化Windows Sockets DLL,协商版本号
*********************************************************/
int CSocketFrame::start_up(void)
{
	WORD wVersionRequested;
    WSADATA wsaData;
    int iResult;

    // 使用 MAKEWORD(lowbyte, highbyte) 宏,在Windef.h 中声明
    wVersionRequested = MAKEWORD(2, 2);

    iResult = WSAStartup(wVersionRequested, &wsaData);
    if (iResult != 0) {
        //告知用户无法找到合适可用的Winsock DLL
        printf("WSAStartup 函数调用错误,错误号: %d\n",  WSAGetLastError());
        return 1;
    }

    // 确认WinSock Dll支持版本2.2
    // 注意,如果DLL支持的版本比2.2更高,根据用户调用前的需求,仍然返回2.2版本号,存储于wsaData.wVersion

    if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
        // 告知用户无法找到可用的WinSock DLL.                              
        printf("无法找到可用的Winsock.dll版本\n");
        WSACleanup();
        return 1;
    }
    else
        printf("Winsock 2.2 dll成功找到\n");

	return 0;
}
/********************************************************
函数名:clean_up
输入参数:无
输出参数:0:成功,1:失败
功能:终止Windows Sockets DLL的使用,释放资源 
*********************************************************/
int CSocketFrame::clean_up(void)
{
	int iResult;
	iResult = WSACleanup();
    if (iResult == SOCKET_ERROR) {
        // WSACleanup调用失败                  
        printf("WSACleanup 函数调用错误,错误号: %d\n",  WSAGetLastError());
        return 1;
    }
	else
        printf("Winsock dll 释放成功\n");

	return 0;
}
/********************************************************
函数名:quit
输入参数:SOCKET s:服务器的连接套接字
输出参数:0:成功,1:失败
功能:关闭套接字,释放dll
*********************************************************/
int CSocketFrame::quit(SOCKET s)
{
    int iResult=0;
    iResult = closesocket(s);
    if (iResult == SOCKET_ERROR){
        printf("closesocket 函数调用错误,错误号:%d\n", WSAGetLastError());
        return 1;
    }
    iResult = clean_up();
    return iResult;
}
/********************************************************
函数名:tcp_server
输入参数:char * hname:服务器主机名 or 点分十进制表示的IP地址
          char * sname:服务端口号
输出参数:创建服务器端流式套接字并配置,0:表示失败
功能:创建流式套接字,根据用户输入的地址和端口号,绑定套接字的服务地址
      将其转换为监听状态
*********************************************************/
SOCKET CSocketFrame::tcp_server( char *hname, char *sname )
{
	sockaddr_in local;
	SOCKET ListenSocket;
	const int on = 1;
	int iResult = 0;

    //为服务器的本地地址local设置用户输入的IP和端口号
	if (set_address( hname, sname, &local, "tcp" ) ==1 )
		return 0;
	
	//创建套接字
	ListenSocket = socket( AF_INET, SOCK_STREAM, 0 );
	if (ListenSocket == INVALID_SOCKET) {
        printf("socket 函数调用错误,错误号: %ld\n", WSAGetLastError());
        clean_up();
        return 0;
    }

	//设置服务器地址可重用选项
	iResult = setsockopt( ListenSocket, SOL_SOCKET, SO_REUSEADDR, ( char * )&on, sizeof( on ));
	if ( iResult == SOC
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值