달력

42024  이전 다음

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

'프로그래밍/C++ / C'에 해당되는 글 3건

  1. 2011.01.13 [c++] CHttpConnection에서 한글 전송 시 null 문제
  2. 2010.12.23 [C++/C] 트랜잭션 ...
  3. 2010.07.08 [C++/C] 중복되지 않게 랜덤 숫자 출력

CHttpConnection 을 이용해 asp 페이지로 한글을 보내고 이를 처리하는 과정에서 문제가 발생했다.
asp 페이지에 값이 null로 넘어옴으로 인해 데이터 처리가 불가능해지는 현상이었다..
이를 해결하기 위해 4시간여 구글링을 하면서 이것 저것 테스트 해본결과 성공적인 결과를 주는 한가지 셋팅을 찾아서 포스팅 한다..

1. 서버

기존 소스

char cpURL[128];
DWORD dwServiceType, dwRet;
INTERNET_PORT nPort;
CString ServerStr, ObjectStr, DataStr;
IString UserID, URL, Email, SQLComm, MSG;
BYTE BType;
int iError;

URL.Format("http://server.com/page.asp?id=%s&type=%d",UserID.ToChar(), BType);

sprintf(cpURL, "%s", URL.ToChar());
AfxParseURL(cpURL, dwServiceType, ServerStr, ObjectStr, nPort);
 
CString HeaderStr = "Content-Type: application/x-www-form-urlencoded";
CInternetSession Session("My Session", PRE_CONFIG_INTERNET_ACCESS);
CHttpConnection *pServer = NULL;
CHttpFile *pFile = NULL;

pServer = Session.GetHttpConnection(ServerStr, nPort);
pFile = pServer->OpenRequest(CHttpConnection::HTTP_VERB_POST, ObjectStr, 0, 1, 0, 0, INTERNET_FLAG_RELOAD);
pFile->AddRequestHeaders(HeaderStr);
pFile->SendRequest();
pFile->QueryInfoStatusCode(dwRet);
  
Session.Close();
delete pFile;
delete pServer;

==================================================
수정 소스

/// 우선 char를 UTF로 변경한다. 그리고 url은에서 파라미터는 제외 한다.
UserID.StringUtf8();    // *char를 utf8로 변경 (회사 내부 소스라 죄송;; 하지만 인터넷 뒤져 보면 나옴.)
URL.Format("
http://server.com/page.asp");
sprintf(cpURL, "%s", URL.ToChar());
AfxParseURL(cpURL, dwServiceType, ServerStr, ObjectStr, nPort);
/// 파라미터를 별도의 CStrig으로 저장
MSG.Format("id=%s&type=%d",UserID.ToChar(), BType); 
DataStr = (LPCTSTR)MSG.ToChar();
  
CString HeaderStr = "Content-Type: application/x-www-form-urlencoded";
CInternetSession Session("My Session", PRE_CONFIG_INTERNET_ACCESS);
CHttpConnection *pServer = NULL;
CHttpFile *pFile = NULL;

pServer = Session.GetHttpConnection(ServerStr, nPort);   // ServerStr =  http://server.com/
pFile = pServer->OpenRequest(CHttpConnection::HTTP_VERB_POST, ObjectStr);   // ObjectStr = page.asp
pFile->SendRequest(HeaderStr,(LPVOID)(LPCTSTR)DataStr, DataStr.GetLength());  //DataStr = id=아이디&type=type
pFile->QueryInfoStatusCode(dwRet);



page.asp 소스에서
<% @language='vbscript' codepage = '65001' %>
<%      response.charset = "utf-8" %>
이 두줄을 추가한다.

=================================

수정 내용을 종합하면 Char* 를 UTF-8로 변경하고.
URL의 파라미터를 별도로 분리해서 SendRequest 에서 처리하고.
asp 에서는 UTF-8로 받는 소스를 추가...

이렇게 해서 해결됐다 !

'프로그래밍 > C++ / C' 카테고리의 다른 글

[C++/C] 트랜잭션 ...  (0) 2010.12.23
[C++/C] 중복되지 않게 랜덤 숫자 출력  (0) 2010.07.08
Posted by SadDev
|
트랜잭션 거는 문제 때문에 삽질에 삽질 하다가.. 대충이라도 정리..
참고 페이지

#include <stdlib.h>

CDataSource mDataSource;
CSession mSession;

CDBPropSet DBInit(DBPROPSET_DBINIT);
HRESULT hr;
IString Conn;   // IString 은 그냥 CString / char로 만들어서 쓰면 됨.

  hr = CoInitialize(0);
  if(FAILED(hr))
  {
    AfxMessageBox("CoInitialize 실패");
    return false;
  }

  Conn.Format("PROVIDER=SQLOLEDB;SERVER=[ServerIP | ServerName];UID=[Logid ID];PWD=[PassWord];DATABASE=[DBName]");
  DBInit.AddProperty(DBPROP_INIT_PROMPT, (short)4);

  DBInit.AddProperty(DBPROP_INIT_PROVIDERSTRING, Conn.ToChar());
DBInit.AddProperty(DBPROP_INIT_LCID, (long)1043);

  hr = mDataSource.Open(_T("SQLOLEDB"), &DBInit);
  if(FAILED(hr))
  {
    AddMessage(NSS_E_DB_CONN, "Can't Connect Database");
    return false;
  }

  hr = mSession.Open(mDataSource);
  if(FAILED(hr))
  {
    AddMessage(NSS_E_DB_OPEN_SESSION, "Can't Open Session");
    return false;
  }
//==================================================================================================
// 실제 소스에서 위 / 아래는 각각 함수로 만들어져서 따로 분리 되어 있으나.. 설명을 위해 하나의 소스에 적음
//==================================================================================================
        CCommand<CDynamicAccessor, CRowset, CNoMultipleResults> Cmd;
HRESULT hr;
IString SQLComm, UserID;
int iError;
short sCount;

rReadPacketStream.ReadString(UserID);
sCount = rReadPacketStream.ReadShort();
       mSession.StartTransaction(ISOLATIONLEVEL_READCOMMITTED, 0, NULL, NULL);    // StartTransaction 으로 트랜잭션을 건다.

for(int i = 0; i < sCount; i++)
{
IString Name;
rReadPacketStream.ReadString(Name);

try
{
SQLComm.Format2(1024,"EXEC dbo.BB_SET_ADD_DATA '%s'", Name.ToChar());
hr = Cmd.Open(mSession, SQLComm.ToChar());
if(FAILED(hr))
{
iError = NSS_E_SQL_INSERT;
throw "AddPticher : SQL Insert Failed";
}
}
catch(char *cpErr)
{
mSession.Abort(NULL, FALSE, FALSE);  // sCount 만큼 인서트를 진행하다가.. 한번이라도 오류가 나면 Abort 실행(롤백)
if(strlen(cpErr) > 0) AddMessage(iError, cpErr);
Cmd.Close();
return iError;
}
}
mSession.Commit(FALSE, XACTTC_SYNC, 0);  // 전부 정상적으로 실행 되면 Commit
Cmd.Close();

return true;
}


