socket与WSASocket互连?

qw317079258 2014-03-29 11:40:23
现在很多windows的服务器都用IOCP,那么socket就是用WSASocket创建的。那么如果客户端用原始的::socket(AF_INET, SOCK_STREAM,0)来创建,能否连接上IOCP的服务器么?目前我测试的结果是不能,::connect返回-1。那么是不是表示IOCP的服务器只支持Windows的客户端来连接呢?因为WSASocket是微软的API啊。
一下是代码:
服务器:
// IOCPServer.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <winsock2.h>
#include <mswsock.h>
#include <process.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <mmsystem.h>
#include <iostream>
typedef unsigned (__stdcall *PBEGINTHREADX_THREADFUN)(void* lpParameter);
#pragma comment(lib,"ws2_32.lib")
#pragma comment(lib,"Mswsock.lib")
#pragma comment(lib,"Winmm.lib")

class MyOverLapped :public WSAOVERLAPPED
{
public:
enum
{
en_INVALID = 0,
en_ACCEPT,
en_SEND,
en_RECEIVE,
en_MAX
};
SOCKET m_socket;
int m_opt;

MyOverLapped()
{
memset(this,0,sizeof(*this));

}
};

HANDLE gCompletion = 0;
LPFN_ACCEPTEX gFnAcceptEx;
LPFN_GETACCEPTEXSOCKADDRS gFnGetAcceptExSockaddrs;

unsigned WINAPI MyOnAccept(void* lpParam)
{
DWORD dwTrans = 0;
DWORD dwKey = 0;
LPOVERLAPPED lpol;

while (true)
{
BOOL bOK = ::GetQueuedCompletionStatus(gCompletion,
&dwTrans, (LPDWORD)&dwKey, (LPOVERLAPPED*)&lpol, WSA_INFINITE);
if (bOK == false)
{
std::cout<<"get出错了啊"<<std::endl;
continue;
}
if (lpol == NULL)
{
std::cout<<"lpol == NULL"<<std::endl;
continue;
}
MyOverLapped* pMyOverLapped = (MyOverLapped*)lpol;
if (pMyOverLapped->m_opt == MyOverLapped::en_ACCEPT)//接受的
{
// 关联新连接到完成端口对象
::CreateIoCompletionPort((HANDLE)pMyOverLapped->m_socket, gCompletion, (DWORD)pMyOverLapped, 0);
// receive
char* buf = new char[1024] ;
WSABUF wsaBuf;
wsaBuf.buf = buf;
wsaBuf.len = 1024;
DWORD dwBytes = 0;
DWORD dwFlags = 0;
pMyOverLapped->m_opt = MyOverLapped::en_RECEIVE;
if (::WSARecv(pMyOverLapped->m_socket, &wsaBuf, 1, &dwBytes, &dwFlags, (LPWSAOVERLAPPED)pMyOverLapped, NULL) != NO_ERROR)
{
if(::WSAGetLastError() != WSA_IO_PENDING)
{
std::cout<<"WSARecv失败!!!"<<std::endl;
system("pause");
return 0;
}
}
}
else if(pMyOverLapped->m_opt == MyOverLapped::en_RECEIVE)
{
std::cout<<"接收成功啦!!!"<<std::endl;
}
}

return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
WSADATA wsaData;
WORD wVersion = MAKEWORD(2, 2);
if (::WSAStartup(wVersion, &wsaData) != 0)
{
std::cout<<"初始化soket服务失败!!!"<<std::endl;
system("pause");
return 0;
}

//创建socket监听本地端口
SOCKET stMySocket = ::WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
const char flag = 0;
if (setsockopt(stMySocket,SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)) != 0)
{
std::cout<<"socket设置重用地址失败!!!"<<std::endl;
system("pause");
return 0;
}
SOCKADDR_IN si;
si.sin_family = AF_INET;
si.sin_port = ::htons(8081);
si.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
if(::bind(stMySocket, (sockaddr*)&si, sizeof(si)) == SOCKET_ERROR)
{
std::cout<<"socket绑定失败!!!"<<std::endl;
system("pause");
return 0;
}
::listen(stMySocket, 200);

