TCP网络通信

服务器:

1 在StdAfx.h中引入<winsock2.h>

2 初始化Winsock库

        WSADATA wsaData;  (WSDATAhttp://blog.youkuaiyun.com/liuhongwei_study/article/details/8128207)
        WORD sockVersion = MAKEWORD(2, 0);
        ::WSAStartup(sockVersion, &wsaData);

3添加对话框

     

4 变量设置

5编写代码:

// TCPServerDlg.cpp : implementation file
//

#include "stdafx.h"
#include "TCPServer.h"
#include "TCPServerDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define WM_SOCKET WM_USER + 1	// 定义网络事件通知消息

/
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/
// CTCPServerDlg dialog

CTCPServerDlg::CTCPServerDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CTCPServerDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CTCPServerDlg)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CTCPServerDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CTCPServerDlg)
	DDX_Control(pDX, IDC_DATA, m_listData);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CTCPServerDlg, CDialog)
	//{{AFX_MSG_MAP(CTCPServerDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_CLEAR, OnClear)
	ON_BN_CLICKED(IDC_START, OnStart)
	ON_MESSAGE(WM_SOCKET, OnSocket)
	ON_BN_CLICKED(IDC_SEND, OnSend)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/
// CTCPServerDlg message handlers

BOOL CTCPServerDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here
	m_bar.Create(WS_CHILD|WS_VISIBLE|SBS_SIZEGRIP, CRect(0, 0, 0, 0), this, 101);
	m_bar.SetBkColor(RGB(0xa6, 0xca, 0xf0));		// 背景色

	int arWidth[] = { 200, -1 };

	m_bar.SetParts(2, arWidth);				// 分栏

	m_bar.SetText(" 忙碌", 1, 0);	// 第一个栏的文本

	m_bar.SetText(" 空闲", 0, 0);				// 第二个栏的文本
	
	m_listData.SetExtendedStyle(LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES);// 设置列表视图控件的属性

	m_listData.InsertColumn(0, "方向", LVCFMT_LEFT, 200);

	m_listData.InsertColumn(1, "数据", LVCFMT_LEFT, 170);


	m_socket = INVALID_SOCKET;	// 初始化监听套节字和连接列表

	m_nClient = 0;
	

	char szHost[256];

	::gethostname(szHost, 256);	// 取得本机名称	
	
	HOSTENT* pHost = gethostbyname(szHost);// 通过本机名称取得地址信息

	if(pHost != NULL)
	{  	
		CString sIP;
		
	
		in_addr *addr =(in_addr*) *(pHost->h_addr_list);	// 得到第一个IP地址
		
		
		sIP.Format(" 本机IP:%s", inet_ntoa(addr[0]));// 显示给用户

		m_bar.SetText(sIP, 0, 0);
	}
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CTCPServerDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CTCPServerDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CTCPServerDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

BOOL CTCPServerDlg::AddClient(SOCKET s)
{
	
	if(m_nClient < MAX_SOCKET)
	{
		
		m_arClient[m_nClient++] = s;// 添加新的成员
		return TRUE;
	}
	return FALSE;
}

void CTCPServerDlg::OnClear() 
{
	// TODO: Add your control notification handler code here
	m_listData.DeleteAllItems();
}

void CTCPServerDlg::OnStart() // 开启服务
{
	// TODO: Add your control notification handler code here
	if(m_socket == INVALID_SOCKET)  
	{
		
		CString sPort;

		GetDlgItem(IDC_PORT)->GetWindowText(sPort);// 取得端口号

		int nPort = atoi(sPort);

		if(nPort < 1 || nPort > 65535)
		{
			MessageBox("端口号错误!");

			return;
		}

		if(!CreateAndListen(nPort))// 创建监听套节字,使它进入监听状态
		{
			MessageBox("启动服务出错!");

			return;
		}
		
	
		GetDlgItem(IDC_START)->SetWindowText("停止服务");	// 设置相关子窗口控件状态

		m_bar.SetText(" 正在监听……", 0, 0);

		GetDlgItem(IDC_PORT)->EnableWindow(FALSE);
	}
	else				// 停止服务
	{
		
		CloseAllSocket();// 关闭所有连接

		
		GetDlgItem(IDC_START)->SetWindowText("开启服务");// 设置相关子窗口控件状态

		m_bar.SetText(" 空闲", 0, 0);

		GetDlgItem(IDC_PORT)->EnableWindow(TRUE);
	}	
}

void CTCPServerDlg::OnCancel() 
{
	// TODO: Add extra cleanup here
	CloseAllSocket();

	CDialog::OnCancel();
}

