MFC TCP/IP 통신에 질문좀 드립니다.

locker180@naver.com의 이미지


로봇과 PC 이더넷 통신을 할려고하는데요

연결은되나 데이터가 들어가지를 않습니다.

하이퍼 터미널과 PC 통신은 되구요

하이퍼 터미널에서 숫자 1 이나 2 를 주게 되면 정상적으로 데이터를 받습니다.

PC 에서 1 이나 2를 주면 동작을 하지 않네요..

로봇, 하이퍼터미널로 숫자 1이나 2값을 PC로 주면 1에 이상한 값이 같이 출력됩니다...

전체 소스를 올려 보겟습니다.

BOOL CServerDlg::OnInitDialog()
{
CDialog::OnInitDialog();

// Add "About..." menu item to system menu.

// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);

CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}

// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon

// TODO: Add extra initialization here
m_pServerSock = new CServerSock();
m_pServerSock->Create(700);
m_pServerSock->Listen();

return TRUE; // return TRUE unless you set the focus to a control
}

void CServerDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}

// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.

void CServerDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting

SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;

// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}

// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CServerDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}

void CServerDlg::OnAccept()
{
UpdateData(TRUE);
CClientSock *p = new CClientSock;
m_pServerSock->Accept(*p);
p->Send("연결되었습니다.", 16);
m_clientSocks.AddTail(p);
}

void CServerDlg::OnReceive(CClientSock* pSock)
{
UpdateData(TRUE);
char buf[1];
pSock->Receive(buf,1);
m_listReceive.InsertString(0, buf);
Send(buf);
}

void CServerDlg::OnSend()
{
// TODO: Add your control notification handler code here
UpdateData(TRUE);
char buf[1];
lstrcpy(buf, (const char*)m_strSend);
lstrcat(buf,"\r\n");
Send(buf);
}

void CServerDlg::Send(char *buf)
{
POSITION pos = m_clientSocks.GetHeadPosition();
while (pos != NULL)
{
CClientSock *p = m_clientSocks.GetNext(pos);
p->Send(buf, strlen(buf)+1);
}
}

shint의 이미지

www.devpia.com

디버깅 방법은 이렇습니다.
- F9 로 브레이크 포인트를 잡습니다.
- F5로 실행합니다.
- F10 으로 한줄씩 값을 디버깅 합니다.

각 함수의 인자값과 리턴값을 확인해보세요. 문서 보는 방법은 MSDN 을 참고해보세요.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms647487(v=vs.85).aspx

배열의 범위를 넘어가는지 확인해보세요.
배열 값보다 많은 값이 들어가면. 잘못된 처리와 오류가 나게 됩니다.

메모리 릭을 확인하는 방법을 찾아보세요.

try catch 문을 확인해보세요.

각 함수 호출 순서를 확인해 보세요.

호출이 중복되는 경우나. 버퍼에 이전 값이 지워지지 않았는지도 확인해 봅니다.

소켓 초기화가 잘 되었는지도 확인해 봅니다.

중복된 데이터의 처리가 있는지도 확인해 봅니다.

각 단계(한줄)마다. 결과값을 확인해 보세요.

이런것들을 한번씩 구현해보시면... 좋습니다. ㅡ_ㅡ;;

원격 데스크탑 접속 열어주시거나. shintx@naver.com
네이트온으로 원격 접속하시면 봐 드릴게요. ㅇ_ㅇ;; shintx@nate.com

접속해도 아마... 디버깅이랑 문서보는 방법이나 알려드릴겁니다. ㅇ_ㅇ;;

그리고... 첨부로...

//Visual Studio 정품 구입하는 방법
http://www.devpia.com/software/products/productlist.aspx?key=nara&ClassCode=0401&Pmaker=NF&PContent=NF

//책에 포함된 CD로 설치하는 방법
VISUAL C++6.0(S/W포함)
http://books.google.co.kr/books?cad=2&client=internal-uds&hl=ko&id=yRs3MwAACAAJ&num=1&source=gbs_similarbooks_r
http://www.kyobobook.co.kr/product/detailViewKor.laf?barcode=9788976277510&ejkGb=KOR&mallGb=KOR&orderClick=LAH
http://dodongbook.co.kr/mall/m_mall_detail.php?ps_ctid=10040000&ps_goid=880600&ps_page=11
http://blog.daum.net/csn0538/16513487
http://blog.daum.net/csn0538/10180871
http://www.kyobobook.co.kr/product/detailViewKor.laf?barcode=9788909050678&ejkGb=KOR&linkClass=331525&mallGb=KOR

정품 소프트웨어가 들어 있는 Visual C++ 6 Teach Yourself in 21days
http://book.interpark.com/product/SecCompare.do?_method=listSec&prdNo=54950
http://blog.naver.com/infopub?Redirect=Log&logNo=100024439069

