בעיה בווינסוק2 בC++ - תכנות - HWzone פורומים
עבור לתוכן
  • צור חשבון

בעיה בווינסוק2 בC++


barp12

Recommended Posts

אז איך מתקנים את זה


#include "stdafx.h"
#include "GameServer.h"
#include "ibTabCtrl.h"
#include "MainP.h"
#include "GameServerDlg.h"
#include "XMLChildNode.h"
#define WM_SOCKET WM_USER+1

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

static UINT BASED_CODE indicators[] = {IDS_INDICATOR_STATUS,IDS_INDICATOR_PLAYERS};
SOCKET s;
SOCKET *clients;
sockaddr *client_sock;
int addr_size = sizeof(sockaddr);
int players = 0;
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();

// Dialog Data
enum { IDD = IDD_ABOUTBOX };

protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support

// Implementation
protected:
DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()


// CGameServerDlg dialog

CGameServerDlg::CGameServerDlg(CWnd* pParent /*=NULL*/)
: CDialog(CGameServerDlg::IDD, pParent)
, m_mainP(NULL)
, m_piAdoBinding(NULL)
, m_strConn(_T(""))
, m_strCmd(_T(""))
, m_ChatPn(NULL)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CGameServerDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_TAB1, m_cTab);
}

BEGIN_MESSAGE_MAP(CGameServerDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
ON_COMMAND(ID_SERVER_EXIT, &CGameServerDlg::OnServerExit)
ON_COMMAND(ID_HELP_ABOUT, &CGameServerDlg::OnHelpAbout)
ON_WM_MOVE()
ON_WM_SHOWWINDOW()
ON_COMMAND(ID_SERVER_START, &CGameServerDlg::OnServerStart)
ON_UPDATE_COMMAND_UI(ID_SERVER_START, &CGameServerDlg::OnUpdateServerStart)
ON_WM_CLOSE()
ON_COMMAND(ID_SERVER_STOP, &CGameServerDlg::OnServerStop)
ON_UPDATE_COMMAND_UI(ID_SERVER_STOP, &CGameServerDlg::OnUpdateServerStop)
ON_WM_TIMER()
END_MESSAGE_MAP()


// CGameServerDlg message handlers

BOOL CGameServerDlg::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
players = 0;
ghDlg = m_hWnd;
m_mainP = new MainP();
m_mainP->Create(IDD_DMAIN,m_cTab.GetWindow(IDD_DMAIN));
m_UserPn = new UserPn();
m_UserPn->Create(IDD_DUSERS,m_cTab.GetWindow(IDD_DUSERS));
m_ChatPn = new CChatPane();
m_ChatPn->Create(IDD_DCHAT,m_cTab.GetWindow(IDD_DCHAT));
m_cTab.AddTabPane(_T("Main"),m_mainP);
m_cTab.AddTabPane(_T("Users"),m_UserPn);
m_cTab.AddTabPane(_T("Chat"),m_ChatPn);
m_bar.Create(this); //We create the status bar

m_bar.SetIndicators(indicators,2); //Set the number of panes

CRect rect;
GetClientRect(&rect);
//Size the two panes
m_bar.SetPaneInfo(0,IDS_INDICATOR_STATUS,
SBPS_NORMAL,rect.Width()/5 * 4);
m_bar.SetPaneInfo(1,IDS_INDICATOR_PLAYERS,
SBPS_NORMAL,rect.Width()/5 * 1);
//This is where we actually draw it on the screen
RepositionBars(AFX_IDW_CONTROLBAR_FIRST,AFX_IDW_CONTROLBAR_LAST,
IDS_INDICATOR_STATUS);
m_bar.SetPaneText(0,_T("Offline"));
m_strConn = _T("Provider=MSDASQL.1;Data Source=Users");
m_strCmd = _T("select * from Users");
m_RsUser = NULL;
m_piAdoBinding = NULL;
::CoInitialize(NULL);
try{
m_RsUser.CreateInstance(__uuidof(Recordset));
m_RsUser->Open((LPCTSTR)m_strCmd,(LPCTSTR)m_strConn,adOpenDynamic,adLockOptimistic,adCmdUnknown);
if(FAILED(m_RsUser->QueryInterface(__uuidof(IADORecordBinding),(LPVOID*)&m_piAdoBinding)))
_com_issue_error(E_NOINTERFACE);
m_piAdoBinding->BindToRecordset(&m_UsRs);
}
catch(_com_error &e)
{
GenerateError(e.Error(),e.Description());
}
if(adFldOK == m_UsRs.PassS && adFldOK == m_UsRs.UserNS){
CString UN,Pass;

while(!m_RsUser->EndOfFile){
UN.Format(_T("%S"),m_UsRs.m_UserName);
Pass.Format(_T("%S"),m_UsRs.m_Pass);
m_UserPn->InsertItem(m_UsRs.m_ID,UN,Pass);
m_RsUser->MoveNext();
}
}
else
MessageBox(_T("cannot read db"));
WSADATA w; // used to store information about WinSock version
int error = WSAStartup (0x0202, &w); // Fill in w

if (error)
{ // there was an error
MessageBox(_T("Error occurd"));
return FALSE;
}
if (w.wVersion != 0x0202)
{ // wrong WinSock version!
WSACleanup (); // unload ws2_32.dll
MessageBox(_T("Error worng verision"));
return FALSE;
}

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

void CGameServerDlg::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 CGameServerDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting

SendMessage(WM_ICONERASEBKGND, reinterpret_cast<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 function to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CGameServerDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}


void CGameServerDlg::GenerateError(HRESULT hr, PWSTR pwszDescription)
{
CString strError;
strError.Format(_T("Run-time error '%d (%x)'"),hr,hr);
strError += "\n\n";
strError += pwszDescription;
AfxMessageBox(strError);
}

void CGameServerDlg::OnServerExit()
{
// TODO: Add your command handler code here
OnOK();
}

void CGameServerDlg::OnHelpAbout()
{
// TODO: Add your command handler code here
CAboutDlg abd;
abd.DoModal();
}

void CGameServerDlg::OnMove(int x, int y)
{
CDialog::OnMove(x, y);
m_cTab.OnMove(x,y);

// TODO: Add your message handler code here
}

void CGameServerDlg::OnShowWindow(BOOL bShow, UINT nStatus)
{
CDialog::OnShowWindow(bShow, nStatus);
m_cTab.SetDefaultPane(0);
m_UserPn->m_ctlList.SetItemState(0, LVIS_SELECTED, LVIS_SELECTED | LVIS_FOCUSED);
m_UserPn->m_ctlList.EnsureVisible(0, FALSE);

// TODO: Add your message handler code here
}

void CGameServerDlg::OnServerStart()
{
// TODO: Add your command handler code here
m_mainP->UpdateData(TRUE);
s = socket(AF_INET,SOCK_STREAM,0);
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(m_mainP->m_iPort);
addr.sin_addr.s_addr = htonl (INADDR_ANY);
if (bind(s, (LPSOCKADDR)&addr, sizeof(addr)) == SOCKET_ERROR){
WSACleanup();
MessageBox(_T("cannot start bind"));
return;
}
if (listen(s,m_mainP->m_iMaxP)==SOCKET_ERROR)
{ // error! unable to listen
WSACleanup ();
MessageBox(_T("unable to start listen"));
return;
}
m_mainP->GetDlgItem(IDC_EPORT)->EnableWindow(FALSE);
m_mainP->GetDlgItem(IDC_EMAXP)->EnableWindow(FALSE);
m_mainP->GetDlgItem(IDC_SMAXP)->EnableWindow(FALSE);
clients = new SOCKET[m_mainP->m_iMaxP];
client_sock = new sockaddr[m_mainP->m_iMaxP];
WSAAsyncSelect(s,this->m_hWnd,WM_SOCKET,FD_READ|FD_WRITE|FD_ACCEPT);
}

void CGameServerDlg::OnUpdateServerStart(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
}

void CGameServerDlg::OnClose()
{
// TODO: Add your message handler code here and/or call default
if(m_RsUser)
m_RsUser->Close();
if(m_piAdoBinding)
m_piAdoBinding->Release();
m_RsUser = NULL;
CoUninitialize();
shutdown (s, SD_SEND); // s cannot send anymore
delete []clients;
delete []client_sock;
// you should check to see if any last data has arrived here
closesocket (s); // close

CDialog::OnClose();
}


void CGameServerDlg::OnServerStop()
{
// TODO: Add your command handler code here
shutdown (s, SD_SEND); // s cannot send anymore
delete []clients;
delete []client_sock;

// you should check to see if any last data has arrived here
closesocket (s); // close
TRACE("Socket closed");
m_mainP->GetDlgItem(IDC_EPORT)->EnableWindow(TRUE);
m_mainP->GetDlgItem(IDC_EMAXP)->EnableWindow(TRUE);
m_mainP->GetDlgItem(IDC_SMAXP)->EnableWindow(TRUE);
m_bar.SetPaneText(0,_T("Offline"));
}

void CGameServerDlg::OnUpdateServerStop(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
}

void CGameServerDlg::OnTimer(UINT_PTR nIDEvent)
{

CDialog::OnTimer(nIDEvent);
}

LRESULT CGameServerDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
// TODO: Add your specialized code here and/or call the base class
switch(message)
{
case WM_SOCKET:
if(WSAGETSELECTERROR(lParam))
{
WSACleanup();
MessageBox(_T("error\nsocket error"));
}
switch(WSAGETSELECTEVENT(lParam))
{
case FD_ACCEPT:
if(players<m_mainP->m_iMaxP)
{
clients[players] = accept(s,&client_sock[players],&addr_size);
if(clients[players]==INVALID_SOCKET)
{
WSACleanup();
MessageBox(_T("Error"));
}
else
{
players++;
CString str;
str.Format(_T("%i Players"),players);
m_bar.SetPaneText(1,(LPCTSTR)str);
}
}
break;
case FD_READ:
char buff[80];
int is;
is = recv(s,buff,sizeof(buff),0);
if(is==SOCKET_ERROR)
MessageBox(_T("error recv"));
m_ChatPn->m_sChat+=buff[0];
m_ChatPn->UpdateData(FALSE);
break;
}
break;
}

return CDialog::WindowProc(message, wParam, lParam);
}