void CTCPServerDlg::CloseAllSocket()
{
	if(m_socket != INVALID_SOCKET)//关闭监听套接字
	{
		::closesocket(m_socket);

		m_socket = INVALID_SOCKET;
	}

	for(int i=0 ; i<m_nClient; i++)
	{
		::closesocket(m_arClient[i]);
	}

	m_nClient =0;
}

BOOL CTCPServerDlg::CreateAndListen(int nPort)
{

	if(m_socket == INVALID_SOCKET)
		::closesocket(m_socket);

	m_socket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);//创建套接字

	if(m_socket == INVALID_SOCKET)
		return FALSE;

	sockaddr_in sin;

	sin.sin_family = AF_INET;

	sin.sin_port = htons(nPort);

	sin.sin_addr.s_addr = INADDR_ANY;

	if(::bind(m_socket, (sockaddr*)&sin, sizeof(sin)) == SOCKET_ERROR)
	{
		return FALSE;
	}
	::WSAAsyncSelect(m_socket, m_hWnd, WM_SOCKET, FD_ACCEPT|FD_CLOSE);	// 设置socket为窗口通知消息类型

	::listen(m_socket,5);// 进入监听模式

	return TRUE;
}



void CTCPServerDlg::AddDataToList(SOCKET s, LPCTSTR pszText, BOOL bRecv)
{
	

	sockaddr_in sockAddr;

	memset(&sockAddr,0,sizeof(sockAddr));

	int nSockAddrLen = sizeof(sockAddr);

	::getpeername(s, (SOCKADDR*)&sockAddr, &nSockAddrLen);	// 取得对方的IP地址和端口号

	int nPeerPort = ::ntohs(sockAddr.sin_port);

	CString sPeerIP = ::inet_ntoa(sockAddr.sin_addr);

	DWORD dwIP = ::inet_addr(sPeerIP);

	hostent* pHost = ::gethostbyaddr((LPSTR)&dwIP, 4, AF_INET);

	char szHostName[256];

	strncpy(szHostName, pHost->h_name, 256);

	CString strItem;	

	if(bRecv)
	{
		strItem = "【接收】";
	}
	else
	{
		strItem = "【发送】";
	}
	strItem = strItem + CString(szHostName) + "["+ sPeerIP+ "] ";

	int nIndex = m_listData.GetItemCount();

	m_listData.InsertItem(nIndex, strItem, 0);

	m_listData.SetItemText(nIndex, 1, pszText);
}


long CTCPServerDlg::OnSocket(WPARAM wParam, LPARAM lParam)
{
	// 取得有事件发生的套节字句柄
	SOCKET s = wParam;
	// 查看是否出错
	if(WSAGETSELECTERROR(lParam))
	{
		RemoveClient(s);
		::closesocket(s);
		return 0;
	}
	switch(WSAGETSELECTEVENT(lParam))// 处理发生的事件
	{
	case FD_ACCEPT:	// 监听中的套接字检测到有连接进入
		{
				if(m_nClient < MAX_SOCKET)
			{
				
				SOCKET client = ::accept(s, NULL, NULL);// 接受连接请求,新的套节字client是新连接的套节字
			
				int i = ::WSAAsyncSelect(client, 
					m_hWnd, WM_SOCKET, FD_READ|FD_WRITE|FD_CLOSE);	// 设置新的套节字为窗口通知消息类型
				AddClient(client);
			}
			else
			{
				MessageBox("连接客户太多!");
			}
		}
		break;
	case FD_CLOSE:// 检测到套接字对应的连接被关闭
		{
			RemoveClient(s);

			::closesocket(s);
		}
		break;
	case FD_READ:// 套接字接受到对方发送过来的数据包
		{
			char szText[1024] ={ 0 };

			::recv(s,szText,1024,0);

			AddDataToList(s,szText,TRUE);

			SendData(s);
		}
		break;
	}

	return 0;
}

void CTCPServerDlg::RemoveClient(SOCKET s)
{

	BOOL bFind = FALSE;

	for(int i=0; i<m_nClient; i++)
	{
		if(m_arClient[i] == s)
		{
			bFind = TRUE;

			break;
		}
	}

	
	if(bFind)// 如果找到就将此成员从列表中移除
	{
		m_nClient--;
	
		for(int j=i; j<m_nClient; j++)	// 将此成员后面的成员都向前移动一个单位
		{
			m_arClient[j] = m_arClient[j+1];
		}
	}
}

void CTCPServerDlg::SendData(SOCKET s)
{

	char szText[1024]="数据已收到";

	::send(s,szText,1024,0);

	AddDataToList(s,szText,FALSE);
}

