精华内容
下载资源
问答
  • c#通过串口及CAN模块实现上位及下位机通讯
    千次阅读
    2020-08-25 15:05:51

    目录

    前言

    一、串口、CAN总线

    二、使用步骤

    1.RS232串口通讯(指令下发与接收)

    2.CAN总线通讯

    总结


     

    前言

     学习及工作中我们经常会遇到上位机与下位机通讯等工作,结合场景使用不同的通讯方式实时通讯,以下为工作中遇到的上位机与下位机进行实时通讯,采用RS232串口和CAN总线形式进行网络通讯。


    一、串口、CAN总线

    串行接口简称串口,也称串行通讯接口或串行通讯接口(通常指设备的COM接口),是采用串行通信方式的扩展接口。串行接口 (Serial Interface)是指数据一位一位地顺序传送。其特点是通讯简单,只要一对传输线,通过设备设置传输线端口等参数就可以实现双向通信,从而大大降低了成本,特别适用于远距离通信,但传送速度较慢。

    CAN是控制器局域网络(Controller Area Network, CAN)的简称,是由以研发和生产汽车电子产品著称的德国BOSCH公司开发的,并最终成为国际标准(ISO 11898),是国际上应用最广泛的现场总线之一。 在北美和西欧,CAN总线协议已经成为汽车计算机控制系统和嵌入式工业控制局域网的标准总线,并且拥有以CAN为底层协议专为大型货车和重工机械车辆设计的J1939协议。上位机与与下位机制定好通用协议通过CAN模块将数据进行16进制转换实时通讯。

     

    二、使用步骤

    1.RS232串口通讯(指令下发与接收)

    代码如下(示例):

    //命名空间引入
    using System.IO.Ports;
    public SerialPort serialPort;//定义串口对象类public
    //定义连接方法
    public void Connect()
    {

           serialPort  = new SerialPort();

           serialPort.BaudRate = 1200;//波特率
           serialPort.PortName = "COM1";
           serialPort.Parity = Parity.None;//校验法:无
           serialPort.DataBits = 8;//数据位:8
           serialPort.StopBits = StopBits.One;//停止位:1
                try
                 {
                    serialPort.Open();//打开串口
                    serialPort.DtrEnable = true;//设置DTR为高电平
                    serialPort.RtsEnable = true;//设置RTS位高电平
                    serialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceived);//DataReceived事件委托
                    byte[] WriteBuffer = Encoding.ASCII.GetBytes("下发指令");
                    //下发
                    serialPort.Write(WriteBuffer, 0, WriteBuffer.Length);
                }
                catch (Exception ex)
                {
                    //打开串口出错,显示错误信息
                    Console.WriteLine("串口打开失败");
                }
            }

    2.CAN总线通讯

    代码如下(示例):

    //首先与CAN模块进行连接

            public TcpClient mTcp = new TcpClient();
            private const int READ_BUFFER_SIZE = 1000;
            private byte[] readBuffer = new byte[READ_BUFFER_SIZE + 1];
            public delegate void DoReadEventHandle(object sender, string e);
            public event DoReadEventHandle ReadedEvent;
            public event DoReadEventHandle LogEvent;

            public string recStr { get; set; }
            public string HandString { get; set; }
            public bool Connect()
            {
                //Can模块ip
                string mIPAddress = "192.168.1.1";
                IPAddress hostIPAddress = IPAddress.Parse(mIPAddress);
                //端口
                int mPort = 8080;
                IPEndPoint endIP = new IPEndPoint(hostIPAddress, mPort);
                try
                {
                    mTcp = new TcpClient(mIPAddress, mPort);
                    DateTime Savetime = DateTime.Now;
                    TimeSpan n = new TimeSpan();
                    while (true)
                    {
                        n = DateTime.Now - Savetime;
                        if (n.TotalMilliseconds > 1000 || mTcp.Client.Connected) break;
                    }
                    if (!mTcp.Client.Connected) return false;
                    mTcp.GetStream().BeginRead(readBuffer, 0, READ_BUFFER_SIZE, DoRead, null);
                }
                catch (Exception)
                {
                    return false;
                }
                return true;
            }
            private void DoRead(IAsyncResult ar)
            {
                try
                {
                    int BytesRead = mTcp.GetStream().EndRead(ar);
                    if (BytesRead > 0)
                    {
                        string s = "";
                        for (int i = 0; i <= BytesRead - 1; i++)
                        {
                            s = s + string.Format("{0:x2}", readBuffer[i]) + " ";
                        }
                        Console.WriteLine(s);
                        var t = s.Split(new string[] { "aa 00 ff 00 00 00 00 00 00 00 00 00 55" },            StringSplitOptions.RemoveEmptyEntries).FirstOrDefault(ex => ex != " ");
                        if (!string.IsNullOrEmpty(t))
                        {
                            recStr += t + "\r\n";
                            if (HandString == recStr && LogEvent != null)
                            {
                                HandString = null;
                                LogEvent(this, "握手成功!");
                            }
                        } mTcp.GetStream().BeginRead(readBuffer, 0, READ_BUFFER_SIZE, DoRead, null);
                    }
                }
                catch (Exception e)
                {
                    mTcp.Client.Close();
                }
            }

    //数据发送

     public void sendCan(string temperature, bool check)
            {
                HandString = "0xC0 0x02 0x02 0x00 0x00";
                string[] tmp = temperature.Split(' ');
                var buf = new byte[22];

                for (int i = 0; i < buf.Length; i++)
                {
                    buf[i] = 0;
                }
                for (int i = 0; i < tmp.Length; i++)
                {
                    try
                    {
                        buf[i] = Convert.ToByte(tmp[i], 16);
                    }
                    catch (Exception e)
                    {
                        buf[i] = 0;
                    }
                }
                SendData(buf, 0, 13, check);
            }

            public bool SendData(byte[] sendBytes, int mStart, int mLen, bool check = true)
            {
                if (!check) return false;
                try
                {
                    lock (mTcp.GetStream())
                    {
                        mTcp.GetStream().Write(sendBytes, mStart, mLen);
                    }
                    return true;
                }
                catch (Exception x)
                {
                    return false;
                }
            }


    总结

    1、RS232串口通讯

          接口的信号电平值较高,易损坏接口电路的芯片,传输速率较低,传输距离有限。

    2、CAN模块通讯

          具有实时性强、传输距离较远、抗电磁干扰能力强、成本低等优点;可根据报文的内容决定接收或屏蔽该报文;通讯过程信道容易阻塞。

     

    更多相关内容
  • 很多人需要编写基于MFC的上位机程序,而这类程序首先要解决的就是网络通信的问题,这里也抽出一点时间写了一个简单的额范例,如果你的需求是如下几幅图片所示(这里用TCP调试助手模拟下位机,以便更清楚的看到我们发...

    很多人需要编写基于MFC的上位机程序,而这类程序首先要解决的就是网络通信的问题,这里也抽出一点时间写了一个简单的额范例,如果你的需求是如下几幅图片所示(这里用TCP调试助手模拟下位机,以便更清楚的看到我们发的信息),那么不妨可以下载下来看一看,程序的代码已经给了非常详细的注释,这里不再赘述,只放一些核心代码:



    这里附上程序的下载地址,自己手工 码的程序,收一点点豆子,核心代码我也直接附出来:程序下载地址

    TCP调试助手程序下载地址(必须要设置下载豆,这个软件大家也可以网上下载,豆多的掠过):TCP/UDP调试助手下载地址

    先说一下程序的运行平台,以免各位下载程序跑的时候出现莫名的报错,本程序已经经过VS2013编译通过及运行:

    同时要设置本机的IP地址,比如我的这里设置的是:192.168.0.105,具体设置方法请百度:


    TCP模拟调试助手时,我们选择创建服务器,具体创建过程见图:


    创建成功后启动:


    //设备连接按钮的代码
    void CconnectDlg::OnBnClickedConnect()
    {
    	// TODO:  在此添加控件通知处理程序代码
    	//测试能不能ping通
    	int ping_ok = 1;
    	CString serv_addr, serv_port;
    
    	SECURITY_ATTRIBUTES sa;
    	HANDLE hRead, hWrite;
    	sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    	sa.lpSecurityDescriptor = NULL;
    	sa.bInheritHandle = TRUE;
    
    
    	CString filename = "ipconfig.ini";
    	CStdioFile mFileIP(filename, CFile::modeCreate | CFile::modeWrite);
    
    	//CString str_ip;
    	GetDlgItem(IDC_IP)->GetWindowText(serv_addr);
    	mFileIP.WriteString(serv_addr);
    	mFileIP.Close();
    	filename = "portconfig.ini";
    	CStdioFile mFilePort(filename, CFile::modeCreate | CFile::modeWrite);
    	GetDlgItem(IDC_Port)->GetWindowText(serv_port);
    	mFilePort.WriteString(serv_port);
    	mFilePort.Close();
    
    	CString strCmd;
    	strCmd = "cmd /k ping ";//加上"cmd /k"是为了能执行类似dir的命令
    	strCmd += serv_addr;
    
    	//创建命名管道
    	if (!CreatePipe(&hRead, &hWrite, &sa, 0)) {
    		return;
    	}
    	STARTUPINFO si;
    	PROCESS_INFORMATION pi;
    	si.cb = sizeof(STARTUPINFO);
    	GetStartupInfo(&si);
    	si.hStdError = hWrite;//数据输出用的文件句柄
    	si.hStdOutput = hWrite;//数据输出用的文件句柄
    	si.wShowWindow = SW_HIDE;
    	si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
    
    
    	OutputDebugString("1");
    
    	if (!CreateProcess(NULL, strCmd.GetBuffer(strCmd.GetLength())//执行cmd命令,并在命名中管道中写入cmd命令返回的串
    		, NULL, NULL, TRUE, NULL, NULL, NULL, &si, &pi)) {
    		return;
    	}
    
    	CloseHandle(hWrite);
    	OutputDebugString("2");
    
    	char buffer[4096] = { 0 };
    	DWORD bytesRead;
    	CString strResult = "";
    
    
    	while (1)
    	{
    		memset(buffer, 0, 4096);
    		if (ReadFile(hRead, buffer, 4096, &bytesRead, NULL) != NULL)//从命名管道中读取数据
    		{
    			if (buffer[18] == 'T')
    			{
    
    				ping_ok = 0;
    				int port;
    				SOCKADDR_IN addr;
    
    				WORD   wVersionRequested;//定义socket1.1或者socket2.0     
    				WSADATA   wsaData;   //定义装载socket版本的变量  
    				int   err;   //错误变量  
    
    				wVersionRequested = MAKEWORD(2, 2);   //定义连接为socket2.0  
    
    				err = WSAStartup(wVersionRequested, &wsaData);   //装载socket2.0支持  
    				if (0 != err)//判断是否装载成功  
    				{
    					return;
    				}
    
    				if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)//判断版本号,是否和定义的一样  
    				{
    					WSACleanup();   //若出问题,卸载支持,并结束程序返回-1  
    					return;
    				}
    				m_socket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, 0);
    
    				if (INVALID_SOCKET == m_socket)
    				{
    					MessageBox("创建套接字失败!");
    					return;
    				}
    
    				if (SOCKET_ERROR == WSAAsyncSelect(m_socket, m_hWnd, WM_SOCK, FD_READ))
    				{
    					MessageBox("注册网络读取事件失败!");
    					return;
    				}
    
    				if (serv_port == "" || serv_addr == "")
    				{
    					MessageBox("服务器地址或端口不能为空!!!");//该函数功能是弹出一个显示s你写的这些内容的框
    
    				}
    				else
    				{
    					port = atoi(serv_port.GetBuffer(1));//将端口字符串转换为数字
    					addr.sin_family = AF_INET;
    					addr.sin_addr.S_un.S_addr = inet_addr(serv_addr.GetBuffer(1));//转换服务器ip地址
    					addr.sin_port = ntohs(port);
    
    					//设置非阻塞模式
    					unsigned long ul = 1;
    					int ret = ioctlsocket(m_socket, FIONBIO, (unsigned long*)&ul);
    					if (ret == SOCKET_ERROR)
    						exit(0);
    
    					if (::connect(m_socket, (SOCKADDR*)&addr, sizeof(SOCKADDR)))
    					{
    						CString Str;
    					}
    					else
    					{
    					}
    
    				}
    				break;
    			}
    			OutputDebugString(buffer);
    
    		}
    		else
    		{
    			break;
    		}
    	}
    	CloseHandle(hRead);
    
    	if (ping_ok)
    	{
    		MessageBox("设备连接出错,请检查连接!");
    	}
    	else
    	{
    		m_connect.EnableWindow(0);
    		m_cut.EnableWindow(1);
    		GetDlgItem(IDC_STATIC_SHOW)->SetWindowText(_T("设备已连接"));
    		AddToInfRec("设备已连接", IDC_Zhuangtai, TRUE, TRUE);
    		CString connected;
    		connected = "设备已经连接";
    		send(m_socket, connected, 50, 0);
    		MyDevFounded = TRUE;
    	}
    }
    
    //发送命令按钮代码
    void CconnectDlg::OnBnClickedButtonSend()
    {
    	// TODO:  在此添加控件通知处理程序代码
    	CString message, showtext, datatest;
    	GetDlgItem(IDC_EDIT_Send)->GetWindowText(message); //从发送数据的edit框中获取信息,存储到message变量中
    
    	if (MyDevFounded == FALSE)   //进行设备连接状态的判断,通过设置MyDevFounded,初始值为false,设备连接成功后置true
    	{
    		AddToInfRec("设备未找到", IDC_Zhuangtai, TRUE, TRUE);//设备未成功连接,提示设备未找到
    		return;
    	}
    	if (message == "")
    	{
    		MessageBox("消息不能为空!");  //对发送数据框进行判断 
    	}
    	else
    	{
    		AddToInfRec("发送数据:", IDC_Zhuangtai,0,0);  
    		AddToInfRec(message, IDC_Zhuangtai,1,1);   //显示发送的数据到状态框
    		::send(m_socket, message.GetBuffer(1), message.GetLength(), 0);  //通过sock发送数据
    	}
    }
    //onsock函数代码
    afx_msg LRESULT CconnectDlg::OnSock(WPARAM wParam, LPARAM lParam)
    {
    	char cs[512] = "";  //定义一个用来存放接收数据的字符串cs
    	if (lParam == FD_READ) //sock收到消息,触发FD_READ
    	{
    		if (SOCKET_ERROR == recv(m_socket, cs, 512, NULL))//使用recv函数来进行判别收到的内容
    		{
    			MessageBox("接收数据失败!"); //如果触发连接错误,则弹出接收数据失败提示框
    			return FALSE;
    		}
    		else{
    			AddToInfRec("接收数据:", IDC_EDIT_REC, 0, 0);
    			AddToInfOut(cs, TRUE, TRUE);//如果没有出现错误,将cs中的数据传递给AddToInfOut来进行处理
    		}
    	}
    	return 0;
    }
    //数据处理函数代码
    void CconnectDlg::AddToInfOut(CString InStr, BOOL AddTime, BOOL NewLine)
    {
    	CString str, str1;
    	UINT i;
    	CHAR SysTime[10];
    	GetDlgItemText(IDC_EDIT_REC, str); //从数据接收的Edit框中获取已经接收到的信息
    	str += InStr; //新收到的信息通过InStr传递到本函数中,声明一个字符串str来存放,此条命令是将新收到的信息叠加到以前的信息中
    
    	//需要添加时间信息
    	if (AddTime == TRUE)
    	{
    		_strtime(SysTime);
    		str1 = SysTime;
    		str1 = " (" + str1 + ")";
    		str += str1;
    	}
    
    	//需要换行
    	if (NewLine == TRUE)
    	{
    		str += "\r\n";
    	}
    
    	//设置新的文本
    	SetDlgItemText(IDC_EDIT_REC, str); //将处理后的信息显示到接收的编辑框中
    	//滚动条自动滚动到最后一行
    	i = ((CEdit*)GetDlgItem(IDC_EDIT_REC))->GetLineCount();
    	((CEdit*)GetDlgItem(IDC_EDIT_REC))->LineScroll(i, 0);
    }


    展开全文
  • 正常情况下我们需要对下位机进行通信需要使用Socket进行连接操作,而在网络编程中又分为面向连接(TCP)和面向无连接(UDP)这两种,针对这两种方式,我们不做具体的原理解释,只说各自的特点和各自的应用场景: ...

    正常情况下我们需要对下位机进行通信需要使用Socket进行连接操作,而在网络编程中又分为面向连接(TCP)和面向无连接(UDP)这两种,针对这两种方式,我们不做具体的原理解释,只说各自的特点和各自的应用场景:

    UDP的特性是:数据报,无连接,简单,不可靠,会丢包,会乱序(实际中遇到的主要是丢包)
    TCP的特性是:流式,有连接,复杂,可靠,延迟较大、带宽占用较大(均是相对于UDP来说)

    有这样的特性其实是非常明显的,在早期,通常来说,我们对于传输数据量比较大的数据交互时一般都会使用UDP连接,对于文字消息我们一般采用TCP连接,但是因为保密性和数据丢包的原因,现在的聊天软件的视频通信我们一般也不再使用UDP,转而使用HTTP协议,但是UDP的弊端也恰恰是他最大的优点,对于一些对于数据量较大,且对数据准确性没有特殊请求的连接时我们还是会使用UDP协议(比如笔者在做PC机连接下位机时,通常数据超过2M/s时TCP就会出现明显的卡顿)。这里我们以连接下位机为例,来详细讲解一下基于UDP和TCP的网络编程过程(PC连接下位机),还是老规矩,先放一张图片,来看看我们想要得到的效果:需要下载示例Demo的请点击此处下载(注:此Demo仅包含客户端|上位机的创建,下位机可以像笔者一样使用TCP工具进行模拟或者直接连接对应的硬件设备)

    接下来,我们大致了解一下网络编程中标准的基于Socket的TCP/UDP编程步骤:

    基于TCP(面向连接)的socket编程的服务器端程序如下:

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

    基于TCP(面向连接)的socket编程的客户端程序如下:

    1、创建套接字(socket)
    2、向服务器发出连接请求(connect)
    3、和服务器端进行通信(send/recv)
    4、关闭套接字

     基于UDP(面向对象)的socket编程的服务器端程序如下:

    1、创建套接字(socket)
    2、将套接字绑定到一个本地地址和端口上(bind)
    3、等待接收数据(recvfrom)
    4、关闭套接字

    基于UDP(面向对象)的socket编程的客户端程序如下:

    1、创建套接字(socket)
    2、向服务器发送数据(sendto)
    3、关闭套接字

     好了,接下来,详细介绍我们在MFC下实现客户端|上位机的具体步骤

    Step1:我们需要新建一个MFC工程,并添加一个按钮用来触发我们的连接操作

    Step2:然后我们在Dlg文件中调用Socket,名字随意

    SOCKET m_socket;

    Step3:添加自定义消息,首先是在头文件中宏定义

    #define WM_Sock WM_USER+1

    然后在类向导中添加自定义消息(注名称必须一致),否则运行过程会出现错误 

    完成添加后我们编辑消息处理函数的内容(这里只放最简单的一个判断,不添加其他任何操作或者处理)

    	afx_msg LRESULT Csocket_demoDlg::OnSock(WPARAM wParam, LPARAM lParam)
    	{
    		char cs[512] = "";  //定义一个用来存放接收数据的字符串cs
    		if (lParam == FD_READ) //sock收到消息,触发FD_READ
    		{
    			if (SOCKET_ERROR == recv(m_socket, cs, 512, NULL))//使用recv函数来进行判别收到的内容
    			{
    				MessageBox("接收数据失败!"); //如果触发连接错误,则弹出接收数据失败提示框
    				return FALSE;
    			}
    			else{
    			}
    		}
    		return 0;
    	}

    Step4:最后就是在按钮的响应事件中添加处理函数

    首先是标准的TCP模式:

    //这是一个标准的TCP连接过程
    void Csocket_demoDlg::OnBnClickedButton1()
    {
    	// 这是一个标准的TCP连接过程
    	CString serv_addr = "192.168.0.104", serv_port = "5050";
    	// TODO:  在此添加控件通知处理程序代码
    	int port;
    	SOCKADDR_IN addr;
    	WORD   wVersionRequested;//定义socket1.1或者socket2.0     
    	WSADATA   wsaData;   //定义装载socket版本的变量  
    	int   err;   //错误变量  
    
    	wVersionRequested = MAKEWORD(2, 2);   //定义连接为socket2.0  
    
    	err = WSAStartup(wVersionRequested, &wsaData);   //装载socket2.0支持  
    	if (0 != err)//判断是否装载成功  
    	{
    		return;
    	}
    
    	if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)//判断版本号,是否和定义的一样  
    	{
    		WSACleanup();   //若出问题,卸载支持,并结束程序返回-1  
    		return;
    	}
    
    	//创建TCP套接字
    	m_socket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, 0);
    
    	//判断套接字错误
    	if (INVALID_SOCKET == m_socket)
    	{
    		MessageBox("创建套接字失败!");
    		return;
    	}
    
    	//判断注册网络错误
    	if (SOCKET_ERROR == WSAAsyncSelect(m_socket, m_hWnd, WM_Sock, FD_READ))
    	{
    		MessageBox("注册网络读取事件失败!");
    		return;
    	}
    
    	//判断服务器地址和端口号错误
    	if (serv_port == "" || serv_addr == "")
    	{
    		MessageBox("服务器地址或端口不能为空!!!");
    
    	}
    	else
    	{
    		port = atoi(serv_port.GetBuffer(1));//将端口字符串转换为整形
    		addr.sin_family = AF_INET;
    		addr.sin_addr.S_un.S_addr = inet_addr(serv_addr.GetBuffer(1));//转换服务器ip地址
    		addr.sin_port = ntohs(port);
    
    		//设置非阻塞模式
    		unsigned long ul = 1;
    		int ret = ioctlsocket(m_socket, FIONBIO, (unsigned long*)&ul);
    		if (ret == SOCKET_ERROR)
    			exit(0);
    
    		//TCP模式下调用Connect()
    		connect(m_socket, (SOCKADDR*)&addr, sizeof(SOCKADDR));
    
    		//对下位机发送指令
    		CString connected;
    		connected = "设备已经连接";
    		send(m_socket, connected, 50, 0);
    	}
    }

    然后是一个标准的UDP连接过程代码:

    // 这是一个标准的UDP连接过程
    void Csocket_demoDlg::OnBnClickedButton1()
    {
    	// 这是一个标准的UDP连接过程
    	CString serv_addr = "192.168.0.104", serv_port = "5050";
    	// TODO:  在此添加控件通知处理程序代码
    	int port;
    	SOCKADDR_IN addr;
    	WORD   wVersionRequested;//定义socket1.1或者socket2.0     
    	WSADATA   wsaData;   //定义装载socket版本的变量  
    	int   err;   //错误变量  
    
    	wVersionRequested = MAKEWORD(2, 2);   //定义连接为socket2.0  
    
    	err = WSAStartup(wVersionRequested, &wsaData);   //装载socket2.0支持  
    	if (0 != err)//判断是否装载成功  
    	{
    		return;
    	}
    
    	if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)//判断版本号,是否和定义的一样  
    	{
    		WSACleanup();   //若出问题,卸载支持,并结束程序返回-1  
    		return;
    	}
    
    	//创建UDP套接字
    	m_socket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, 0);
    
    	//判断套接字错误
    	if (INVALID_SOCKET == m_socket)
    	{
    		MessageBox("创建套接字失败!");
    		return;
    	}
    
    	//判断注册网络错误
    	if (SOCKET_ERROR == WSAAsyncSelect(m_socket, m_hWnd, WM_Sock, FD_READ))
    	{
    		MessageBox("注册网络读取事件失败!");
    		return;
    	}
    
    	//判断服务器地址和端口号错误
    	if (serv_port == "" || serv_addr == "")
    	{
    		MessageBox("服务器地址或端口不能为空!!!");
    
    	}
    	else
    	{
    		port = atoi(serv_port.GetBuffer(1));//将端口字符串转换为整形
    		addr.sin_family = AF_INET;
    		addr.sin_addr.S_un.S_addr = inet_addr(serv_addr.GetBuffer(1));//转换服务器ip地址
    		addr.sin_port = ntohs(port);
    
    		//设置非阻塞模式
    		unsigned long ul = 1;
    		int ret = ioctlsocket(m_socket, FIONBIO, (unsigned long*)&ul);
    		if (ret == SOCKET_ERROR)
    			exit(0);
    
    		//对下位机发送指令
    		CString connected;
    		connected = "设备已经连接";
    		sendto(m_socket, connected, 50, 0,NULL,NULL);
    	}
    }

    最后,提供一种非标准的连接方式 

    //这是一种非常规的连接过程UDP+Connect
    void Csocket_demoDlg::OnBnClickedButton1()
    {
    	//这是一种非常规的连接过程UDP+Connect
    	CString serv_addr = "192.168.0.104", serv_port = "5050";
    	// TODO:  在此添加控件通知处理程序代码
    	int port;
    	SOCKADDR_IN addr;
    	WORD   wVersionRequested;//定义socket1.1或者socket2.0     
    	WSADATA   wsaData;   //定义装载socket版本的变量  
    	int   err;   //错误变量  
    
    	wVersionRequested = MAKEWORD(2, 2);   //定义连接为socket2.0  
    
    	err = WSAStartup(wVersionRequested, &wsaData);   //装载socket2.0支持  
    	if (0 != err)//判断是否装载成功  
    	{
    		return;
    	}
    
    	if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)//判断版本号,是否和定义的一样  
    	{
    		WSACleanup();   //若出问题,卸载支持,并结束程序返回-1  
    		return;
    	}
    
    	//创建TCP套接字
    	m_socket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, 0);
    
    	//创建UDP套接字
    	/*m_socket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, 0);*/
    
    	//判断套接字错误
    	if (INVALID_SOCKET == m_socket)
    	{
    		MessageBox("创建套接字失败!");
    		return;
    	}
    
    	//判断注册网络错误
    	if (SOCKET_ERROR == WSAAsyncSelect(m_socket, m_hWnd, WM_Sock, FD_READ))
    	{
    		MessageBox("注册网络读取事件失败!");
    		return;
    	}
    
    	//判断服务器地址和端口号错误
    	if (serv_port == "" || serv_addr == "")
    	{
    		MessageBox("服务器地址或端口不能为空!!!");
    
    	}
    	else
    	{
    		port = atoi(serv_port.GetBuffer(1));//将端口字符串转换为整形
    		addr.sin_family = AF_INET;
    		addr.sin_addr.S_un.S_addr = inet_addr(serv_addr.GetBuffer(1));//转换服务器ip地址
    		addr.sin_port = ntohs(port);
    
    		//设置非阻塞模式
    		unsigned long ul = 1;
    		int ret = ioctlsocket(m_socket, FIONBIO, (unsigned long*)&ul);
    		if (ret == SOCKET_ERROR)
    			exit(0);
    
    		//TCP模式下调用Connect()
    		//UDP下也可以使用connect,使用connect函数之后可不必使用sendto函数
    		connect(m_socket, (SOCKADDR*)&addr, sizeof(SOCKADDR));
    
    		//对下位机发送指令
    		CString connected;
    		connected = "设备已经连接";
    		send(m_socket, connected, 50, 0);
    	}
    }

    这里,在文件中我已经给了详细的注释,针对非标准的连接方式特别说明几点:

    1、程序中UDP和TCP的连接仅在创建套接字时有不同

    //创建TCP套接字
    m_socket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, 0);
    //创建UDP套接字
    m_socket = WSASocket(AF_INET, SOCK_DGRAM, 0, NULL, 0, 0);

    2、连接时都使用了Connect函数:这里具体的解释可以参考原文博客,这里只做简单摘要

    标准的udp客户端开了套接口后,一般使用sendto和recvfrom函数来发数据,实际上,udp发送数据有两种方法供大家选用的:
    方法一: 
    socket----->sendto()或recvfrom() 
    方法二: 
    socket----->connect()----->send()或recv().(此时sendto,recvfrom仍可用)

    给UDP套接口调用connect,与TCP不同的是:没有三路握手过程。内核只是检查是否存在立即可知的错误(例如一个显然不可达的目的地),记录对端的IP地址和端口号(取自传递给connect的套接口地址结构),然后立即返回到调用进程

    展开全文
  • linux vm虚拟网络连接失败,重启网卡失败原因及解决办法0 .vm虚拟机下的网络三种连接方式详解1. vm虚拟以及宿主机没有vmnet1 vmnet8 网卡2 网卡配置文件出错测试网络是否连通 :ping www.baidu.com 0 .vm虚拟...

    0 .vm虚拟机下的网络三种连接方式详解

    NAT模式 桥接模式 仅主机模式

    ( 1 ) NAT模式: 意为网络地址转换 NAT模式借助虚拟NAT设备和虚拟DHCP服务器,使得虚拟机可以联网,这是VMware 中最为常用的一种联网模式,这种连接方式使用的是VMnet8 虚拟交换机。同处于NAT 网络模式下的系统通过VMnet8 交换机进行通信。NAT 网络模式下的IP 地址、子网掩码、网关和DNS 服务器都是通过DHCP 分配的。而该模式下的系统在与外部通信的时候使用的是虚拟的NAT 服务器,因此,虚拟机在外部网络中不必具有自己的IP地址。从外部网络来看,虚拟机和主机在共享一个IP地址,默认情况下,外部网络终端也无法访问到虚拟机。
    (2 )桥接模式: 就是将虚拟机的虚拟网络适配器与主机的物理网络适配器进行交接,虚拟机中的虚拟网络适配器可通过主机中的物理网络适配器直接访问到外部网络,这种模式也很容易理解,凡是选择使用桥接网络的系统就好像是局域网中的一个独立的主机, 就是和真实的计算机一模一样的主机, 并且它也连接到了这个真实的网络。因此如果要这个系统联网,就需要将这个系统和外面的真实主机采用相同的设置方法,如果你想把虚拟机当做一台完全独立的计算机看待,并且允许它和其他终端一样的进行网络通信,那么桥接模式通常是虚拟机访问网络的最简单途径。
    ( 3 )仅主机模式: 这种模式和NAT 模式差不多,但是是一种比NAT模式更加封闭的的网络连接模式,即便同处于这种联网模式下的主机是相互连通的,但是默认是不会连接到外部网络的,这样在进行网络实验(尤其是蠕虫病毒)时就不会担心传播到外部。

    形象的说:
      NAT模式的虚拟机,纯粹就是一个没上过户口的黑户,路由器"民政局"根本不知道有这么个人,自然也不会主动和它通信。即使虚拟机偶尔要向外面发送点的信件,都得交给主机以主机的名义转发出去,主机还专门请了一位叫做NAT的老大爷来专门负责这些虚拟机的发信、收信事宜。
      
      桥接模式的虚拟机,就像一个在路由器"民政局"那里"上过户口"的成年人,有自己单独的居住地址,虽然和主机住在同一个大院里,但好歹是有户口的人,可以大摇大摆地直接和外面通信。
      
      仅主机模式的虚拟机,纯粹是一个彻彻底底的黑奴,不仅没有户口、路由器"民政局"不知道这么号人,还被主机关在小黑屋里,连信件也不准往外发。

    1. vm虚拟机以及宿主机没有vmnet1 vmnet8 网卡

    在这里插入图片描述

    vmnet1: 这是Host 用于与Host-Only 虚拟网络进行通信的虚拟-(仅主机网卡。
    vmnet8: 这是Host 用于与NAT 虚拟网络进行通信的虚拟网卡。-(Nat)主机和虚拟机的IP地址不是在同一个网段,IP地址是虚拟出来的,通过该虚拟网卡实现转播
    如果查看发现vm虚拟机的宿主机上没有vmnet1 vmnet8 (如上图) 网卡配置,但是网卡基础配置操作都无误,且查询启动命令均正确 那么极有可能是network与NetworkManager冲突导致(最常见原因)
    解决方法:禁用NetworkManager

    1 临时禁用
    /etc/init.d/NetworkManager stop    (centos6)
    service NetworkManager stop        (centos6)
    systemctl stop NetworkManager      (centos7)
    
     
    永久
    chkconfig NetworkManager off       (centos6)
    systemctl disable NetworkManager   (centos7)
    
    
    2 重启网卡
    service network restart(以centos 7为例)
    

    2 网卡配置文件出错

    (1)编辑网卡配置文件:
    vi /etc/sysconfig/network-scripts/ifcfg-eth33(160) [以桥接模式为例]
    在这里插入图片描述

    1.	如上图所示:打开网卡配置文件,可看到光标在闪烁
    2.	按键盘的上下左右键,可以移动光标。
    3.	把光标移到最后一行(一直按下键)的no单词后面,按下字母a键
    4.	按回退键(backspace键),删除no,改为yes。
    5.	然后按下esc键,退出插入模式。
    6.	英文输入法状态下,输入冒号(shift+冒号)wq 然后回车
    7.	退出文件编辑
    
    
    

    (2)重启网卡
    service network restart(以centos 7为例)
    **

    测试网络是否连通 :ping www.baidu.com

    **

    // 下期出vm虚拟机下centos7 三种网络配置详细步骤(桥接 NAT 仅主机)

    展开全文
  • 堡垒远程连接服务器被拒绝

    千次阅读 2021-08-08 10:48:21
    堡垒远程连接服务器被拒绝 内容精选换一换云堡垒配置了FTP/SFTP远程备份,报请检查服务器密码或网络...原因二:云堡垒与FTP/SFTP服务器的网络连接不通,导致远程备份失败。原因三:FTP/S华为云帮助中心,为...
  • ESP32-CAM 直播远程控制Wifi小车-下位机(一)

    千次阅读 多人点赞 2020-09-26 20:16:26
    下位机由Arduino开发,将视频流发给Rtmp服务器(JAVA)处理转发给Android App 也可以使用微信小程序。 材料准备 底盘 ESP32-CAM 开发板 两节18650电池 18650电池盒 LM2596S-ADJ 降压模块 继电器 ...
  • 点击查看arcgis连接到数据库失败,常规功能故障具体信息答:解决方法: 1.新建空白地图文档,给整个数据框定义上目标图层相同的地理坐标系。不要设置投影坐标系。由于导入的多为经纬度数据,给数据框设置单位为度...
  • 请问下位机通过串口线连接的上位机,是怎么和上位机进行日期的同步的,下位机是否有能力自己获取日期而不依赖上位机?
  • 手机向日葵远程连接服务器

    万次阅读 2021-08-13 07:27:38
    手机向日葵远程连接服务器 内容精选换一换云堡垒配置了FTP/SFTP远程备份,报请检查服务器密码或网络...原因二:云堡垒与FTP/SFTP服务器的网络连接不通,导致远程备份失败。原因三:FTP/S华为云帮助中心,为用...
  • 大家现在可以来和小编一起了解我们的联通iptv顶盒要怎么安装连接方法,以及大家还要学会的联通iptv顶盒有哪些操作使用方法,希望小编我的这些介绍可以帮助到大家。一、连接安装方法1、光猫ONU的LAN2与沃TV特制...
  • 1、在cmd.exe中 Ping 10.12.13.77发现下位机是通信正常的,说明物理线路是正常的。 2.查看是不是某个端口被占用 输入命令:netstat -ano,列出所有端口的情况。在列表中我们观察被占用的端口,比如是8000,首先找到...
  • 本文详细演示FineReport客户端连接SQLServer(2000、2005等),常常会出现的错误:com.microsoft.sqlserver.jdbc.SQLServerException: 到主机的TCP/IP 连接失败的解决方案。
  • PowerDesigner16.5连接数据库失败

    千次阅读 2020-04-23 23:20:57
    1.首先说明连接失败原因: (1)Power Designer未使用“以管理员身份运行” (2)这个软件不能使用64的jdk只能使用32的jdk,win+r然后输入cmd,在命令提示符输入“Java -version”查看jdk版本 2.连接oracle 11...
  • 那么反过来,下位机硬件给上位机发送指令怎么才能实现呢?对于PMAC来说,最常见的情况就是,当PMAC一次运动完成时通知当前PC程序运动已完成。   1.下位机通知上位机原理   如下图所示, PC给PMAC发送指令...
  • 路由器加密设置和电视不相符,电视就无法辨认,我们电视所能辨认路由器的无线加密方法为: (1)选用WEP加密方法,设置如下:认证方法挑选Open,WEP加密挑选64Bit,密钥方法挑选ASCII,密钥任设一个即可,暗码需设置5...
  • 远程连接失败---解决方法简述

    千次阅读 2018-06-16 23:12:01
    很多朋友在使用电脑远程连接的时候,都出现了无法远程连接的问题,而造成远程连接失败的原因有很多,比如:本地网络异常.机房网络异常.服务器出现故障.远程连接设置有误等. 以下就是针对该问题的一些解决方案的简单...
  • 数据库连接错误信息提示: QSqlDatabase: QMYSQL driver not loaded QSqlDatabase: available drivers: QSQLITE QMYSQL QMYSQL3 QPSQL QPSQL7 出现这个问题的原因是Qt中没有MySql driver或者是版本有问题导致的...
  • Android 使用 Usb Accessory 模式与 linux 下位机进行通信

    万次阅读 热门讨论 2017-04-10 00:25:32
    这段时间研究了Usb Accessory模式, 这个模式正常的使用方法是用来和专为Android设备设计的USB主机硬件通讯的. 这种设备需要使用Accessory Development Kit (ADK)来开发, 遵循Android Open Accessory (AOA)协议.
  • VMware安装之后正常使用,第二次使用时突然发现没有显示ip,操作系统也没显示有线连接,重启网络服务无效,报错如上图。 百度无数个方法,包括设置MAC地址,关闭networkManager等均无效。 后来发现主机上网络中心...
  • 在某一台服务器无法访问另一台服务器的https服务,telnet检测端口发现端口无法连接: [root@020113 ~]# telnet 192.168.5.27 443 Trying 192.168.5.27... 问题分析 第一步:网络检查 同网段其他主机访问服务端是...
  • 也是今天遇到了相关问题花了很久时间仍未解决,参考多大佬文章才解决,自己觉得还是应该在总结一下解决方法!!! 问题 虚拟机安装了Ubuntu系统后,主机在cmd中无法ping通以该虚拟机,图 解决方法 ① 管理员...
  • 由于干的是加工行业,所以想深钻一下自己的行业。所以就了个宇龙数控仿真系统,结果了N个版本搞了半天,装完了却打不开。如图 哎呀这个着急啊,百度找了半天 ...
  • 前段时间自己在本地写的一个WebSocket程序部署到服务器出现了几个错误,我自己也做了记录和分析,...Q1 客户端链接WebSocket服务器时连接失败,报404错误。  排查了地址错误和配置相关后,是因为JAR冲突,因为To...
  • 在百度百科查询的资料修改了都不行(在不重装系统前提,联想台式都是win732系统),给大家一一列举,请求广大网友指点。①、在搜索程序和文件框或运行里面输入:gpedit.msc,然后按回车键,在本地组策略编辑器...
  • WebSocket部署到服务器时,出现连接失败的问题解决与分析 原创 2017年03月16日 11:27:40 5364 前段时间在本地写的一个WebSocket程序部署到服务器上时出错,做记录和分析 本地环境是:...
  • urlopen error [WinError 10060]由于连接方在一段时间后没有正确答复或连接的主机没有反应,连接尝试失败。" 如下所示: 解决办法:这可能是由于自身网络问题或者mnist数据集下载网页连接不...
  • 无界鼠标MOUSE WITHOUT BORDERS连接失败的解决办法问题描述、解决办法现在我们来建立出站规则遇到的问题 问题描述、解决办法 我是win10主,win7从,从官网下载安装好后同局域网开启防火墙,win7怎么输入win10的...
  • 补充,在公司测试时虚拟机和主机连接测试时又出现了:port 22:No route to host的问题,查了一下发现时因为ip网段不同,因为虚拟机事直接挂起的没有关机,所有ip网段还是家里的网段,重启就变回来了。   最近要...
  • ESP32实现蓝牙主从机连接-BluetoothSerial蓝牙库

    千次阅读 热门讨论 2021-11-04 12:38:55
      因为需要使用ESP32的蓝牙功能,就看了ESP32的经典蓝牙库,例程里是ESP32作为从,使用手机或者其他设备连接ESP32进行数据传输。但我又需要使用ESP32互连,一个作为主机,一个作为从,就根据库敲了一下ESP32...
  • 此时应该首先保证正确编辑SSH连接: Windous上用户名一般都设置为root,但是UOS/Ubuntu并不识别,如果用户名是root,出现该情况时,请将root改为该普通用户的用户名,点击确定,进行连接,成功即可,若不成功,需要...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 135,913
精华内容 54,365
关键字:

下位机连接失败