זה הקוד

אני לא ראיתי את ההודעה הזאת

אפשר לראות את כל הקוד (מעצבן כל החצאי קודים האלו).
קישור לתוכן
שתף באתרים אחרים

יש לי בעיה גם בווינסוק אז אני אשאל כאן במקום לכתוב דיון חדש.

כתבתי ישום tcp client וישום tcp server בסיסי... בכל מקרה הוא עובד לי רק שהכתובת היא כתובת ה- loopback של המחשב 127.0.0.1.. כשאני מנסה את התוכנית על שני מחשבים ומשתמש באייפי של אחד מהם היא לא מצליחה להתחבר (יש לי ראוטר אבל NAT אמור להעביר את המידע למחשב המתאים לפי הפורט לא?).

ה- server שלי מקשיב בכל כתובות האייפי של המחשב אני חושב.. מבנה ה- SOCKADDR_IN שלי מוגדר כך:

InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);

אה ועוד משהו... ה- server שלי עובד על non blocking sockets ומשתמש במודל עם שימוש בפונקציה WSAAsyncSelect לקבלת הודעות כמו FD_Accept או FD_Recieve.. בכל מקרה יש פעמים בהם נשלח מידע לתוכנית שלי ובכל זאת אני רואה שיש לי Error בפונקציה recv.