void CTCPServerDlg::OnSend() 
{
	// TODO: Add your control notification handler code here
	if(m_socket == INVALID_SOCKET)
	{
		return;
	}

	CString sText;

	GetDlgItem(IDC_TEXT)->GetWindowText(sText);//取得要发送的字符串

	sText += "\r\n";//添加回车换行

	if(::send(m_socket, sText, sText.GetLength(), 0) != -1)
	{
		int nIndex = m_listData.GetItemCount();

		m_listData.InsertItem(nIndex, "【发送】", 0);

		m_listData.SetItemText(nIndex, 1, sText);

		GetDlgItem(IDC_TEXT)->SetWindowText("");
	}
}

注意:OnSock函数是消息映射函数

客户端

1 2同上

3 添加对话框

4 设置变量

 

5 编辑代码

// TCPClientDlg.cpp : implementation file
//

#include "stdafx.h"
#include "TCPClient.h"
#include "TCPClientDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define WM_SOCKET WM_USER + 1 //定义网络事件通知消息
/
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/
// CTCPClientDlg dialog

CTCPClientDlg::CTCPClientDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CTCPClientDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CTCPClientDlg)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CTCPClientDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CTCPClientDlg)
	DDX_Control(pDX, IDC_DATA, m_listData);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CTCPClientDlg, CDialog)
	//{{AFX_MSG_MAP(CTCPClientDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_CLEAR, OnClear)
	ON_BN_CLICKED(IDC_CONNECT, OnConnect)
	ON_BN_CLICKED(IDC_SEND, OnSend)
	ON_MESSAGE(WM_SOCKET, OnSocket)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/
// CTCPClientDlg message handlers

BOOL CTCPClientDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	m_bar.Create(WS_CHILD|WS_VISIBLE|SBS_SIZEGRIP, CRect(0, 0, 0, 0), this, 101);
	
	m_bar.SetBkColor(RGB(0xa6, 0xca, 0xf0));

	int arWidth[] = { 200, -1 };

	m_bar.SetParts(2, arWidth);	
								
	m_bar.SetText(" 忙碌", 1, 0);	
	
	m_bar.SetText(" 空闲", 0, 0);

	m_listData.SetExtendedStyle(LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES);

	m_listData.InsertColumn(0, "方向", LVCFMT_LEFT, 100);

	m_listData.InsertColumn(1, "数据", LVCFMT_LEFT, 170);

	GetDlgItem(IDC_SEND)->EnableWindow(FALSE);

	GetDlgItem(IDC_TEXT)->EnableWindow(FALSE);

	GetDlgItem(IDC_ADDR)->SetWindowText("127.0.0.1");
	
	m_socket = INVALID_SOCKET;


	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CTCPClientDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CTCPClientDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CTCPClientDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

BOOL CTCPClientDlg::Connect(LPCTSTR pszRemoteAddr, u_short nPort)
{

	m_socket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);//创建套接字

	if( m_socket == INVALID_SOCKET)
	{
		return FALSE;

	}

	::WSAAsyncSelect(m_socket, m_hWnd,
		WM_SOCKET, FD_CONNECT | FD_CLOSE | FD_WRITE | FD_READ);//设置socket为窗口通知消息类型
	
	ULONG uAddr = ::inet_addr(pszRemoteAddr);

	if( uAddr == INADDR_NONE)// 不是IP地址,就认为这是主机名称
	{
		hostent* pHost =::gethostbyname(pszRemoteAddr);//从主机名取得IP地址

		if( pHost == NULL)
		{
			::closesocket(m_socket);

			m_socket = INVALID_SOCKET;

			return FALSE;

		}

		uAddr = ((struct in_addr*)*( pHost->h_addr_list))->s_addr;
	}

	sockaddr_in remote;

	remote.sin_addr.S_un.S_addr = uAddr;

	remote.sin_family = AF_INET;

	remote.sin_port = htons(nPort);

	::connect(m_socket, (sockaddr*)&remote, sizeof(sockaddr));//连接远程机

	return TRUE;
}

void CTCPClientDlg::OnClear() 
{
	// TODO: Add your control notification handler code here
	m_listData.DeleteAllItems();
}

