討論區快速選單
知識庫快速選單
軟體開發過程中有哪些資安漏洞? 政府補助!學嵌入式+物聯網
[ 回上頁 ] [ 討論區發言規則 ]
broadcast 4Byte hex data
更改我的閱讀文章字型大小
作者 : allen680321(思思烤烤)
[ 貼文 16 | 人氣 0 | 評價 20 | 評價/貼文 1.25 | 送出評價 2 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2014/1/14 下午 02:32:38
先上程式片段

char sbuf[1024];
memset(sbuf,0,1024);
signed char data[]={0xaa,0x00,0x00,0xbb};
sprintf_s(sbuf,"%s \r\n",data);

//sizeof char=1
printf("sizeof char=%d\n",sizeof(char));

//sbuf data: 0xffffffaa,0xd,0xa,0x0
printf("sbuf data:0x%x,0x%x,0x%x,0x%x\n",sbuf[0],sbuf[1],sbuf[2],sbuf[3]);

//sizeof sbuf data=1024
printf("sizeof sbuf data=%d\n",sizeof(sbuf));

//sbuf data len =3
printf("sbuf data len = %d\n",strlen(sbuf));

int ret = sendto(s, sbuf, strlen(sbuf), 0, (sockaddr*)&brdcastaddr, len);

我是想broadcast一段4Byte的hex資料,只是廣播會成功,但如上面片段程式所描
述的,我printf出來的資料和我塞進去的並不一樣,不論是內容或者長度都不一致,
當然最終發送出去的也就是錯誤的資料了。
小弟在VC++的經驗還蠻菜的、希望各位先進可以指教一下,謝 謝。
作者 : ozzy123(ozzy) VC++優秀好手資訊類作業求救卓越專家C++卓越專家貼文超過4000則人氣指數超過30000點
[ 貼文 4498 | 人氣 37262 | 評價 11100 | 評價/貼文 2.47 | 送出評價 49 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2014/1/14 下午 05:53:39

>先上程式片段
>
>char sbuf[1024];
 --- declare an array sbuf and its type is character and owns 1024 elements.
>memset(sbuf,0,1024);
 --- initialize 1024 elements to zero
>signed char data[]={0xaa,0x00,0x00,0xbb};
--- declare & initialize an array data , 1st element's value is 0xaa , 2nd one's 0x00 , 3rd one is 0x00 , last one is 0xbb
>sprintf_s(sbuf,'%s \r',data);
> ?? sprintf_s is a string manipulation function . if you want to assign data to sbuf , you should use a safe function , http://msdn.microsoft.com/en-us/library/wes2t00f%28VS.80%29.aspx
>//sizeof char=1
>printf('sizeof char=%d
',sizeof(char));
>
>//sbuf data: 0xffffffaa,0xd,0xa,0x0
>printf('sbuf data:0x%x,0x%x,0x%x,0x%x
',sbuf[0],sbuf[1],sbuf[2],sbuf[3]);
>
>//sizeof sbuf data=1024
>printf('sizeof sbuf data=%d
',sizeof(sbuf));
>
>//sbuf data len =3
>printf('sbuf data len = %d
',strlen(sbuf));
>
>int ret = sendto(s, sbuf, strlen(sbuf), 0, (sockaddr*)&brdcastaddr, len);
>
>我是想broadcast一段4Byte的hex資料,只是廣播會成功,但如上面片段程式所描
>述的,我printf出來的資料和我塞進去的並不一樣,不論是內容或者長度都不一致,
>當然最終發送出去的也就是錯誤的資料了。
>小弟在VC++的經驗還蠻菜的、希望各位先進可以指教一下,謝 謝。
作者 : ozzy123(ozzy) VC++優秀好手資訊類作業求救卓越專家C++卓越專家貼文超過4000則人氣指數超過30000點
[ 貼文 4498 | 人氣 37262 | 評價 11100 | 評價/貼文 2.47 | 送出評價 49 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2014/1/14 下午 05:55:43
http://lionrex.pixnet.net/blog/post/63848807-%5Bc%2B%2B%5D-memset,-memcpy,-strcpy
作者 : sflam(Raymond)討論區板主 Visual C++ .NET卓越專家VC++一代宗師新手入門優秀好手資訊類作業求救頂尖高手C++一代宗師貼文超過4000則
[ 貼文 4945 | 人氣 9172 | 評價 32290 | 評價/貼文 6.53 | 送出評價 142 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
主題發起人allen680321註記此篇回應為最佳解答 2014/1/15 上午 02:09:40

>先上程式片段
>
>char sbuf[1024];
>memset(sbuf,0,1024);

不要用 memset(), 它所做的是把記憶體設為 all-bits zero, 但 all-bits zero 未必適合所有平台的所有類型.

更簡單, 安全, 而且更有效率的方法是:
  char sbuf[1024] = {0};

>signed char data[]={0xaa,0x00,0x00,0xbb};

應該用 unsigned char 來存 binary 資料.

>sprintf_s(sbuf,"%s \r\n",data);

"%s" 預期相應的參數是個指向「字串」的指標. 這裡的「字串」指的是 c-style string, 是一個以 0 字元做為終結字元的字元陣列. 很明顯, 你的 data 不是這樣子的一個字串.

"%s" 的作用是把 data 指標所指向的數值, 用系統的字元編碼得到相關字元, 放在 sbuf 裡.

幸好你 data 裡的資料有 0 值 (第二個元素), 所以 sprintf 在運作時會終結, 要不然, sprintf 會一直往下走, 去讀取 data 範圍外的資料. 這會導致不可預期的結果.

因為你 data 的內容不是字元的編碼, %s 將會得到怪異的字元, 也有可能造成不可預期的結果.

總而言之, 只要資料不是「字串」, 就不能用任何跟字串有關的函式.

你要的是 memcpy(), 或自己用 loop 去一個字元一個字元的複製.


>//sizeof char=1
>printf("sizeof char=%d\n",sizeof(char));

不管是什麼平台, sizeof(char) 一定是 1. 這是定義.

>//sbuf data: 0xffffffaa,0xd,0xa,0x0
>printf("sbuf data:0x%x,0x%x,0x%x,0x%x\n",sbuf[0],sbuf[1],sbuf[2],sbuf[3]);

printf() 是個 variadic function (variable arguments function). 當呼叫 variadic function 的時候, 所有的 char, short 等整數類型的參數都會先提升到 int 類型.

sbuf 的元素是 char 類型. 在你的平台上, char 類型跟 signed char 類型一樣, 所以 0xaa 對 8 位元的 signed char 來說是負值 (在 2's complement 的平台上, 0xaa 是 -86). 當轉換成 int 時, 它也是負值, 0xffffffaa 就是 32-位元 int 類型的 -86.

要正確的輸出 sbuf 的資料, 你必須把 sbuf 的類型改成 unsigned char.


>//sizeof sbuf data=1024
>printf("sizeof sbuf data=%d\n",sizeof(sbuf));
>
>//sbuf data len =3
>printf("sbuf data len = %d\n",strlen(sbuf));
>
>int ret = sendto(s, sbuf, strlen(sbuf), 0, (sockaddr*)&brdcastaddr, len);

如果 sbuf 存放的不是「字串」, 就不應該用處理字串的函式, 否則, 會得到不正確, 或導致不可預期的結果.

你用的應該是 winsock 的函式, 因為 winsock 的 send() 的第二個參數是用 char*. 在其它系統上, 它是 void* (這個比較正確).

如果 sbuf 是 unsigned char, 這裡把它 cast 成 char* 就好了.

作者 : allen680321(思思烤烤)
[ 貼文 16 | 人氣 0 | 評價 20 | 評價/貼文 1.25 | 送出評價 2 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2014/1/15 上午 10:03:46
感謝您的幫忙、我不確定這樣子修改後是否可以解決問題,但是至少我瞭解了很多在VC上寫程式的注意事項,

我會儘快依您的建議修改程式,結果如何我會再po上來。感恩。
作者 : allen680321(思思烤烤)
[ 貼文 16 | 人氣 0 | 評價 20 | 評價/貼文 1.25 | 送出評價 2 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2014/1/15 上午 10:04:15
感謝您的幫忙、我不確定這樣子修改後是否可以解決問題,但是至少我瞭解了很多在VC上寫程式的注意事項,

我會儘快依您的建議修改程式,結果如何我會再po上來。感恩。
作者 : allen680321(思思烤烤)
[ 貼文 16 | 人氣 0 | 評價 20 | 評價/貼文 1.25 | 送出評價 2 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2014/1/15 上午 11:23:42
感謝 sflam的幫忙,此問題已解決,我附上解決後的完整程式碼,有二種,一個是VC++ 另一個是C#
VC++
// broadcastTest.cpp : 定義主控台應用程式的進入點。
//
#include "StdAfx.h"
#include <stdio.h>
#include <tchar.h>
#include <winsock2.h>
#include <string>
#include <iostream>
#include <atlbase.h>

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


int _tmain(int argc, _TCHAR* argv[])
{
if(argc < 2)
    {
     std::cout << "Error in Syntax: UDPServer.exe <port no> <msg>";
     return 0;
    }

    int portno = ::_wtoi(argv[1]);
    USES_CONVERSION;
    WORD w = MAKEWORD(1,1);
    WSADATA wsadata;
    ::WSAStartup(w, &wsadata);
 
 
    SOCKET s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if(s == -1)
    {
     std::cout << "Error in creating socket";
     return 0;
    }
    char opt = 1;
    setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char*)&opt, sizeof(char));
    SOCKADDR_IN brdcastaddr;
    memset(&brdcastaddr,0, sizeof(brdcastaddr));
    brdcastaddr.sin_family = AF_INET;
    brdcastaddr.sin_port = htons(portno);
    brdcastaddr.sin_addr.s_addr = INADDR_BROADCAST;
    int len = sizeof(brdcastaddr);
unsigned char sbuf[1024]={0};
unsigned char data[]={0xaa,0x00,0x00,0xbb};
memcpy(sbuf,(void *)data,4);

printf("sizeof char=%d\n",sizeof(char));
printf("sbuf data:0x%x,0x%x,0x%x,0x%x\n",sbuf[0],sbuf[1],sbuf[2],sbuf[3]);
printf("sizeof sbuf data=%d\n",sizeof(sbuf));

int ret = sendto(s,(char *) sbuf, 4, 0, (sockaddr*)&brdcastaddr, len);
    if(ret < 0)
    {
     std::cout << "Error broadcasting to the clients";
    }
    else
{
     std::cout << "Broadcasting is done";
    }
    ::closesocket(s);
 
     return 0;
}

作者 : allen680321(思思烤烤)
[ 貼文 16 | 人氣 0 | 評價 20 | 評價/貼文 1.25 | 送出評價 2 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2014/1/15 上午 11:24:09
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;

namespace ConsoleApplication1
{
    public class sender
    {
     public void Send()
     {
     UdpClient client = new UdpClient();
     IPEndPoint ip = new IPEndPoint(IPAddress.Broadcast, 55555);
     byte[] bytes = { 0xaa, 0x00, 0x00, 0xbb };
     client.Send(bytes, bytes.Length, ip);
     client.Close();
     }
    };
    class Program
    {
     static void Main(string[] args)
     {
     Byte[] data={0xaa,0x00,0x00,0xbb};
     sender test =new sender();
     test.Send();
     }
    }
}
作者 : sflam(Raymond)討論區板主 Visual C++ .NET卓越專家VC++一代宗師新手入門優秀好手資訊類作業求救頂尖高手C++一代宗師貼文超過4000則
[ 貼文 4945 | 人氣 9172 | 評價 32290 | 評價/貼文 6.53 | 送出評價 142 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2014/1/15 下午 10:18:17
>我附上解決後的完整程式碼,有二種,一個是VC++ 另一個是C#

多謝分享.

給一個小建議...

> unsigned char data[]={0xaa,0x00,0x00,0xbb};
> memcpy(sbuf,(void *)data,4);
> ...
> int ret = sendto(s,(char *) sbuf, 4, 0, (sockaddr*)&brdcastaddr, len);

memcpy() 跟 sendto() 的第三個參數可以用 sizeof data 來替代固定常數 4. 這樣的話, 如果 data 長度改變, 你不需要到處去找跟長度有關的 4 來做更改 (一個程式可能有幾個 4, 但不是每個 4 都跟 data 的長度有關).

 板主 : 青衫 , Raymond
 > Visual C++ - 討論區
 - 最近熱門問答精華集
 - 全部歷史問答精華集
 - Visual C++ - 知識庫
  ■ 全站最新Post列表
  ■ 我的文章收藏
  ■ 我最愛的作者
  ■ 全站文章收藏排行榜
  ■ 全站最愛作者排行榜
  ■  月熱門主題
  ■  季熱門主題
  ■  熱門主題Top 20
  ■  本區Post排行榜
  ■  本區評價排行榜
  ■  全站專家名人榜
  ■  全站Post排行榜
  ■  全站評價排行榜
  ■  全站人氣排行榜
 請輸入關鍵字 
  開始搜尋
 
Top 10
評價排行
Visual C++
1 青衫 11070 
2 Raymond 10090 
3 Clier 7630 
4 小約翰 2500 
5 Cog 2030 
6 coco 1870 
7 aming 1410 
8 牧童哥 1400 
9 r2109 1380 
10 Akira 1350 
Visual C++
  專家等級 評價  
  一代宗師 10000  
  曠世奇才 5000  
  頂尖高手 3000  
  卓越專家 1500  
  優秀好手 750  
Microsoft Internet Explorer 6.0. Screen 1024x768 pixel. High Color (16 bit).
2000-2019 程式設計俱樂部 http://www.programmer-club.com.tw/
0.1728516