פורסם 2007 בפברואר 2118 שנים שאני שולח מידע ב ווינסוק זה מגיע לי בסיניתקוד הקבלה char buff[80]; recv(s,buff,sizeof(buff),0);קוד השליחהsend (s, "hi", 3, 0);send (s, "hi", 3, 0);
פורסם 2007 בפברואר 2118 שנים מחבר recv מחזיר אם היתה בעיההא קלטתי את הבעיה זה לא מצליח לקבל את ההודעה זה מחזיר SOCKET_ERROR
פורסם 2007 בפברואר 2118 שנים גם לא עונה על השאלה (וטועה), גם מתחכם וגם לא מדפיס את כל הקוד.בהצלחה בהמשך.
פורסם 2007 בפברואר 2118 שנים מחבר אז איך מתקנים את זה#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#endifstatic 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 Aboutclass CAboutDlg : public CDialog{public: CAboutDlg();// Dialog Data enum { IDD = IDD_ABOUTBOX }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support// Implementationprotected: 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 dialogCGameServerDlg::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 handlersBOOL 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);}זה הקודאני לא ראיתי את ההודעה הזאתאפשר לראות את כל הקוד (מעצבן כל החצאי קודים האלו).
פורסם 2007 בפברואר 2118 שנים תבדוק בדיבאגר את:ערך החזרה של RECVתוכן BUFF ישירות, ולא דרך ההוספה שלו למקום אחר.
פורסם 2007 בפברואר 2218 שנים יש לי בעיה גם בווינסוק אז אני אשאל כאן במקום לכתוב דיון חדש.כתבתי ישום 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 מחזירה:10038WSAENOTSOCKSocket 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. ככה שזה לא אומר לי הרבה..תודה למי שיעזור.
פורסם 2007 בפברואר 2218 שנים אתה מנסה בין 2 מחשבים ברשת המקומית, או מהאינטרנט ? אם מהאינטרנט, תבדוק שה NAT מקונפג להפנות אליך את הבקשות, אם בין 2 מחשבים, תבדוק שאין FIREWALL שחוסם (אתה יכול עם תוכנה כמו NETCAT לבדוק למשל שהכל פתוח).לגבי ה WSAENOTSOCK, אתה בטוח שאתה לא משנה את הערך של ה SOCK, או שפשוט החיבור נסגר באמצע ואתה לא בודק את זה ?
פורסם 2007 בפברואר 2218 שנים אתה מנסה בין 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 הוא לא סטטי ככה שאולי מה שעשיתי זה טיפשי אבל זה לא אמור ליצור בעיות כי בעצם כל פעם אני משתמש בסוקט חדש ויוצר התחברות איתו, שולח מידע וסוגר..תודה על העזרה.
פורסם 2007 בפברואר 2218 שנים בגדול זה לא חכם לעשות תקשורת ככה, במיוחד בפרוקוטול TCP, בגלל התקורה של יצירת חיבור חדש בכל פעם מחדש (אם אתה רוצה ככה, כבר עדיף UDP).כמו שאמרתי, נסה להריץ NETCAT בין שני הצדדים ולראות אם זה עובד בסדר.מה הפרמטרים שאתה מעביר ל WSAAsyncSelect (אתה משתמש בו רק פעם אחת בקוד ?) האם אתה מטפל גם ב FD_ACCEPT ?
ארכיון
דיון זה הועבר לארכיון ולא ניתן להוסיף בו תגובות חדשות.