void CTCPClientDlg::OnConnect() 
{
	// TODO: Add your control notification handler code here
	if( m_socket == INVALID_SOCKET) //连接服务器
	{
		CString sAddr;

		GetDlgItem(IDC_ADDR)->GetWindowText(sAddr);//取得服务器地址
		if(sAddr.IsEmpty())
		{
			MessageBox("请输入服务器地址!");

			return;

		}
		CString sPort;
		
		GetDlgItem(IDC_PORT)->GetWindowText(sPort);//取的端口号

		int nPort = atoi(sPort);

		if(nPort <1 || nPort > 65535)
		{
			MessageBox("端口错误!");

			return;

		}

		if( !Connect(sAddr,nPort)) //连接服务器
		{
			MessageBox("连接服务器出错!");

			return;
			
	
		}
		GetDlgItem(IDC_CONNECT)->SetWindowText("取消");//设置用户界面

		m_bar.SetText(" 正在连接……", 0, 0);
		
		
	}
	else
		{
			::closesocket(m_socket);//关闭套接字

			m_socket = INVALID_SOCKET;

		GetDlgItem(IDC_CONNECT)->SetWindowText("连接服务器");//设置用户界面
		m_bar.SetText(" 空闲", 0, 0);	
		GetDlgItem(IDC_ADDR)->EnableWindow(TRUE);
		GetDlgItem(IDC_PORT)->EnableWindow(TRUE);
		GetDlgItem(IDC_TEXT)->EnableWindow(FALSE);
		GetDlgItem(IDC_SEND)->EnableWindow(FALSE);
		}
}

void CTCPClientDlg::OnSend() 
{
	// TODO: Add your control notification handler code here
	if(m_socket == INVALID_SOCKET)
	{
		return;
	}

	CString sText;

	GetDlgItem(IDC_TEXT)->GetWindowText(sText);//取得要发送的字符串

	sText += "\r\n";//添加回车换行

	if(::send(m_socket, sText, sText.GetLength(), 0) != -1)
	{
		int nIndex = m_listData.GetItemCount();

		m_listData.InsertItem(nIndex, "【发送】", 0);

		m_listData.SetItemText(nIndex, 1, sText);

		GetDlgItem(IDC_TEXT)->SetWindowText("");
	}
}

long CTCPClientDlg::OnSocket(WPARAM wParam, LPARAM lParam)
{

	SOCKET s= wParam;// 取得有事件发生的套节字句柄

	if(WSAGETSELECTERROR(lParam))
	{
		if( m_socket != SOCKET_ERROR)
			OnConnect();

		m_bar.SetText(" 连接出错!", 0, 0);

		return 0;
	}

	switch(WSAGETSELECTEVENT(lParam))
	{
	case FD_CONNECT:      // 套节字正确的连接到服务器
		{
			GetDlgItem(IDC_CONNECT)->SetWindowText("断开连接");//设置用户界面

			GetDlgItem(IDC_ADDR)->EnableWindow(FALSE);

			GetDlgItem(IDC_PORT)->EnableWindow(FALSE);

			GetDlgItem(IDC_TEXT)->EnableWindow(TRUE);

			GetDlgItem(IDC_SEND)->EnableWindow(TRUE);

			m_bar.SetText(" 已经连接到服务器", 0, 0);
		}
		break;
	
	case FD_READ:
		{
			char szText[1024];

			::recv(s,szText,1024,0);

			int nIndex = m_listData.GetItemCount();

			m_listData.InsertItem(nIndex, "【接收】", 0);

			m_listData.SetItemText(nIndex, 1, (CString(szText)));

			SendData(s);

			
		}

		break;
	
	case FD_CLOSE:

			OnConnect();

			break;	
	}
		return 0;
}

void CTCPClientDlg::OnCancel() 
{
	// TODO: Add extra cleanup here
	if(m_socket != INVALID_SOCKET)
		::closesocket(m_socket);

	CDialog::OnCancel();


}

void CTCPClientDlg::AddDataToList(SOCKET s, LPCTSTR pszText, BOOL bRecv)
{
	
	sockaddr_in sockAddr;

	memset(&sockAddr,0,sizeof(sockAddr));

	int nSockAddrLen = sizeof(sockAddr);

	::getpeername(s, (SOCKADDR*)&sockAddr, &nSockAddrLen);	// 取得对方的IP地址和端口号

	int nPeerPort = ::ntohs(sockAddr.sin_port);

	CString sPeerIP = ::inet_ntoa(sockAddr.sin_addr);

	DWORD dwIP = ::inet_addr(sPeerIP);

	hostent* pHost = ::gethostbyaddr((LPSTR)&dwIP, 4, AF_INET);

	char szHostName[256];

	strncpy(szHostName, pHost->h_name, 256);

	CString strItem;	

	if(bRecv)
	{
		strItem = "【接收】";
	}
	else
	{
		strItem = "【发送】";
	}
	strItem = strItem + CString(szHostName) + "["+ sPeerIP+ "] ";

	int nIndex = m_listData.GetItemCount();

	m_listData.InsertItem(nIndex, strItem, 0);

	m_listData.SetItemText(nIndex, 1, pszText);
}

void CTCPClientDlg::SendData(SOCKET s)
{
	char szText[1024]="数据已收到";

	::send(s,szText,1024,0);

	AddDataToList(s,szText,FALSE);
}


 


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值