//MFC와 RC 리소스 에디터가 없고. 닷넷과 CLR폼을 사용하는 버전
Visual Studio 2005 Express 무료
http://www.microsoft.com/korea/msdn/vstudio/express/support/install/

Visual Studio 2010 2012 Express 무료 다운로드 링크
http://www.microsoft.com/visualstudio/kor/downloads

//인스톨 쉴드 정품 구매 방법
http://www.devpia.com/software/products/productlist.aspx?key=esd&ClassCode=6001&Pmaker=NF&PContent=NF

그외에 다른 개발 도구
//
Dev-C++ 사용하기 무료
http://blog.naver.com/swmem_bjm?Redirect=Log&logNo=130163400038
http://www.bloodshed.net/dev/devcpp.html

----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.

매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.

각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com

Lipi의 이미지

와이어샤크를 PC에 설치하여 하이퍼터미널로 전송했을 때와 만드신 프로그램으로 데이터를 전송했을때와의 패킷 내용의 차이를 한번 분석해 보시길 권장드립니다.
http://www.wireshark.org

mirheekl의 이미지

void CServerDlg::OnSend() 
{
// TODO: Add your control notification handler code here
UpdateData(TRUE);
char buf[1];
lstrcpy(buf, (const char*)m_strSend);
lstrcat(buf,"\r\n");
Send(buf);
}
 
void CServerDlg::Send(char *buf)
{
POSITION pos = m_clientSocks.GetHeadPosition();
while (pos != NULL)
{
CClientSock *p = m_clientSocks.GetNext(pos);
p->Send(buf, strlen(buf)+1);
}
}

1바이트짜리 버퍼를 처리하는 부분이 잘못된듯 하네요. buf[1] 이거요. 송수신 루틴 둘다 문제가 있습니다.

1. 버퍼를 좀더 크게 잡으시고.. 버퍼가 1바이트뿐이기 때문에 뒤에 \r\n이랑 널 터미네이터가 오버런을 냅니다.. 프로그램이 뻗거나 데이터가 제대로 보존되지 않는 게 당연합니다. 그리고 문자열 관련 함수는 secured 버전을 사용하시는게 좋겠네요. strcat_s, strcpy_s, ...
2. 전송 루틴에선 문자열로 체크하는 대신 버퍼의 길이, 데이터의 길이를 함께 받거나 주도록 처리하는 쪽이 나중에 문제의 소지가 적습니다. 현재는 송수신하려는 버퍼보다 실제 데이터가 더 길 때, 그리고 바이너리 데이터를 전송하기 위한 처리가 되어 있지 않은 걸로 보입니다.

위에 다른분들이 말씀하신 것처럼 와이어샥이나 기타 패킷 분석 툴을 사용하셔도 좋고, 당장 쓰실 여유가 없으시면 로봇 역할을 대신하는 데이터 수신프로그램을 하나 더 만들어서 송신측에서 제대로 데이터가 발생하는지 체크해보셔도 됩니다. 여튼 현재의 구현방식에는 문제가 있습니다.

--

locker180@naver.com의 이미지

수신측 프로그램을 만들어서 해보면 통신은 잘됩니다.
버퍼1바이트를 한이유가 로봇에 "1","2" 이런식으로 던져주기만해서 쓰레기 값이 같이 들어갈까바
1바이트를 잡았구요 200바이트를 잡아도 전혀 데이터가 넘어가질 않네요...

mirheekl의 이미지

이렇게 해서 바이트단위로 데이터를 찍어보면 당연히 차이가 보일겁니다.

또한가지 의심되는건 커넥션이 그냥 일반 TCP통신이 아닐 수 있다는 생각입니다. 텔넷의 경우 처음 접속했을때 추가적인 데이터가 들어가거든요. 말씀드린 세팅으로 데이터를 쭉 찍어보면 아실겁니다. 이런걸 제대로 전송을 안하면 로봇측에서 아 쓸데없는 접속이 들어왔구나 하고 이후의 데이터를 싹 무시할수도 있는 거죠. 스펙부터 확인해보시는게 좋겠단 생각입니다. 일반 TCP연결인지 아니면 꼭 텔넷 연결을 요구하는지 말이죠.

그리고 정상 동작 여부와 관계없이 버퍼 부분은 꼭 수정하셔야 합니다. 1바이트 데이터를 잡아놓고 그 이후의 영역까지 사용하고 있으니까요.

--

Anti-Lock의 이미지

윗분이 정확하게 지적 하신듯 합니다.
명백히 코드의 문제가 눈으로 보이니, 수정하세요..
char buf[200] 으로 한다고 수정이 다된게 아닙니다.
MFC, socket 통신에 대해 공부해서 아로 계시듯이
C/C++에 대해서도 알아두셔야 합니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.