新建两个基于对话框的工程,分别为sFile、cFile。在s端添加两个Edit:一个显示窗口IDC_EDIT1(点击右键选择Properties->Styles,选中Multiline,Vertical scroll、Read-only三项),一个输入窗口IDC_EDIT2。然后增加一个发送按钮:IDC_BtnSend。在c端添加三个Edit:一个显示窗口IDC_EDIT1(点击右键选择Properties->Styles,选中Multiline,Vertical scroll、Read-only三项),一个输入窗口IDC_EDIT2,一个IP地址输入窗口IDC_EDIT3。再增加两个按钮:一个发送按钮IDC_SEND,一个连接服务器按钮IDC_btnConnect。
服务器端具体步骤如下:
1、在StdAfx.h中添加 #include <afxsock.h> // MFC socket extensions
在Resource.h中添加#define IDP_SOCKETS_INIT_FAILED 103
在sFileDlg.h中添加public:void update(CString s);
在sFileDlg.h中添加private:
CEdit* show_edit;
CEdit* send_edit;
2、在sFileDlg.cpp中添加#include <winsock2.h>(加在#include "stdafx.h"之前)
#pragma comment(lib, "WS2_32.lib")
新建两个socket:SOCKET listen_sock;
SOCKET sock;
声明线程函数 UINT server_thd(LPVOID p);
3、在OnInitDialog()函数中添加:
show_edit = (CEdit *)GetDlgItem(IDC_EDIT1);
send_edit = (CEdit *)GetDlgItem(IDC_EDIT2);
send_edit->SetFocus();
char name[80];
CString IP;
hostent* pHost;
gethostname(name, 128);//获得主机名
pHost = gethostbyname(name);//获得主机结构
IP = inet_ntoa(*(in_addr *)pHost->h_addr);
update("本机IP地址:" + IP);
AfxBeginThread(&server_thd, 0);
添加函数update():
void CSFileDlg::update(CString s)
{
show_edit->ReplaceSel(s + "/r/n");
}
添加线程函数server_thd():
UINT server_thd(LPVOID p)
{
WSADATA wsaData;
WORD wVersion;
wVersion = MAKEWORD(2,2);
WSAStartup(wVersion,&wsaData);
// WSAStartup(0x0202, &wsaData);SOCKADDR_IN local_addr;
SOCKADDR_IN client_addr;
int iaddrSize = sizeof(SOCKADDR_IN);
int res;
char msg[1024];
CSFileDlg * dlg = (CSFileDlg *)AfxGetApp()->GetMainWnd();
local_addr.sin_family = AF_INET;
local_addr.sin_port = htons(5150);
local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
if( (listen_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET )
{
dlg->update("创建监听失败");
}
if( bind(listen_sock, (struct sockaddr*) &local_addr, sizeof(SOCKADDR_IN)) )
{
dlg->update("绑定错误");
}
listen(listen_sock, 1);
if( (sock = accept(listen_sock, (struct sockaddr *)&client_addr, &iaddrSize)) == INVALID_SOCKET)
{
dlg->update("accept 失败");
}
else
{
CString port;
port.Format("%d", int(ntohs(client_addr.sin_port)));
dlg->update( "已连接来自:" + CString(inet_ntoa(client_addr.sin_addr)) + " 端口:" +
port);
}
接收数据
while(1)
{
if( (res = recv(sock, msg, 1024, 0)) == -1 )
{
dlg->update("失去连接");
break;
}
else
{
msg[res] = '\0';
dlg->update("client:" + CString(msg));
}
}
return 0;
}
4、添加按钮实现函数void CSFileDlg::OnBtnSend():
void CSFileDlg::OnBtnSend()
{
// TODO: Add your control notification handler code here
CString s;
char * msg;
send_edit->GetWindowText(s);
msg = s.GetBuffer(s.GetLength());
if(send(sock, msg, strlen(msg), 0) == SOCKET_ERROR)
{
show_edit->ReplaceSel("发送失败/r/n");
}
else if(s == "")
{
MessageBox("请输入信息");
}
else
{
show_edit->ReplaceSel("server:" + s + "/r/n");//消息上屏,清空输入,并重获焦点
send_edit->SetWindowText("");
send_edit->SetFocus();
}
}
5、在InitInstance()函数中添加:
if (!AfxSocketInit())
{
AfxMessageBox(IDP_SOCKETS_INIT_FAILED);
return FALSE;
}
客户端具体步骤如下:
1、在StdAfx.h中添加 #include <afxsock.h> // MFC socket extensions
在Resource.h中添加#define IDP_SOCKETS_INIT_FAILED 103
在sFileDlg.h中添加public:void update(CString s);
在sFileDlg.h中添加private:
CEdit* edit1;
CButton* btnconn;
CEdit* send_edit;
CEdit* ip_edit;
2、在sFileDlg.cpp中添加#include <winsock2.h>(加在#include "stdafx.h"之前)
#pragma comment(lib, "WS2_32.lib")
新建一个socket:SOCKET sock;
声明线程函数 UINT recv_thd(LPVOID p);
3、在OnInitDialog()函数中添加:
edit1 = (CEdit *)GetDlgItem(IDC_EDIT1);
send_edit = (CEdit *)GetDlgItem(IDC_EDIT2);
btnconn = (CButton *)GetDlgItem(IDC_btnConnect);
ip_edit = (CEdit *)GetDlgItem(IDC_EDIT3);
ip_edit->SetWindowText("127.0.0.1");
添加函数update():
void CCFileDlg::update(CString s)
{
edit1->ReplaceSel(s + "/r/n");
}
添加线程函数recv_thd():
UINT recv_thd(LPVOID p)
{
int res;
char msg[1024];
CString s;
CCFileDlg * dlg = (CCFileDlg *) AfxGetApp()->GetMainWnd();
dlg->update("in thd");
while(1)
{
if( (res = recv(sock, msg, 1024, 0)) == -1)
{
dlg->update("失去连接");
break;
}
else
{
msg[res] = '/0';
dlg->update("server:" + CString(msg));
}
}
//closesocket(sock);
return 0;
}
4、添加按钮实现函数void CCFileDlg::OnSend():
void CCFileDlg::OnSend()
{
// TODO: Add your control notification handler code here
CString s;
char * msg;
send_edit->GetWindowText(s);
msg = s.GetBuffer(s.GetLength());
if(send(sock, msg, strlen(msg), 0) == SOCKET_ERROR)
{
update("发送失败");
}
else if(s == "")
{
MessageBox("请输入信息");
}
else
{
update("client:" + s);//消息上屏,清空输入,并重获焦点
send_edit->SetWindowText("");
send_edit->SetFocus();
}
}
5、添加连接按钮实现函数OnConnect():
void CCFileDlg::OnConnect()
{
// TODO: Add your control notification handler code here
WSADATA wsaData;
SOCKADDR_IN server_addr;
WORD wVersion;
wVersion = MAKEWORD(2,2);
WSAStartup(wVersion,&wsaData);
// WSAStartup(0x0202, &wsaData);CString ip;
ip_edit->GetWindowText(ip);//取得服务器的IP地址
server_addr.sin_addr.s_addr = inet_addr(ip);
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(5150);
if( (sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
{
edit1->ReplaceSel("create socket error/r/n");
}
if( connect(sock, (struct sockaddr *) &server_addr, sizeof(SOCKADDR_IN)) == SOCKET_ERROR)
{
edit1->ReplaceSel("连接失败/r/n");
}
else
{
edit1->ReplaceSel("连接成功/r/n");
AfxBeginThread(&recv_thd, 0);
btnconn->EnableWindow(FALSE);//按钮变灰
}
}
6、在InitInstance()函数中添加:
if (!AfxSocketInit())
{
AfxMessageBox(IDP_SOCKETS_INIT_FAILED);
return FALSE;
}