TCP接收发送

简介:

  TCP有客户端和服务端,简称Client和Server。下面就介绍如何创建以及乱码等处理。


1.服务端

1)首先要新建两个类,基类为CAsyncSocket,一个是类作用是监听,另一个类作用是重写发送和接收函数。

class CListenSocket : public CAsyncSocket
class COverwriteSocket : public CAsyncSocket


2)服务端的监听类

1)创建和监听

void CTcpAsynSDlg::OnButtonTcpServer() 
{
	// TODO: Add your control notification handler code here
	GetDlgItem(IDC_BUTTON_TcpServer)->SetWindowText(_T("服务器打开"));

	if (m_ListenSocket.m_hSocket == INVALID_SOCKET)
	{
		BOOL bFlag = m_ListenSocket.Create(8888, SOCK_STREAM, FD_ACCEPT);  //创建

		if (!bFlag)
		{
			AfxMessageBox("Socket创建失败!");
			m_bIsTcpOpen = FALSE;
			return;
		}

		if (!m_ListenSocket.Listen())  //监听
		{
			int nError = m_ListenSocket.GetLastError();

			if (nError != WSAEWOULDBLOCK)
			{
				AfxMessageBox("Socket的Listen失败!");
				m_bIsTcpOpen = FALSE;
				return;
			}
			
		}
		m_bIsTcpOpen = TRUE;
		GetDlgItem(IDC_BUTTON_TcpServer)->SetWindowText(_T("服务端关闭"));

	}
	else
	{
		m_ListenSocket.Close();
		GetDlgItem(IDC_BUTTON_TcpServer)->SetWindowText(_T("服务器打开"));
		m_bIsTcpOpen = FALSE;
	
	}
	
}

2)监听客户端是否连接

void CListenSocket::OnAccept(int nErrorCode) 
{
	// TODO: Add your specialized code here and/or call the base class
	m_pOverwriteSocket = new COverwriteSocket();

	if (Accept(*m_pOverwriteSocket))  //Listen之后监听客户端是否连接
	{
		g_bIsListenSocket = TRUE;

	}
	else
	{
		g_bIsListenSocket = FALSE;
		delete m_pOverwriteSocket;
		m_pOverwriteSocket = NULL;
	}
	
	CAsyncSocket::OnAccept(nErrorCode);
}

COverwriteSocket *m_pOverwriteSocket;

记住监听一定是另一个重写发送和接收的类,检测是否有客户端连接。


3)服务端的重写接受和发送的类

(1)重写OnReceive

void COverwriteSocket::OnReceive(int nErrorCode) 
{
	// TODO: Add your specialized code here and/or call the base class
	
	memset(m_szRecBuffer, 0, sizeof(m_szRecBuffer));
	m_nLength = Receive(m_szRecBuffer, sizeof(m_szRecBuffer));  //接收

	if (m_nLength == strlen(m_szRecBuffer))
	{
		g_bIsOnReceive = TRUE;		
	}
	if (m_nLength == -1)
	{
		g_bIsOnReceive = FALSE;
	}
	
	CAsyncSocket::OnReceive(nErrorCode);
}

(2)重写OnSend

void COverwriteSocket::OnSend(int nErrorCode) 
{
    // TODO: Add your specialized code here and/or call the base class
    m_nLength = Send(m_chBuffer, strlen(m_chBuffer));  //发送

    CAsyncSocket::OnSend(nErrorCode);
}

(3)注意:

接收和发送变量定义

char m_chBuffer[4096];
char m_szRecBuffer[4096];
如果客户端和服务端都写,接收和发送变量类型如果不一样,就要自己转换,否则会有乱码。


2.客户端

1)调用Create和Connect函数建立连接

CAsyncSocket *m_pClientSocket;
BOOL CTcpClient::TcpClientOpen()
{
	int nRet = 0;
	
	m_pClientSocket = new CAsyncSocket();
	GetHostAddress(m_strIP);
	if(m_pClientSocket->Create())   //创建
	{
		nRet = m_pClientSocket->Connect(m_strIP, 8888);  //连接
		Sleep(10);
		int nError = WSAGetLastError();

		if (nError == WSAEWOULDBLOCK)  //判断是否成功
		{
			m_IsTcpOpen = TRUE;
			return TRUE;
		}	
	}
	m_IsTcpOpen = FALSE;
	return FALSE;
}
如果new CSocket()。简单判断成功的标准就是读返回值,查看MSDN或者百度或谷歌。也可通过接收和发送判断是否成功。

2)接收,可重写OnReceive也可直接调用Receive()函数

BOOL CTcpClient::TcpClientReceive(CString& strReceive, int nRecLen)
{
	int nLen = 4096;
	int nRet = 0;
	char chBuffer[4096];

	memset(chBuffer, 0, sizeof(char)*nLen);
	nRet =m_pClientSocket->Receive(chBuffer, nLen);  //接收

	if (nRet == 0)
	{
		AfxMessageBox("TCP未连接!");
		return FALSE;
	}
	else if (nRet == SOCKET_ERROR)
	{
		AfxMessageBox("TCP接收数据出错!");
		return FALSE;
	}
	else
	{
		chBuffer[nRet] = 0;
		nRecLen = nRet;
		strReceive += chBuffer;
		return TRUE;
		
	}
	return FALSE;
}

3)发送,可重写OnSend也可直接调用Send()函数。

BOOL CTcpClient::TcpClientSend(CString strSend)
{
	int nLen = 0;

	sprintf(m_chBuffer,"%s", strSend);   //CString转换成char数组
	
	m_nLength = strlen(m_chBuffer);
        nLen =m_pClientSocket->Send(&m_chBuffer, strlen(m_chBuffer));   //发送

	if (nLen == strSend.GetLength())
	{
		return TRUE;
	}
 	return FALSE;

}


4)注意:

sprintf(m_chBuffer,"%s", strSend);           

这一句转换相当重要,当自己在对话框添加编辑框,获取编辑框的内容时,一定要转换成char数组,以便和其它兼容,如果还是CString数据直接发送出去,如果对方接收函数变量定义的类型是char数组,就会一定乱码。根据自己定义的类型,使用不同的转换方法。简单理解:客户端和服务端接收发送的变量类型一开始要保持一致。    


3.对话框显示

1)界面


服务端创建:放两个编辑框,三个按钮,定义接收和发送数组。


4.注意

基类可以使用CSocket,其和CAsyncSocket原理上的关系和区别:

1)CSocket类是从CAsyncSocket类派生出来的,继承了Receive、Send、Accept等函数。

2)CSocket对象执行Receive、ReceiveFrom和Accept函数时是阻塞的,而CAsyncSocket对象在执行以上函数时是非阻塞的,会返回WSAEWOULDBLOCK。

3)使用CAsyncSocket,如果通过GetLastError()返回的值如果是WSAEWOULDBLOCK,就说明成功,不要以为这是个错误值,切记!本人一开始没有理解透,浪费很多时间。

4)对于选择哪种基类,没必要太多纠结。可根据项目需求和个人意愿。

5)代码上的区别就是连接判断等函数返回值的判断。阻塞和非阻塞,简单理解就是同步和异步。

6)代码注释地方皆为主要部分。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值