MFC下CSocket编程详解

本文详细介绍了在MFC环境下使用CSocket进行Socket编程的方法,包括常用的函数、注意事项及实例代码。

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程序时,必须要包含<afxsock.h>都文件。

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

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

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

1) 客户端主要代码:

// 初始化
AfxSocketInit();

// 创建 CSocket 对象
CSocket aSocket;

CString strIP;
CString strPort;
CString strText;

this -> GetDlgItem(IDC_EDIT_IP) -> GetWindowText(strIP);
this -> GetDlgItem(IDC_EDIT_PORT) -> GetWindowText(strPort);
this -> GetDlgItem(IDC_EDIT_TEXT) -> GetWindowText(strText);

// 初始化 CSocket 对象, 因为客户端不需要绑定任何端口和地址, 所以用默认参数即可
if ( ! aSocket.Create())
... {
char szMsg[1024] = ...{0};

sprintf(szMsg, "create faild: %d", aSocket.GetLastError());

AfxMessageBox(szMsg);
return;
}


// 转换需要连接的端口内容类型
int nPort = atoi(strPort);

// 连接指定的地址和端口
if (aSocket.Connect(strIP, nPort))
... {
char szRecValue[1024] = ...{0};

//发送内容给服务器
aSocket.Send(strText, strText.GetLength());

//接收服务器发送回来的内容(该方法会阻塞, 在此等待有内容接收到才继续向下执行)
aSocket.Receive((void *)szRecValue, 1024);

AfxMessageBox(szRecValue);
}

else
... {
char szMsg[1024] = ...{0};

sprintf(szMsg, "create faild: %d", aSocket.GetLastError());

AfxMessageBox(szMsg);
}


// 关闭
aSocket.Close();

2)服务器端代码:

unsigned int StartServer(LPVOID lParam)
... {
//初始化Winscok
if (!AfxSocketInit())
...{
AfxMessageBox(IDP_SOCKETS_INIT_FAILED);
return 1;
}


m_exit = false;

CServerDlg *aDlg = (CServerDlg *)lParam;

CString strPort;

aDlg->GetDlgItemText(IDC_EDIT_PORT, strPort);

UINT nPort = atoi(strPort);

//socket------------------------------------------------

CSocket aSocket, serverSocket;
//最好不要使用aSocket.Create创建,因为容易会出现10048错误 if (!aSocket.Socket())
...{
char szError[256] = ...{0};

sprintf(szError, "Create Faild: %d", GetLastError());

AfxMessageBox(szError);

return 1;
}


BOOL bOptVal = TRUE;
int bOptLen = sizeof(BOOL);

//设置Socket的选项, 解决10048错误必须的步骤
aSocket.SetSockOpt(SO_REUSEADDR, ( void * ) & bOptVal, bOptLen, SOL_SOCKET);
//监听
if ( ! aSocket.Listen( 10 ))
... {
char szError[256] = ...{0};

sprintf(szError, "Listen Faild: %d", GetLastError());

AfxMessageBox(szError);

return 1;
}


CString strText;

aDlg -> GetDlgItemText(IDC_EDIT_LOG, strText);

strText += " Server Start! " ;

aDlg -> SetDlgItemText(IDC_EDIT_LOG, strText);

while ( ! m_exit)
... {
//接收外部连接 if(!aSocket.Accept(serverSocket))
...{
continue;
}

else
...{
char szRecvMsg[256] = ...{0};
char szOutMsg[256] = ...{0};
//接收客户端内容:阻塞 serverSocket.Receive(szRecvMsg, 256);

sprintf(szOutMsg, "Receive Msg: %s ", szRecvMsg);

aDlg->GetDlgItemText(IDC_EDIT_LOG, strText);

strText += szOutMsg;

aDlg->SetDlgItemText(IDC_EDIT_LOG, strText);
//发送内容给客户端
serverSocket.Send("Have Receive The Msg", 50);
//关闭 serverSocket.Close();
}

}
//关闭
aSocket.Close();
serverSocket.Close();

aDlg -> GetDlgItemText(IDC_EDIT_LOG, strText);

strText += " Have Close! " ;

aDlg -> SetDlgItemText(IDC_EDIT_LOG, strText);

return 0 ;
}


//绑定端口 if ( ! aSocket.Bind(nPort))
... {
char szError[256] = ...{0};

sprintf(szError, "Bind Faild: %d", GetLastError());

AfxMessageBox(szError);

return 1;
}

3) SDK 下的服务器端代码

// 子线程函数
unsigned int StartServer(LPVOID lParam)
... {

//初始化Winsock, AfxSocketInit() 也是封装了这些语句, 不过 AfxSocketInit() 所做的事比这里多些

WSADATA wsaData;

//Winsock 的版本, 建议用1.1 ,兼容性好
WORD wVersionRequested = MAKEWORD(1, 1);
int nResult = WSAStartup(wVersionRequested, &wsaData);
if (nResult != 0)
...{
return 1;
}


//-----------------------------------------------------

m_exit = false;

CServerDlg *aDlg = (CServerDlg *)lParam;

CString strPort;

aDlg->GetDlgItemText(IDC_EDIT_PORT, strPort);

UINT nPort = atoi(strPort);

//socket------------------------------------------------

//接口对象
SOCKET aSocket, serverSocket;

//寻址相关结构
sockaddr_in serverSockaddr;
memset(&serverSockaddr, 0, sizeof(serverSockaddr));


aSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

if (aSocket == INVALID_SOCKET)
...{
char szError[256] = ...{0};

sprintf(szError, "Create Faild: %d", GetLastError());

AfxMessageBox(szError);

return 1;
}


//注意,该处非常重要,取值的正确与否决定关闭scoket后端口是否能正常释放
BOOL bOptVal = TRUE;
int bOptLen = sizeof(BOOL);

//设置 socket 选项, SOL_SOCKET 和 SO_REUSEADDR 一起使用, 并且后面的参数如上,
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值