בעיקרון התוכנית שלי (תוכנית דוגמא קטנה בשביל תירגול) היא תוכנית בה בחלון הקליינט המתשמש מצייר משהו ובחלון הסרבר רואים גם את הציור ככה שכל פעם שבקליינט מציירים נקודה, מיקומה נשלח לסרבר.. בכל מקרה אצלי רק חלק מהנקודות מצטיירות בסרבר בגלל ה- Error ב- recv שלפעמים קורה... הוא כאילו רנדומלי ואין לי דרך להסביר מתי הוא נקרא.

אה ו- recv מחזירה:

10038WSAENOTSOCK

Socket operation on an invalid socket. This error can be returned from any Winsock function that takes a SOCKET handle as a parameter. This error indicates that the supplied socket handle is not valid.

ככה שזה לא אומר לי הרבה..

תודה למי שיעזור.

קישור לתוכן
שתף באתרים אחרים

אתה מנסה בין 2 מחשבים ברשת המקומית, או מהאינטרנט ? אם מהאינטרנט, תבדוק שה NAT מקונפג להפנות אליך את הבקשות, אם בין 2 מחשבים, תבדוק שאין FIREWALL שחוסם (אתה יכול עם תוכנה כמו NETCAT לבדוק למשל שהכל פתוח).

