读书人

直接用Windows Socket API编程遇到的有

发布时间: 2013-02-24 17:58:56 作者: rapoo

直接用Windows Socket API编程遇到的问题。
我Winsock的代码都在WndProc函数里,其他代码都是Win32窗体应用程序的标准代码,由新建工程时的向导(不是MFC向导)自动创建的,包括WinMain,注册窗口类之类的函数。说明清楚工程的类型,就不必多介绍了。

我现在写好的程序都不会报错,存在的疑问只是对于建立连接的流程和代码的编写有一些疑问。

先给出服务器的WndProc的代码(其他都是标准的,就省略了)。下面再说疑问。


/*事先定义了其中所有要用到的变量,以及
#define OnMySocketMessage 111111
为监听Socket对象的消息;
#define OnAcceptSocket 222222
为用于连接的Socket对象的消息
*/
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
//RECT r;
//TCHAR text[] = _T("");

switch (message)
{
case WM_CREATE:
//-----------------------------------------
//-------------Winsock内容-----------------
//-----------------------------------------
// 初始化WinSock
WSAStartup((WORD)(1<<8|1),&WSAData);
//建立侦听所用的socket
MySocket = socket(PF_INET,SOCK_STREAM,0);
//绑定端口
memset(&MyName,0,sizeof(MyName));//初始化mysock结构体名
MyName.sin_addr.s_addr=htonl(INADDR_ANY);//IP地址。#define s_addr S_un.S_addr
MyName.sin_family=AF_INET;//只能是这个值
MyName.sin_port=htons(1024);//端口
bind(MySocket,(sockaddr *) &MyName,sizeof(MyName));//绑定端口

//侦听
listen(MySocket,3);
//注册连接消息回调
WSAAsyncSelect(MySocket,hWnd,OnMySocketMessage, FD_READ|FD_WRITE|FD_OOB|FD_ACCEPT|FD_CONNECT|FD_CLOSE);//希望套接字在收到请求时产生消息
//-----------------------------------------
//-------------Winsock内容完---------------
//-----------------------------------------

case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// 分析菜单选择:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
//绘图或文本输出代码
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
closesocket(MySocket);
closesocket(AcceptSocket);
WSACleanup();
PostQuitMessage(0);
break;
case OnMySocketMessage://套接字消息
switch(lParam)
{
case FD_ACCEPT://收到连接请求
CustomNameLen=sizeof(CustomName);
AcceptSocket = accept(MySocket,(sockaddr *)&CustomName,&CustomNameLen);//相应连接
WSAAsyncSelect(AcceptSocket,hWnd,OnAcceptSocket, FD_READ|FD_WRITE|FD_OOB|FD_ACCEPT|FD_CONNECT|FD_CLOSE);//希望套接字在收到请求时产生消息
break;
case FD_CONNECT://连接成功
break;
case FD_CLOSE://连接关闭
closesocket(MySocket);//关闭连接
WSACleanup();
break;
}
case OnAcceptSocket:
switch(lParam)
{
case FD_READ://收到数据
char text[225];
recv(MySocket,&text[0],sizeof(text),0);
break;
case FD_WRITE://发送数据
break;
case FD_OOB://收到带外数据
break;
case FD_ACCEPT://收到连接请求
break;
case FD_CONNECT://连接成功
break;
case FD_CLOSE://连接关闭
closesocket(MySocket);//关闭连接
WSACleanup();
break;
}
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}

对于服务器。很多教程都说最开始建立一个Socket来监听,收到连接请求之后调用accept来响应,同时这个函数成功之后将返回一个用于连接的Socket。
问题一:返回的用于连接的Socket,是不是和客户端的实际连接是由他完成的?
问题二:如果是,那是不是也要调用WSAAsyncSelect函数,以返回的Socket为参数注册他的网络消息回调啊啊??(就像我上面写的代码那样)



现在,我先启动服务器,在启动客户端,在客户端启动成功之后,服务器的MySocket(用于侦听的的Socket)收到lParam包含FD_ACCEPT的OnMySocketMessage消息。我按照上面所说的调用accept来响应,也要调用WSAAsyncSelect函数,以返回的AcceptSocket为参数注册他的网络消息回调(如代码)。执行了之后随即收到OnAcceptSocket消息,但是lParam中包含的值是8.不是上面定义的FD_READ等6个常数中的任何一个?这是怎么回事?

客户端这边跟服务器很相似(准确说客户端就是服务器的项目复制了一份改过来的),照贴代码吧,客户端的问题不多,就是……那个该死的消息从头到尾一次都没收到过


LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
char text[]={"My infomation"};

