jackhkyin 2022-12-01 10:36 采纳率: 100%
浏览 103
已结题

用socket实现ping遇到的问题

最近在学习socket网络编程,网上找到一段代码。但运行时报10040错误,查询错误代码显示是缓存不够但我设置的数据缓存是很大的一个值,不可能是数据缓冲不够。有懂socket的朋友帮我看看代码哪里有问题,另外原代码是通过IP来ping 如果改成域名的话需要改哪里

img

#include<stdio.h>
#include<stdlib.h>
#include<winsock2.h>
#include<winsock.h>
#pragma comment(lib,"ws2_32.lib")
#pragma warning( disable : 4996)

//常量定义
const int MAX_ICMP_PACKET_SIZE = 204800;               //ICMP报文最大长度(包括报头)
const int DEF_ICMP_DATA_SIZE = 131072;                 //ICMP报文默认数据字段长度
const int ICMP_ECHO_REQUEST = 8;                       //ICMP类型字段,8表示请求回显

//ICMP的报头格式
typedef struct SIcmpHdr 
{
    BYTE bType;                                        //ICMP类型码
    BYTE bCode;                                        //子类型码
    USHORT sCksum;                                     //校验和
    USHORT sId;                                        //ICMP数据报的ID号
    USHORT sSeq;                                       //ICMP数据报的序列号
    ULONG lTimeStamp;                                  //可选数据部分
} 
SICMPHDR, * LPSICMPHDR;

//IP报头格式
typedef struct SIpHdr 
{
    unsigned char cHdrLen;                             //4位头部长度
    unsigned char cVersion;                            //4位版本号
    unsigned char cTos;                                //8位服务类型
    unsigned short sTotalLen;                          //16位总长度
    unsigned short sIdentifier;                        //16位标示符
    unsigned short sFragAndFlags;                      //3位标志加13位片偏移
    unsigned char cTTL;                                //8位生存时间
    unsigned char cProtocol;                           //8位上层协议号
    unsigned short sCheckSum;                          //16位校验和
    unsigned long lSrcIp;                              //32位源IP地址
    unsigned long lDstIp;                              //32位目的IP地址
} 
SIPHDR, * LPSIPHDR;

//计算校验和函数
USHORT CheckSum(USHORT* pBuf, int iSize)
{
    unsigned long cksum = 0;
    while (iSize > 1) {
        cksum += *pBuf++;
        iSize -= sizeof(USHORT);
    }
    if (iSize)
        cksum += *(UCHAR*)pBuf;
    cksum = (cksum >> 16) + (cksum & 0xffff);
    cksum += (cksum >> 16);
    return (USHORT)(~cksum);
}

void Ping(char* lpszHostAddr)
{
    //初始化
    WSADATA stWSA; WSAStartup(MAKEWORD(2, 2), &stWSA);
    SOCKET hRawSock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);//创建原始套接字
    if (hRawSock == INVALID_SOCKET) {
        printf("创建原始套接字失败(ErrorCode : %d)\n", WSAGetLastError());
        system("PAUSE");
        return;
    }

    //设置socket的超时机制
    int iTimeout = 1000;//设置延时为1秒
    int iRet = setsockopt(hRawSock, SOL_SOCKET, SO_RCVTIMEO, (char*)&iTimeout, sizeof(iTimeout));
    if (iRet == SOCKET_ERROR) {
        printf("设置延时失败(ErrorCode : %d)\n", WSAGetLastError());
        system("PAUSE");
        return;
    }

    //填充数据报
    char szBuff[MAX_ICMP_PACKET_SIZE];
    memset(szBuff, 0, MAX_ICMP_PACKET_SIZE);
    int iDatSize = DEF_ICMP_DATA_SIZE;
    iDatSize += sizeof(SICMPHDR);
    ((LPSICMPHDR)szBuff)->bType = ICMP_ECHO_REQUEST;//设置类型信息
    ((LPSICMPHDR)szBuff)->sId = (USHORT)GetCurrentThreadId();//设置ID号为当前线程号
    memset(szBuff + sizeof(SICMPHDR), 'E', iDatSize - sizeof(SICMPHDR));//在ICMP数据部分填入数据
    ((LPSICMPHDR)szBuff)->sCksum = 0;
    ((LPSICMPHDR)szBuff)->lTimeStamp = GetTickCount();
    ((LPSICMPHDR)szBuff)->sSeq = 0;
    ((LPSICMPHDR)szBuff)->sCksum = CheckSum((USHORT*)szBuff, iDatSize);

    //发送数据报文
    sockaddr_in saDst; saDst.sin_family = AF_INET; saDst.sin_addr.s_addr = inet_addr(lpszHostAddr);
    int iSend = sendto(hRawSock, szBuff, iDatSize, 0, (struct sockaddr*)&saDst, sizeof(saDst));
    if (iSend == SOCKET_ERROR || iSend < iDatSize) {
        printf("发送失败(ErrorCode : %d)\n", WSAGetLastError());
        system("PAUSE");
        return;
    }

    //接收回应报文
    sockaddr_in saFrom;
    int iSaLen = sizeof(saFrom);
    memset(szBuff, 0, MAX_ICMP_PACKET_SIZE);
    int iRecv = recvfrom(hRawSock, szBuff, MAX_ICMP_PACKET_SIZE, 0, (struct sockaddr*)&saFrom, &iSaLen);
    if (iRecv <= 0) {
        printf("接收回应报文失败(ErrorCode : %d)\n", WSAGetLastError());
        system("PAUSE");
        return;
    }

    LPSIPHDR lpIp = (LPSIPHDR)szBuff;
    unsigned short iIpHdr = lpIp->cHdrLen * 4;//IP报头的长度
    LPSICMPHDR lpIcmp = (LPSICMPHDR)(szBuff + iIpHdr);
    //判断是否是目的端发回的消息
    if (lpIcmp->sId == (USHORT)GetCurrentThreadId())            return;
    printf("Ping %s successfully !\n", inet_ntoa(saFrom.sin_addr));
    closesocket(hRawSock);//关闭套接字
    system("PAUSE");
    return;
}

void main()

{
    Ping((char*)("192.168.0.1"));
}

  • 写回答

4条回答

      报告相同问题?

      相关推荐 更多相似问题

      问题事件

      • 系统已结题 12月9日
      • 已采纳回答 12月1日
      • 修改了问题 12月1日
      • 创建了问题 12月1日

      悬赏问题

      • ¥15 求一个超难的动态新增元素的 click 事件无效的解决办法。
      • ¥20 怎么修改mediawiki允许上传的文件大小?
      • ¥15 agrySEXPAYm 是毒吗
      • ¥50 Java实现注册登录实现数据库增删改查功能,数据库至少两个表
      • ¥20 求解R语言的数据分析问题
      • ¥20 求GD32F105和305解除读保护方法教程
      • ¥15 C++代码优化,复杂度太高,无法通过clang-tidy检查,用什么办法可以优=化
      • ¥15 关于跨链隐私保护方案
      • ¥15 node mongodb 根据id给子集合list添加对象 请问应该如何操作
      • ¥50 如何得到路径下的绝对路径并且回传到list上