לגבי ה WSAENOTSOCK, אתה בטוח שאתה לא משנה את הערך של ה SOCK, או שפשוט החיבור נסגר באמצע ואתה לא בודק את זה ?

קישור לתוכן
שתף באתרים אחרים

אתה מנסה בין 2 מחשבים ברשת המקומית, או מהאינטרנט ? אם מהאינטרנט, תבדוק שה NAT מקונפג להפנות אליך את הבקשות, אם בין 2 מחשבים, תבדוק שאין FIREWALL שחוסם (אתה יכול עם תוכנה כמו NETCAT לבדוק למשל שהכל פתוח).

לגבי ה WSAENOTSOCK, אתה בטוח שאתה לא משנה את הערך של ה SOCK, או שפשוט החיבור נסגר באמצע ואתה לא בודק את זה ?

תודה על התגובה.

אני מנסה ברשת.. ושאני מנסה להתחבר לעצמי עם 127.0.0.1 זה עובד אבל שאני מנסה בין 2 מחשבים ברשת זה לא.. אני אנסה לבדוק אם אין firewall שחוסם.

לגבי ה- WSAENOTSOCK .. אני די חדש בווינסוק ככה שאני פשוט אראה לך את קוד השליחה של הקליינט ואת הקוד של הסרבר שמקבל את המידע.

קוד קליינט:

// Create a new socket to make a client connection.

newConnection = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

if (newConnection == INVALID_SOCKET) {

return 1;

}

if (connect(newConnection , (SOCKADDR *) &ServerAddr, sizeof(ServerAddr))==SOCKET_ERROR)

{

MessageBox(hwnd, "Connect Error " , "Error", MB_OK);

i=WSAGetLastError();

closesocket(s);

return 1;

}

if(send(newConnection , sendBuf, bufLength, 0)==SOCKET_ERROR)

{

MessageBox(hwnd, "Send Error", "Error", MB_OK);

}

shutdown(newConnection ,SD_SEND);

closesocket(newConnection );

והנה קוד מהסרבר:

case FD_READ:

// Receive data from the socket in

// wParam

if (recv((SOCKET)wParam, recvBuf, recvBufLen, 0)<0)

{

error=WSAGetLastError();

LogFile.open("logFile2.txt",ios_base::out|ios_base::app);

LogFile<<"Error while reciving data: Error Number "<<error<<endl;

LogFile.close();

return 0;

}

הראתי לך רק חלקים שאני חושב שהם רלוונטים.. בכל מקרה כמו שאתה רואה הסרבר עובד עם non-blocking sockets ומקבל התראה ל- recv.. הקליינט עובד עם blocking sockets ופשוט שולח את המידע..

מה שלא אמרתי ושאני עכשיו חושב שאולי זה לא בסדר זה הדבר הבא:

החלק שהראיתי לך מקוד הקליינט נקרא בעצם כל פעם שהתוכנה רוצה לשלוח משהו.. זאת אומרת שאני כל פעם מתחבר מחדש וסוגר את הסוקט מחדש... אני גם עושה newConnection=SOCKET() כל פעם מחדש אבל newConnection הוא לא סטטי ככה שאולי מה שעשיתי זה טיפשי אבל זה לא אמור ליצור בעיות כי בעצם כל פעם אני משתמש בסוקט חדש ויוצר התחברות איתו, שולח מידע וסוגר..

תודה על העזרה.

קישור לתוכן
שתף באתרים אחרים

בגדול זה לא חכם לעשות תקשורת ככה, במיוחד בפרוקוטול TCP, בגלל התקורה של יצירת חיבור חדש בכל פעם מחדש (אם אתה רוצה ככה, כבר עדיף UDP).

כמו שאמרתי, נסה להריץ NETCAT בין שני הצדדים ולראות אם זה עובד בסדר.

מה הפרמטרים שאתה מעביר ל WSAAsyncSelect (אתה משתמש בו רק פעם אחת בקוד ?) האם אתה מטפל גם ב FD_ACCEPT ?

קישור לתוכן
שתף באתרים אחרים

ארכיון

דיון זה הועבר לארכיון ולא ניתן להוסיף בו תגובות חדשות.

×
  • צור חדש...