switch (message)
{
case WM_CREATE:
//-----------------------------------------
//-------------Winsock内容-----------------
//-----------------------------------------
// 初始化WinSock
WSAStartup((WORD)(1<<8|1),&WSAData);
//建立侦听所用的socket
MySocket = socket(PF_INET,SOCK_STREAM,0);
//绑定端口
memset(&MyName,0,sizeof(MyName));//初始化mysock结构体名
MyName.sin_addr.s_addr=inet_addr("127.0.0.1");//IP地址。#define s_addr S_un.S_addr
MyName.sin_family=AF_INET;//只能是这个值
MyName.sin_port=htons(1024);//端口
//连接
connect(MySocket,(sockaddr *) &MyName,sizeof(MyName));
//注册连接消息回调
WSAAsyncSelect(MySocket,hWnd,OnMySocketMessage, FD_READ|FD_WRITE|FD_OOB|FD_ACCEPT|FD_CONNECT|FD_CLOSE);//希望套接字在收到请求时产生消息
//-----------------------------------------
//-------------Winsock内容完---------------
//-----------------------------------------

case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// 分析菜单选择:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
//绘图或文本输出代码
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
closesocket(MySocket);
WSACleanup();
PostQuitMessage(0);
break;
case OnMySocketMessage://套接字消息
switch(lParam)
{
case FD_READ://收到数据
break;
case FD_WRITE://发送数据
break;
case FD_OOB://收到带外数据
break;
case FD_ACCEPT://收到连接请求
break;
case FD_CONNECT://连接成功
send(MySocket,&text[0],sizeof(text),0);
break;
case FD_CLOSE://连接关闭
closesocket(MySocket);//关闭连接
WSACleanup();
break;
}
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}

问题暂时就那么多,希望大神们看看吧~~
[解决办法]
accept返回的Socket,是与客户端的连接,之后的发送接收由他完成。不调用WSAAsyncSelect是,他继承listen socket的消息和事件。另外修改 Select为:WSAAsyncSelect(AcceptSocket,hWnd,OnAcceptSocket, FD_READ
[解决办法]
FD_WRITE
[解决办法]
FD_OOB
[解决办法]
FD_CONNECT
[解决办法]
FD_CLOSE);建议你参考《WinSock网络编程经络》,socket例子源码下载地址:
http://download.csdn.net/detail/geoff08zhang/4571358
------解决方案--------------------


引用:
引用:accept返回的Socket,是与客户端的连接,之后的发送接收由他完成。不调用WSAAsyncSelect是,他继承listen socket的消息和事件。另外修改 Select为:WSAAsyncSelect(AcceptSocket,hWnd,OnAcceptSocket, FD_READ
[解决办法]
FD_WRITE
[解决办法]
FD_OOB
[解决办法]
FD……
客户端收不到消息是因为你在服务器端并没有给客户端发送消息,没有send函数调用么;不明白为什么你非要用1024端口号,个人服务一般的端口号在1024和65535之间,是开区间,你的代码没法调,你可以贴出来一些错误信息,帮你看看,先这么多了
[解决办法]
case FD_ACCEPT://收到连接请求
CustomNameLen=sizeof(CustomName);
AcceptSocket = accept(MySocket,(sockaddr *)&CustomName,&CustomNameLen);//相应连接
WSAAsyncSelect(AcceptSocket,hWnd,OnAcceptSocket, FD_READ
[解决办法]
FD_WRITE
[解决办法]
FD_OOB
[解决办法]
FD_ACCEPT
[解决办法]
FD_CONNECT
[解决办法]
FD_CLOSE);//希望套接字在收到请求时产生消息
break;

服务器在上面已经使用了异步模型
//注册连接消息回调
WSAAsyncSelect(MySocket,hWnd,OnMySocketMessage, FD_READ
[解决办法]
FD_WRITE
[解决办法]
FD_OOB
[解决办法]
FD_ACCEPT
[解决办法]
FD_CONNECT
[解决办法]
FD_CLOSE);//希望套接字在收到请求时产生消息
//-----------------------------------------
//-------------Winsock内容完---------------
为什么FD_ACCEPT之后又要用一次异步模型,这是其一

其二,你在客户端FD_CONNECT之后
case FD_CONNECT://连接成功
send(MySocket,&text[0],sizeof(text),0);
发送消息给服务器吗?那你说客户端收不到消息,又是怎么个意思

代码能通过编译没错,但是细细看问题不少,你再研究研究异步SOCKET的模型呢
[解决办法]
引用:
引用:调试Socket有时必须用抓包工具抓包。能详细说一下吗?为什么呢?

不用抓包工具抓包,无法确定是发送方未实际发送或发送数据格式未按约定还是接收方未按约定解析数据。

读书人网 >C++

热点推荐