基于TCP/IP协议进行MFC与机械臂进行Socket网络通讯

3 篇文章 0 订阅
2 篇文章 0 订阅

需求

需要和机械臂进行通讯,具体来说基于TCP/IP协议和MFC框架中,与机械臂进行Socket通讯。其中机械臂作为客户端,本电脑作为服务器。服务器发送数据给机械臂,机械臂完成动作后,返还数据给服务器。

TCP流式套接字的编程步骤:

服务器端程序:
1、加载套接字库
2、创建套接字(socket)。
3、将套接字绑定到一个本地地址和端口上(bind)。
4、将套接字设为监听模式,准备接收客户请求(listen)。
5、等待客户请求到来;当请求到来后,接受连接请求,返回一个新的对应于此次连接的套接字(accept)。
6、用返回的套接字和客户端进行通信(send/recv)。
7、返回,等待另一客户请求。
8、关闭套接字。

具体实现

首先新建一个基于对话框的工程取名为sFile,此工程作为服务器端。删除对话框中的中间代码和OK按钮。

  • 在新建的对话框中添加一个List Box控件作为显示窗口,右键点击选择——添加变量,将变量定义为控件类型并取名为m_listwords。
  • 添加一个Edit control控件作为输入窗口
  • 然后增加一个发送按钮:IDC_BtnSend。

代码

一:sFileDlg.h中添加的代码

public:void update(CString s);
private: CEdit* send_edit;
void CString2Char(CString str, char ch[]);  //此函数为字符格式转换函数,后面会讲到

二、 新建两个socket套接字:

SOCKET listen_sock; 
SOCKET sock;

在sFileDlg.cpp中添加 CString IP; //定义为全局变量
并声明线程函数 UINT server_thd(LPVOID p);

3、在OnInitDialog()函数中添加:

send_edit = (CEdit *)GetDlgItem(IDC_EDIT1);
send_edit->SetFocus();
char name[128];
hostent* pHost;
gethostname(name, 128);//获得主机名 
pHost = gethostbyname(name);//获得主机结构 
IP = inet_ntoa(*(in_addr *)pHost->h_addr);
update(_T("本服务器IP地址:") + IP);
AfxBeginThread(server_thd, NULL);//创建线程

4、添加函数update():

  void CSFileDlg::update(CString s)
{
 m_listwords.AddString(s);
}

5、添加线程函数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();
char ch_ip[20];
CString2Char(IP, ch_ip);//注意!这里调用了字符格式转换函数,此函数功能:CString类型转换为Char类型,实现代码在后面添加
//local_addr.sin_addr.s_addr = htonl(INADDR_ANY);//获取任意IP地址
local_addr.sin_addr.s_addr=inet_addr(ch_ip);
local_addr.sin_family = AF_INET;
local_addr.sin_port = htons(8888);
if ((listen_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)//创建套接字
{
dlg->update(_T("创建监听失败"));
}
if (bind(listen_sock, (struct sockaddr*) &local_addr, sizeof(SOCKADDR_IN)))//绑定套接字
{
dlg->update(_T("绑定错误"));
}
listen(listen_sock, 1);
if ((sock = accept(listen_sock, (struct sockaddr *)&client_addr, &iaddrSize)) == INVALID_SOCKET)//接收套接字
{
dlg->update(_T("accept 失败"));
}
else
{
CString port;
port.Format(_T("%d"), int(ntohs(client_addr.sin_port)));
dlg->update(_T("已连接客户端:") + CString(inet_ntoa(client_addr.sin_addr)) + "  端口:" + port);
}
接收数据
while (1)
{ 
if ((res = recv(sock, msg, 1024, 0)) == -1)
{
dlg->update(_T("失去客户端的连接"));
break;
}
else
{
msg[res] = '\0';
dlg->update(_T("client:") + CString(msg));
}
}
return 0;
} 

6、添加按钮发送函数(在对话框中右键点击刚添加的按钮弹出菜单,然后选择添加事件响应函数这一栏,将函数命名为OnSending)

void CsFileDlg::OnSending()
{
// TODO: Add your control notification handler code here
CString s;
char  msg[1024];
send_edit->GetWindowTextW(s);
CString2Char(s, msg); //  注意!这里调用了字符格式转换函数,此函数功能:CString类型转换为Char类型,实现代码后面添加
if (send(sock, msg, strlen(msg), 0) == SOCKET_ERROR)
{
show_edit->ReplaceSel(_T("发送失败"));
m_listwords.SetWindowTextW(_T("发送失败"));
}
else if (s == "")
{
MessageBox(_T("请输入信息"));
}
else
{
s = msg;
//update(s);//消息上屏,清空输入,并重获焦点
//show_edit->ReplaceSel(_T("server:") + s);//消息上屏,清空输入,并重获焦点
m_listwords.AddString(_T("server:") + s);
send_edit->SetWindowText(_T(""));
m_listwords.SetFocus();
}
}

void CString2Char(CString str, char ch[])//此函数就是字符转换函数的实现代码
{
int i;
char *tmpch;
int wLen = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0, NULL, NULL);//得到Char的长度
tmpch = new char[wLen + 1];                                             //分配变量的地址大小
WideCharToMultiByte(CP_ACP, 0, str, -1, tmpch, wLen, NULL, NULL);       //将CString转换成char*


for (i = 0; tmpch[i] != '\0'; i++) ch[i] = tmpch[i];
ch[i] = '\0';
}

参考

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值