由于项目的需要,在学习使用socket使用socket,记录自己碰到的一个问题。
MFC编程中,习惯使用CSocket,而在控制台程序中只能使用SOCKET套接字。若全为MFC,则其通信比较容易.
服务端创建监听套接字,并监听:
CListenSocket *cLisSoc = new CListenSocket();
cLisSoc->Create(5555,SOCK_STREAM,”127.0.0.1“);
cLisSoc->Listen();
客户端创建客户端套接字,连接
CClientSocket *cSock = new CClientSocket();
cSock->Create();
cSock->Connect("127.0.0.1",5555);
其中CListenSocket,CClientSocket均为继承于CSocket的自定义类。
这样可以完成套接字的连接。
然,要将MFC的CSocket和控制台的SOCKET连接 C1:
客户端:
SOCKET clientS = socket(AF_INET,SOCK_STREAM,0);
sockaddr_in sockSerClient;
sockSerClient.sin_family = AF_INET;
sockSerClient.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
sockSerClient.sin_port = 5555;
int len = sizeof(sockaddr);
int a = connect(clientS,(sockaddr *)&sockSerClient,len);
服务端:
CListenSocket *cLisSoc = new CListenSocket();
cLisSoc->Create(5555,SOCK_STREAM,”127.0.0.1“);
cLisSoc->Listen();
这样会出现问题,在连接的时候会提示10061的错误,意思是强行拒绝连接。
在使用Create方法创建套接字的时候实际上已经调用了Bind的方法,如果再次调用Bind方法会提示10022的错误,意思是已经绑定。
显然这样连接存在错误。CSocket的Connect重载了两个方法:
BOOL Connect( LPCTSTR lpszHostAddress, UINT nHostPort );
BOOL Connect( const SOCKADDR* lpSockAddr, int nSockAddrLen );
若以CSocket创建客户端套接字:
sockaddr_in sockSer;
sockSer.sin_family = AF_INET;
sockSer.sin_addr.S_un.S_addr = inet_addr(m_ipAddr.c_str());
sockSer.sin_port = m_nPort;
int len = sizeof(sockaddr);
BOOL con = Connect((sockaddr *)&sockSer,len);
SOCKET创建服务端套接字:
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = 7777;
addr.sin_addr.S_un.S_addr =inet_addr("127.0.0.1");
bind(serSock, (sockaddr*)&addr, sizeof(sockaddr_in));
listen(serSock, 5); //5 表示同时允许有多少个连接请求
这样是可以连接的。这样看来,C1的解决方案也得使用SOCKET,而不用Create方法。最后查MSDN,找到解决方案:
客户端:
SOCKET clientS = socket(AF_INET,SOCK_STREAM,0);
sockaddr_in sockSerClient;
sockSerClient.sin_family = AF_INET;
sockSerClient.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
sockSerClient.sin_port = 5555;
int len = sizeof(sockaddr);
int a = connect(clientS,(sockaddr *)&sockSerClient,len);
服务端:
CListenSocket *cLisSoc = new CListenSocket();
/***********代替Create***********************************/
sockaddr_in sockSer;
sockSer.sin_family = AF_INET;
sockSer.sin_addr.S_un.S_addr = inet_addr(ipAddr);
sockSer.sin_port = nPort;
SOCKET s = socket(AF_INET,SOCK_STREAM,0);
cLisSoc->Attach(s);
int len = sizeof(sockaddr);
int a = cLisSoc->Bind((sockaddr*)&sockSer,len);
int b = GetLastError();
/*****************************************************/
cLisSoc->Listen();
在我曾经的理解中,认为Create()方法应该做了上述的操作了的,在msdn中也说Create方法,会创建一个window socket并附加到这个对象当中的。创建完之后需要调用Bind,而实际使用过程中,调用了Create(),基本上不用调用Bind()方法,即使使用了,GetLastError()和提示10022的错误。至于为什么C1会不能连接,目前还没有想清楚,在解决之中。