MFC下CSocket编程详解

该示例代码在VS2003下联调通过。

[@more@]MFC下CSocket编程详解

转自: http://blog.csdn.net/yejiansnake/archive/2008/03/13/2175778.aspx


MFC下CSocket编程详解:

1. 常用的函数和注意事项(详细的函数接口说明请查看MSDN):

CSocket::Create 初始化(一般写服务器程序都不要用为好,用下面的 CSocket::Socket 初始化)

CSocket::Socket初始化

CSocket::SetSockOpt 设置socket选项

CSocket::Bind 绑定地址端口

CSocket::Connect 连接

CSocket::Listen 监听

CSocket::Accept 接收外部连接的socket

CSocket::Send 发送内容

CSocket::Receive 接收内容

CSocket::Close 关闭(不等于delete)

1) 在使用MFC编写socket程序时,必须要包含都文件。

2) AfxSocketInit() 这个函数,在使用CSocket前一定要先调用该函数,否则使用CSocket会出错;并且该函数还有一个重要的使用方式,
就是在某个线程下使用 CSocket 前一定要调用,就算主线程调用了该函数,在子线程下使用 CSocket 也要先调用该函数,要不会出错。

3) 还要注意的是, Create 方法已经包含了 Bind 方法,如果是以 Create 方法初始化的前提下不能再调用 Bind ,要不一定出错。

2. 以下是使用例子代码,通过例子来学习如何使用 CSocket 进行编程, 并且附件上有完整的例子代码。例子的可以在我的发布资源中找到:MFC下CSocket编程例子 http://download.csdn.net/source/379597

1) 客户端主要代码:

None.gif // 初始化
None.gif AfxSocketInit();
None.gif
None.gif // 创建 CSocket 对象
None.gif CSocket aSocket;
None.gif
None.gif CString strIP;
None.gif CString strPort;
None.gif CString strText;
None.gif
None.gif this -> GetDlgItem(IDC_EDIT_IP) -> GetWindowText(strIP);
None.gif this -> GetDlgItem(IDC_EDIT_PORT) -> GetWindowText(strPort);
None.gif this -> GetDlgItem(IDC_EDIT_TEXT) -> GetWindowText(strText);
None.gif
None.gif // 初始化 CSocket 对象, 因为客户端不需要绑定任何端口和地址, 所以用默认参数即可
None.gif if ( ! aSocket.Create())
ExpandedBlockStart.gifContractedBlock.gif ... {
ExpandedSubBlockStart.gifContractedSubBlock.gifchar szMsg[1024] = ...{0};
InBlock.gif
InBlock.gif sprintf(szMsg, "create faild: %d", aSocket.GetLastError());
InBlock.gif
InBlock.gif AfxMessageBox(szMsg);
InBlock.gifreturn;
ExpandedBlockEnd.gif }

None.gif
None.gif // 转换需要连接的端口内容类型
None.gif int nPort = atoi(strPort);
None.gif
None.gif // 连接指定的地址和端口
None.gif if (aSocket.Connect(strIP, nPort))
ExpandedBlockStart.gifContractedBlock.gif ... {
ExpandedSubBlockStart.gifContractedSubBlock.gifchar szRecValue[1024] = ...{0};
InBlock.gif
InBlock.gif//发送内容给服务器
InBlock.gif aSocket.Send(strText, strText.GetLength());
InBlock.gif
InBlock.gif//接收服务器发送回来的内容(该方法会阻塞, 在此等待有内容接收到才继续向下执行)
InBlock.gif aSocket.Receive((void *)szRecValue, 1024);
InBlock.gif
InBlock.gif AfxMessageBox(szRecValue);
ExpandedBlockEnd.gif }

None.gif else
ExpandedBlockStart.gifContractedBlock.gif ... {
ExpandedSubBlockStart.gifContractedSubBlock.gifchar szMsg[1024] = ...{0};
InBlock.gif
InBlock.gif sprintf(szMsg, "create faild: %d", aSocket.GetLastError());
InBlock.gif
InBlock.gif AfxMessageBox(szMsg);
ExpandedBlockEnd.gif }

None.gif
None.gif // 关闭
None.gif aSocket.Close();
None.gif

2)服务器端代码:

None.gif unsigned int StartServer(LPVOID lParam)
ExpandedBlockStart.gifContractedBlock.gif ... {
//初始化Winscok
InBlock.gifif (!AfxSocketInit())
ExpandedSubBlockStart.gifContractedSubBlock.gif...{
InBlock.gif AfxMessageBox(IDP_SOCKETS_INIT_FAILED);
InBlock.gifreturn 1;
ExpandedSubBlockEnd.gif }

InBlock.gif
InBlock.gif m_exit = false;
InBlock.gif
InBlock.gif CServerDlg *aDlg = (CServerDlg *)lParam;
InBlock.gif
InBlock.gif CString strPort;
InBlock.gif
InBlock.gif aDlg->GetDlgItemText(IDC_EDIT_PORT, strPort);
InBlock.gif
InBlock.gif UINT nPort = atoi(strPort);
InBlock.gif
InBlock.gif//socket------------------------------------------------
InBlock.gif
InBlock.gif CSocket aSocket, serverSocket;
InBlock.gif//最好不要使用aSocket.Create创建,因为容易会出现10048错误InBlock.gifif (!aSocket.Socket())
ExpandedSubBlockStart.gifContractedSubBlock.gif...{
ExpandedSubBlockStart.gifContractedSubBlock.gifchar szError[256] = ...{0};
InBlock.gif
InBlock.gif sprintf(szError, "Create Faild: %d", GetLastError());
InBlock.gif
InBlock.gif AfxMessageBox(szError);
InBlock.gif
InBlock.gifreturn 1;
ExpandedSubBlockEnd.gif }

InBlock.gif
InBlock.gif BOOL bOptVal = TRUE;
InBlock.gifint bOptLen = sizeof(BOOL);

InBlock.gif //设置Socket的选项, 解决10048错误必须的步骤
InBlock.gif aSocket.SetSockOpt(SO_REUSEADDR, ( void * ) & bOptVal, bOptLen, SOL_SOCKET);
//监听
InBlock.gif if ( ! aSocket.Listen( 10 ))
ExpandedSubBlockStart.gifContractedSubBlock.gif ... {
ExpandedSubBlockStart.gifContractedSubBlock.gifchar szError[256] = ...{0};
InBlock.gif
InBlock.gif sprintf(szError, "Listen Faild: %d", GetLastError());
InBlock.gif
InBlock.gif AfxMessageBox(szError);
InBlock.gif
InBlock.gifreturn 1;
ExpandedSubBlockEnd.gif }

InBlock.gif
InBlock.gif CString strText;
InBlock.gif
InBlock.gif aDlg -> GetDlgItemText(IDC_EDIT_LOG, strText);
InBlock.gif
InBlock.gif strText += " Server Start! " ;
InBlock.gif
InBlock.gif aDlg -> SetDlgItemText(IDC_EDIT_LOG, strText);
InBlock.gif
InBlock.gif while ( ! m_exit)
ExpandedSubBlockStart.gifContractedSubBlock.gif ... {
InBlock.gif//接收外部连接InBlock.gifif(!aSocket.Accept(serverSocket))
ExpandedSubBlockStart.gifContractedSubBlock.gif...{
InBlock.gifcontinue;
ExpandedSubBlockEnd.gif }

InBlock.gifelse
ExpandedSubBlockStart.gifContractedSubBlock.gif...{
ExpandedSubBlockStart.gifContractedSubBlock.gifchar szRecvMsg[256] = ...{0};
ExpandedSubBlockStart.gifContractedSubBlock.gifchar szOutMsg[256] = ...{0};
InBlock.gif
//接收客户端内容:阻塞InBlock.gif serverSocket.Receive(szRecvMsg, 256);
InBlock.gif
InBlock.gif sprintf(szOutMsg, "Receive Msg: %s ", szRecvMsg);
InBlock.gif
InBlock.gif aDlg->GetDlgItemText(IDC_EDIT_LOG, strText);
InBlock.gif
InBlock.gif strText += szOutMsg;
InBlock.gif
InBlock.gif aDlg->SetDlgItemText(IDC_EDIT_LOG, strText);
InBlock.gif
//发送内容给客户端
InBlock.gif serverSocket.Send("Have Receive The Msg", 50);
InBlock.gif
//关闭InBlock.gif serverSocket.Close();
ExpandedSubBlockEnd.gif }
InBlock.gif
ExpandedSubBlockEnd.gif }
InBlock.gif
//关闭
InBlock.gif aSocket.Close();
InBlock.gif serverSocket.Close();
InBlock.gif
InBlock.gif aDlg -> GetDlgItemText(IDC_EDIT_LOG, strText);
InBlock.gif
InBlock.gif strText += " Have Close! " ;
InBlock.gif
InBlock.gif aDlg -> SetDlgItemText(IDC_EDIT_LOG, strText);
InBlock.gif
InBlock.gif return 0 ;
ExpandedBlockEnd.gif}