여기서 중요한건 역시나 StartTransaction , Abort , Commit 

프로시져에는 SET XACT_ABORT ON 을 꼭 적어주자..

Posted by SadDev
|

1 ~ 100 까지 랜덤하게 숫자를 뽑을때 중복되지 않게 뽑으면서 속도까지 빠르려면 어떤 방법이 있을까??

일반적으로 사실 for문 을 잘 돌리면 중복 되지 않게 뽑는건 어렵지 않다..
다만 중복 for문에 의해 속도가 느려질뿐... 1 ~ 10 정도의 작은 수는 괜찮지만 1000, 10000 같이 숫자가 커질수록 부하는 몇배로 커진다...

우선 한가지 생각해본 방법은
미리 배열에 1 ~100까지 담아두고 하나씩 빼오는 것.
그러다 이미 빠진 숫자가 나오면 그 옆의 숫자를 가져오는 것을 생각해봤다.

IString arrNum[100];
for(int i = 1 i < 101; i++)
{
  arrNum[i] = i+1;
}
for(int i = 1; i < 101; i++)
   {
    sTemp = (short)rand() % 100 ;
    while(arrNum[sTemp].Compare("")==0)
    {
     sTemp++;
     if(sTemp == 100) sTemp = 1;
    }
    arrNum[sTemp] = "";
   }
printf("%d", sTemp);

①②③④⑤⑥⑦⑧⑨⑩....... 이렇게 100까지 저장해 둔다.

랜덤을 돌려서 5가 나오면
①②③④""⑥⑦⑧⑨⑩.......   5는 공백이 된다.

쭉 for문을 돌다가 또 5가 나오면 그 옆 숫자인 6을 가져오고.. 6도 비어있으면 그 옆의 7... 이런식으로 한칸 옆의 숫자를 가져오면서 돌게 된다.


하지만 위 코드도 단점이 있었다..
낮은 확률이긴 하지만 마지막에 가면 근접한 숫자들이 뭉쳐서 나올때가 있다.


그래서 검색을 하고 하고 또 해서 찾아낸 방법.
int sCard = 100;
int *x = new int[sCard];
   for (int j = 0 ; j < sCard; j++)
    x[j] = j;
   
   for (int j = 0; j < sCard; j++)
   {
    int tmp = 0;
    int k = 0;
    int l = 0;
    for(int m = 0; m < 8; m++)
    {
     tmp += rand() << (32 - ((m + 1) * 4));
    }
    k = (tmp % (sCard - j)) + j;
    l = x[j];
    x[j] = x[k];
    x[k] = l;
   }
   free(x);


아참.. 위 코드는 0~ 100이 되겠다..
인덱스 가져올 일이 있어서 0 부터로 짯음...

사실 소스에서
 for(int m = 0; m < 8; m++)
    {
     tmp += rand() << (32 - ((m + 1) * 4));
    }
    k = (tmp % (sCard - j)) + j;


이부분은 이해를 못하고 있다..
먼가 중요한 부분이고 위 소스 때문에 난수가 제대로 나오는것 같은데 아직 정확히 이해는 못하고 있다 ;ㅁ;

'프로그래밍 > C++ / C' 카테고리의 다른 글

[c++] CHttpConnection에서 한글 전송 시 null 문제  (0) 2011.01.13
[C++/C] 트랜잭션 ...  (0) 2010.12.23
Posted by SadDev
|