GUID GuidAcceptEx = WSAID_ACCEPTEX;
DWORD dwBytes;
::WSAIoctl(stMySocket,
SIO_GET_EXTENSION_FUNCTION_POINTER,
&GuidAcceptEx,
sizeof(GuidAcceptEx),
&gFnAcceptEx,
sizeof(gFnAcceptEx),
&dwBytes,
NULL,
NULL);

// 加载扩展函数GetAcceptExSockaddrs
GUID GuidGetAcceptExSockaddrs = WSAID_GETACCEPTEXSOCKADDRS;
::WSAIoctl(stMySocket,
SIO_GET_EXTENSION_FUNCTION_POINTER,
&GuidGetAcceptExSockaddrs,
sizeof(GuidGetAcceptExSockaddrs),
&gFnGetAcceptExSockaddrs,
sizeof(gFnGetAcceptExSockaddrs),
&dwBytes,
NULL,
NULL
);

// 创建完成端口对象
gCompletion = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0);
// 将监听套节字关联到完成端口
::CreateIoCompletionPort((HANDLE)stMySocket, gCompletion, (DWORD)0, 0);

//accept
MyOverLapped* pWSAOverLapped = new MyOverLapped;
pWSAOverLapped->m_opt = MyOverLapped::en_ACCEPT;
pWSAOverLapped->m_socket= WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
char* buff = new char[1024];

bool rst = gFnAcceptEx(stMySocket,
pWSAOverLapped->m_socket,
buff,
1024-((sizeof(sockaddr_in) + 16) * 2),
sizeof(sockaddr_in) + 16,
sizeof(sockaddr_in) + 16,
&dwBytes,
(WSAOVERLAPPED*)pWSAOverLapped
);
if(!rst && ::WSAGetLastError() != WSA_IO_PENDING)
{
std::cout<<"socket accept 错误!!!"<<::WSAGetLastError()<<std::endl;
system("pause");
return 0;
}

//创建监听线程
_beginthreadex(NULL, 0, (PBEGINTHREADX_THREADFUN)MyOnAccept, 0, 0, NULL);

HANDLE hEvent = ::CreateEvent(NULL, FALSE, FALSE, TEXT("ShutdownEvent"));
::WaitForSingleObject(hEvent, INFINITE);
::CloseHandle(hEvent);

std::cout<<"服务器关闭!!!"<<std::endl;
system("pause");
return 0;
}






客户端:
// IOCPClient.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <winsock2.h>
#include <mswsock.h>
#include <process.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <mmsystem.h>
#include <iostream>
#pragma comment(lib,"ws2_32.lib")
#pragma comment(lib,"Mswsock.lib")
#pragma comment(lib,"Winmm.lib")



int _tmain(int argc, _TCHAR* argv[])
{
// WSADATA wsaData;
// WORD wVersion = MAKEWORD(2, 2);
// if (::WSAStartup(wVersion, &wsaData) != 0)
// {
// std::cout<<"初始化soket服务失败!!!"<<std::endl;
// system("pause");
// return 0;
// }

//SOCKET mySocket=::WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
SOCKET mySocket = ::socket(AF_INET, SOCK_STREAM,0);
SOCKADDR_IN si;
si.sin_family = AF_INET;
si.sin_port = ::htons(8081);
si.sin_addr.S_un.S_addr = htonl(INADDR_LOOPBACK);

int rst =::connect(mySocket, (sockaddr*)&si, sizeof(si));
if (rst == 0)
{
rst = ::send(mySocket,"12345",6,MSG_OOB);
}
while (true)
{
char cmd[125]={0};
std::cin>>cmd;
}
}



求大神解读
...全文
155 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
qw317079258 2014-03-29
  • 打赏
  • 举报
回复
已经发现问题了。。。很低级,客户端需要使用新版本的socket,也就是客户端需要下面这段代码: WSADATA wsaData; WORD wVersion = MAKEWORD(2, 2); if (::WSAStartup(wVersion, &wsaData) != 0) { std::cout<<"初始化soket服务失败!!!"<<std::endl; system("pause"); return 0; }
zybjtu 2014-03-29
  • 打赏
  • 举报
回复
恭喜卤煮

3,881

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 其它技术问题
社区管理员
  • 其它技术问题社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