InBlock.gif
InBlock.gif//绑定端口InBlock.gif if ( ! aSocket.Bind(nPort))
ExpandedSubBlockStart.gifContractedSubBlock.gif ... {
ExpandedSubBlockStart.gifContractedSubBlock.gifchar szError[256] = ...{0};
InBlock.gif
InBlock.gif sprintf(szError, "Bind Faild: %d", GetLastError());
InBlock.gif
InBlock.gif AfxMessageBox(szError);
InBlock.gif
InBlock.gifreturn 1;
ExpandedSubBlockEnd.gif }

InBlock.gif

3) SDK 下的服务器端代码

None.gif // 子线程函数
None.gif unsigned int StartServer(LPVOID lParam)
ExpandedBlockStart.gifContractedBlock.gif ... {
InBlock.gif
InBlock.gif//初始化Winsock, AfxSocketInit() 也是封装了这些语句, 不过 AfxSocketInit() 所做的事比这里多些
InBlock.gif
InBlock.gif WSADATA wsaData;
InBlock.gif
InBlock.gif//Winsock 的版本, 建议用1.1 ,兼容性好
InBlock.gif WORD wVersionRequested = MAKEWORD(1, 1);
InBlock.gifint nResult = WSAStartup(wVersionRequested, &wsaData);
InBlock.gifif (nResult != 0)
ExpandedSubBlockStart.gifContractedSubBlock.gif...{
InBlock.gifreturn 1;
ExpandedSubBlockEnd.gif }

InBlock.gif
InBlock.gif//-----------------------------------------------------
InBlock.gif
InBlock.gif m_exit = false;
InBlock.gif
InBlock.gif CServerDlg *aDlg = (CServerDlg *)lParam;
InBlock.gif
InBlock.gif CString strPort;
InBlock.gif
InBlock.gif aDlg->GetDlgItemText(IDC_EDIT_PORT, strPort);
InBlock.gif
InBlock.gif UINT nPort = atoi(strPort);
InBlock.gif
InBlock.gif//socket------------------------------------------------
InBlock.gif
InBlock.gif//接口对象
InBlock.gif SOCKET aSocket, serverSocket;
InBlock.gif
InBlock.gif//寻址相关结构
InBlock.gif sockaddr_in serverSockaddr;
InBlock.gif memset(&serverSockaddr, 0, sizeof(serverSockaddr));
InBlock.gif
InBlock.gif
InBlock.gif aSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
InBlock.gif
InBlock.gifif (aSocket == INVALID_SOCKET)
ExpandedSubBlockStart.gifContractedSubBlock.gif...{
ExpandedSubBlockStart.gifContractedSubBlock.gifchar szError[256] = ...{0};
InBlock.gif
InBlock.gif sprintf(szError, "Create Faild: %d", GetLastError());
InBlock.gif
InBlock.gif AfxMessageBox(szError);
InBlock.gif
InBlock.gifreturn 1;
ExpandedSubBlockEnd.gif }

InBlock.gif
InBlock.gif//注意,该处非常重要,取值的正确与否决定关闭scoket后端口是否能正常释放
InBlock.gif BOOL bOptVal = TRUE;
InBlock.gifint bOptLen = sizeof(BOOL);
InBlock.gif
InBlock.gif//设置 socket 选项, SOL_SOCKET 和 SO_REUSEADDR 一起使用, 并且后面的参数如上,
InBlock.gif

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/143526/viewspace-1045771/,如需转载,请注明出处,否则将追究法律责任。

user_pic_default.png
请登录后发表评论 登录
全部评论
<%=items[i].createtime%>

<%=items[i].content%>

<%if(items[i].items.items.length) { %>
<%for(var j=0;j
<%=items[i].items.items[j].createtime%> 回复

<%=items[i].items.items[j].username%>   回复   <%=items[i].items.items[j].tousername%><%=items[i].items.items[j].content%>

<%}%> <%if(items[i].items.total > 5) { %>
还有<%=items[i].items.total-5%>条评论 ) data-count=1 data-flag=true>点击查看
<%}%>
<%}%>
<%}%>

转载于:http://blog.itpub.net/143526/viewspace-1045771/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值