C# PLC和电脑上软件以太网通讯问题

如题

所用工具:

            1,第三方拍摄软件EasyInspector 简称EI。
            2,自己写的软件Checksoft。
            3,基恩士PLC CPU模块KV-NC32T

描述下软件功能

            1.EI 可以通过SOCKET的方法进行通讯,即控制什么时候开始拍照检测,并将检测的数据
            返回。
            2,利用上述的SOCKET方法(EI 带的例程),写了一个软件:一方面和PLC通讯,另一方面和EI软件通讯。
            3,跟PLC通讯方面,checksoft作为伺服器,PLC作为客服端,我们便让checksoft 不断读取PLC某一软原件(备注:软元件相当于一个变量16BIT 或者32bit,这里是16bit的某一位,如MR402),当该位变成true,则置位标志位,通过该标志位让EI开始拍照,并且将结果回传给PLC。

软件结构

图片说明
##存在问题
现如今存在的问题是,checksoft在不断访问的过程中会出现UI界面卡死,出现未响应的情况。而且卡死在不同的地方,线程里有一个时钟一样的东西,有时候也会停止。

所做的解决措施

            1,利用文字记录在死循环中不断记录,看下是在哪个地方卡死,结果就是在卡死在了线程里面,也没有在EI软件通讯上。
            2,利用另一个线程监视该线程,但是我能力不够,不太成功,我上传的程序代码中,ControlUpdateAction中就是监视线程,可能我不太会用多线程。
            3,UI界面卡死,因此把所有的在软件显示数值的函数都注释了,客户用过还是会出现卡死的情况。
            4,EMI的问题考虑过,在网线上加了滤波磁环也不行

如若有不明白的地方,欢迎向我提问,QQ329917892

我会上传checksoft的源代码,和EI软件的安装包。望各位大侠慷慨解囊,各出奇招,帮帮小弟。

11个回答

界面不卡死才怪,你在UI线程里面那么多地方用了Thread.Sleep函数,这个函数你真的理解吗?windows系统是基于消息机制的,一旦你调用Thread.Sleep函数当前线程就会处于“假死”状态,不会处理任何鼠标键盘以及界面需要重绘的消息,所以永远不要在UI线程里面频繁的去调用Thead.Sleep函数,你按钮点击之后connect—open()函数大可以去开新的线程去处理,然后用invoke函数来处理跨线程调用UI控件的问题,还有我发现你在程序很多地方都用了死循环,而且有的地方连没有调用Thread.Sleep函数,这样的话你的cpu真的吃得消吗?总结来说两个问题:一:把你所有耗时的操作丢到子线程去处理,然后子线程如果要更新UI线程的界面就调用invoke函数实现,二:所有的死循环必须加上Thread.Sleep函数,让你的cpu“喘口气儿”

hxycsdn9159
hxycsdn9159 回复u010358801: 至于sleep多少是根据你实际需求来的,哪怕是sleep(0)也要sleep一下,给cpu一个喘气的空挡
一年多之前 回复
hxycsdn9159
hxycsdn9159 回复u010358801: sleep多少其实是根据你的实际情况来定的,主要问题是你再按钮的点击事件里面写了死循环而且调用sleep函数,按钮点击的事件可是在UI线程里执行的,你这样写就会造成界面假死
一年多之前 回复
u010358801
D_galaxy 这位大佬说的挺有道理的,我对C#还有些不了解的,我想问下载UI界面的线程具体是在哪里?然后,我的死循有两个地方!一个是用来工作的线程,另一个是监视工作线程的监视线程。所以SLEEP函数多久合适?我这个程序大概如何优化好一点
一年多之前 回复

很简单的你自己写个例子,在UI线程下面写个死循环然后里面调用Thead.Sleep函数,你看看你界面是不是会死掉,拖都拖不动
while(true)
{
Thread.Sleep(100);
}
把这个代码写到你的UI线程里面你可以试试,界面绝对一直处于“假死”状态

hxycsdn9159
hxycsdn9159 回复u010358801: Program.cs里的Main()函数就是UI线程的入口,一般UI线程都是[STAThread]单元线程模型
一年多之前 回复
u010358801
D_galaxy 你说的点我知道,就是不知道UI线程,在我程序的哪个位置 = =!!
一年多之前 回复

checksoft 软件 链接:https://pan.baidu.com/s/1om4pKDg-08bjkrVH8nEgUg 密码:gwnt 我的源代码

EI软件 链接:https://pan.baidu.com/s/14fGoUH4vpG0jT6k5Wc6BKg 密码:hwjx

u010358801
D_galaxy 我软件通讯是没问题的。只是不知道为什么会卡死
一年多之前 回复

是不是通过OPC的方式和PLC通讯,取得哪个点的状态,你开一个线程,线程里面调用一个委托(委托绑定一个方法),这个方法去读取那个点的状态显示在控件上面。

u010358801
D_galaxy 不是通过OPC和PLC连接,是SOCKET 网口上的通讯
一年多之前 回复

另外线程里面调用方法的时候加锁(防止多个地方同时调用这个方法),当你线程间隔时间太短,上一个步骤没完成,又开始了,或是几个地方同时操作这个方法就有可能down掉了。

u010358801
D_galaxy 我查了下,我现在只存在一个线程,那个监视线程是我后来加上去的,因此,我想问的是只有一个线程的话,就不存在非法调用的问题。
一年多之前 回复
u010358801
D_galaxy 现在我只有一个线程,就是用安全调用来调用这个方法?好的我试下
一年多之前 回复

既然用网线RJ45传输,那么软件在接受和发送数据协议的时候是否用到TCP/IP 协议。我觉得应该先解决通讯协议问题。只要是和PLC通过网口传输数据,就必须写TCP/IP协议。而且如果不行的话那只能用过C或者C#写232或者485通讯协议来和PLC通讯。

u010358801
D_galaxy 4、SOCKET连接与TCP连接 创建Socket连接时,可以指定使用的传输层协议,Socket可以支持不同的传输层协议(TCP或UDP),当使用TCP协议进行连接时,该Socket连接就是一个TCP连接。
一年多之前 回复

各位大佬,如果不行的话,我想采用两个线程,即一个是工作的线程,另一条是监视的线程。然后,监视的线程来监视工作的线程,如果工作的线程出现卡死的情况
卡死的情况,进行重启该线程。这种方法是否可行?

winner12315
winner12315 这种方法治标不治本。感觉程序可能出现BUG了。
一年多之前 回复
hxycsdn9159
hxycsdn9159 先不说你这种方法是否可行,就算可行也是治标不治本的方法,界面卡死的根本原因你还是没解决
一年多之前 回复

如果你实在不知道怎么找卡死的原因,最简单的方法,把全部代码注释掉,一点一点的放开,直到出现问题就是最后放开的代码造成的

hxycsdn9159
hxycsdn9159 回复u010358801: 界面卡死的原因不在于界面数据的更新,而是在于你在UI线程里面执行了耗时的操作,并且还使用了死循环,而且在死循环里使用sleep函数
一年多之前 回复
u010358801
D_galaxy 可以方便加我QQ,方便指导下吗?非常感谢!!
一年多之前 回复
u010358801
D_galaxy 对的。一开始,我就怀疑软件卡死的跟UI界面有关,因此把所有数据更新的函数都注释掉了。但是还出现软件的卡死。所以我才发布帖子求助,我是个小白,请多多指教。
一年多之前 回复
共11条数据 1 尾页
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
其他相关推荐
C#与PLC通讯,C#做从站中modbus寻址方式
C#与PLC通讯,modbus-RTU,c#做从站,比如我想用PLC读C#中D0的值,怎么在C#中把值赋进D0
C# 西门子PLC S7 200通信
现在是西门子PLC那边有2个寄存器地址,是VB510,VB50,510是我的C#向里面写数据,但是怎么读取500发给我的数据,怎么解析(500给我的就是阿拉伯数字)
C#通过pc access SAMRT与S7-200 SMART通讯,上位如何实时读PLC的变量,包括I/O信号
1,C#通过pc access 与S7-200 SMART通讯没有问题。已经连接成功。 2,在上位界面上做了几个按钮和textbox,触发按钮时,textbox可以读到变量的状态。实际变量通过PLC编程调试软件也能监控到变量变化。 3,我在上位上做一列指示灯。 想实现:PLC的变量发生改变时,这一列指示灯能够根据变量状态改变颜色。 实时刷新(200ms)。 例如: I0.0变为1时,指示灯0改变颜色,由红变绿。 . . . . . I0.7变为1时,指示灯改变颜色,由红变绿。 Q0.0变为1时,指示灯0改变颜色,由红变绿。 . . . . . Q0.7变为1时,指示灯改变颜色,由红变绿。 ![图片说明](https://img-ask.csdn.net/upload/201908/07/1565144872_203127.png)
C# USB转串口程序问题
现在是这样,我正在学C#,想先学学上位机程序,决定从串口通讯开始学习; 我手上有个施耐德和ABB的PLC,我准备用电脑走MODBUS/RTU通讯来控制PLC; 但是现在我发现我的电脑上没有串口,即在设备管理器里面看不到端口这个栏目,没有COM口; 我记得我以前调试MODBUS/RTU通讯的时候,有用到一个USB转串口的线,然后用一个串口调试助手来实现数据截取;我很疑惑这个程序是不是从USB端口里面拿的数据,即数据经过USB转串口线,然后程序读取USB内的数据,在展现出来; 那么问题来了,我现在是继续寻找发掘现在电脑的串口在哪里,继续走开发串口的路子; 还是用USB转串口这样,从USB口走数据,然后自己写一个串口调试工具这样
C#和三菱PLC socket网络通信
以下代码是用C++和PLC通信,但是我看不懂C++,能帮我把这段代码用C#的形式写出来吗? 或者有能直接和PLC网络通信的C#源码,感谢各位高手,谢谢,非常感谢~~~ ------------------------------------------------------------------------ #include "stdafx.h" #include "SensorMounter.h" #include "SocketThread.h" IMPLEMENT_DYNCREATE(CSocketThread, CWinThread) CSocketThread::CSocketThread() : m_sIPAddress(_T("")) { m_nSocketPort = 0; m_bConnected = FALSE; m_nWtmE1 = 0; } CSocketThread::~CSocketThread() { } BOOL CSocketThread::InitInstance() return TRUE; } int CSocketThread::ExitInstance() { return CWinThread::ExitInstance(); } BEGIN_MESSAGE_MAP(CSocketThread, CWinThread) ON_THREAD_MESSAGE(WMU_SOCKET_CONNECT, OnSConnect) ON_THREAD_MESSAGE(WMU_SOCKET_SEND, OnSSend) ON_THREAD_MESSAGE(WMU_SOCKET_RECV, OnSRecv) ON_THREAD_MESSAGE(WMU_SOCKET_CLOSE, OnSClose) ON_THREAD_MESSAGE(WMU_SOCKET_QUIT, OnSQuit) END_MESSAGE_MAP() void CSocketThread::OnSConnect(UINT wParam, LONG lParam) { TRACE("CSocketThread::OnSConnect: start\n"); BOOL bRC = SocketConnect(); _ST_SEND *pSend = (_ST_SEND *)wParam; if (!pSend) return; pSend->nDoneSize = (bRC ? 0 : -1); if (pSend->hwndDone) ::SendMessage(pSend->hwndDone, WMU_SOCKET_DONE, (WPARAM)pSend, (LPARAM)pSend->nDoneSize); if (pSend->hEvDone) SetEvent(pSend->hEvDone); } void CSocketThread::OnSSend(UINT wParam, LONG lParam) { TRACE("CSocketThread::OnSSend: start\n"); _ST_SEND *pSend = (_ST_SEND *)wParam; if (!pSend) return; if (!m_bConnected) { pSend->nDoneSize = -1; if (pSend->hwndDone) ::SendMessage(pSend->hwndDone, WMU_SOCKET_DONE, (WPARAM)pSend, (LPARAM)(-1)); if (pSend->hEvDone) SetEvent(pSend->hEvDone); return; } pSend->nDoneSize = 0; switch (pSend->nDataType) { case _ST_DATA: pSend->nDoneSize = SocketSendData(pSend->nAddr, *((WORD *)pSend->pData), pSend->bDebugDisp); break; case _ST_MULTIBYTE: pSend->nDoneSize = SocketSendMultiByte(pSend->nSize, pSend->nAddr, pSend->pData, pSend->bDebugDisp); break; case _ST_MULTIWORD: pSend->nDoneSize = SocketSendMultiWord(pSend->nSize, pSend->nAddr, (WORD *)pSend->pData, pSend->bDebugDisp); break; case _ST_MULTIBYTE_BIN: pSend->nDoneSize = SocketBinSendMultiByte(pSend->nSize, pSend->nAddr, pSend->pData, pSend->bDebugDisp); break; case _ST_MULTIWORD_BIN: pSend->nDoneSize = SocketBinSendMultiWord(pSend->nSize, pSend->nAddr, (WORD *)pSend->pData, pSend->bDebugDisp); break; default: break; } if (pSend->hwndDone) ::SendMessage(pSend->hwndDone, WMU_SOCKET_DONE, (WPARAM)pSend, (LPARAM)(pSend->nDoneSize)); if (pSend->hEvDone) SetEvent(pSend->hEvDone); } void CSocketThread::OnSRecv(UINT wParam, LONG lParam) { _ST_SEND *pSend = (_ST_SEND *)wParam; if (!pSend) return; if (!m_bConnected) { pSend->nDoneSize = -1; if (pSend->hwndDone) ::SendMessage(pSend->hwndDone, WMU_SOCKET_DONE, (WPARAM)pSend, (LPARAM)(-1)); if (pSend->hEvDone) SetEvent(pSend->hEvDone); return; } BOOL bRC; switch (pSend->nDataType) { case _ST_DATA: bRC = SocketReceiveData(pSend->nAddr, (WORD *)pSend->pData, pSend->bDebugDisp); pSend->nDoneSize = (bRC ? sizeof(WORD) : 0); break; case _ST_MULTIBYTE: break; case _ST_MULTIWORD: bRC = SocketReceiveMultiWord(pSend->nSize, pSend->nAddr, (WORD *)pSend->pData, pSend->bDebugDisp); pSend->nDoneSize = (bRC ? pSend->nSize : 0); break; case _ST_MULTIWORD_BIN: bRC = SocketBinReceiveMultiWord(pSend->nSize, pSend->nAddr, (WORD *)pSend->pData, pSend->bDebugDisp); pSend->nDoneSize = (bRC ? pSend->nSize : 0); break; default: break; } if (pSend->hwndDone) ::SendMessage(pSend->hwndDone, WMU_SOCKET_DONE, (WPARAM)pSend, (LPARAM)(pSend->nDoneSize)); if (pSend->hEvDone) SetEvent(pSend->hEvDone); } void CSocketThread::OnSClose(UINT wParam, LONG lParam) { TRACE("CSocketThread::OnSClose: start\n"); SocketDisconnect(); } void CSocketThread::OnSQuit(UINT wParam, LONG lParam) { TRACE("CSocketThread::OnSQuit: start"); // AfxEndThread(0); ::PostQuitMessage(0); } BOOL CSocketThread::SocketConnect() { BOOL bRet; bRet = m_SW.Socket(m_nSocketPort); if (!bRet) { CString msg; msg.Format("[NG] port:%d code = %d:%d", m_nSocketPort, m_SW.m_nErrorCode, m_SW.m_nLastError); MessageBox(NULL, (LPCTSTR)msg, _T("CSocketThread::SocketConnect: Connect"), MB_ICONERROR); return (m_bConnected = FALSE); } bRet = m_SW.Connect((LPCTSTR)m_sIPAddress); if (!bRet) { CString msg; msg.Format("[NG] Host Connect Error \n HostName:%s code = %d:%d", (LPCTSTR)m_sIPAddress, m_SW.m_nErrorCode, m_SW.m_nLastError); MessageBox(NULL, (LPCTSTR)msg, _T("CSocketThread::SocketConnect: Connect"), MB_ICONERROR); return (m_bConnected = FALSE); } return (m_bConnected = TRUE); } BOOL CSocketThread::SocketBinSendMultiByte(int nDataNum, UINT nAddress, BYTE ucData[], BOOL bDebugDisp) { BYTE pSendBuf[37] = { 0x50, 0x00, 0x00, 0xFF, 0xFF, 0x03, 0x00, 0xCC, 0xCC, 0x10, 0x00, 0x01, 0x14, 0x01, 0x00, 0xCC, 0xCC, 0xCC, 0x90, 0xCC, 0xCC, 0xD1, 0xD1, 0xD1, 0xD1, 0xD2, 0xD2, 0xD2, 0xD2, 0xD3, 0xD3, 0xD3, 0xD3, 0xD4, 0xD4, 0xD4, 0xD4 }; WORD wDataLength = 12 + nDataNum*4; DWORD dwDeviceAddr = nAddress + (0x90<<24); WORD wDeviceNum = nDataNum*8; memcpy( &pSendBuf[7], &wDataLength, 2); memcpy( &pSendBuf[15], &dwDeviceAddr, 4); memcpy( &pSendBuf[19], &wDeviceNum, 2); BYTE pBuf[4]; for (int i=0; i<nDataNum; i++) { for (int j=0; j<4; j++) { pBuf[j] = 0x00; if( (ucData[i]&(0x01<<j*2)) ) pBuf[j] |= 0x10; if( (ucData[i]&(0x01<<(j*2+1))) ) pBuf[j] |= 0x01; } memcpy( &pSendBuf[21+i*4], &pBuf, 4); } int nSend = m_SW.SendBin( pSendBuf, 21+nDataNum*4 ); if (nSend < 0) { SocketDispErrorCode(_T("SendMultiByte(send)")); return FALSE; } if(m_nWtmE1 > 0) Sleep(m_nWtmE1); BYTE pReceiveBuf[11]; long nReceive = m_SW.ReadBin( pReceiveBuf, 11); if ( nReceive < 1 ) { SocketDispErrorCode(_T("SendMultiByte(receive)")); return FALSE; } if ( pReceiveBuf[0]==0xD0 && pReceiveBuf[1]==0x00 && pReceiveBuf[2]==0x00 && pReceiveBuf[3]==0xFF && pReceiveBuf[4]==0xFF && pReceiveBuf[5]==0x03 && pReceiveBuf[9]==0x00 && pReceiveBuf[10]==0x00 ) { if(pReceiveBuf[7]==2) return TRUE; else if(pReceiveBuf[7]==0) return FALSE; } nReceive = m_SW.ReadBin( pReceiveBuf, pReceiveBuf[7]-2); if ( nReceive < 1 ) { SocketDispErrorCode(_T("SendMultiByte(receive)")); return FALSE; } return TRUE; } BOOL CSocketThread::SocketBinSendMultiWord(int nDataNum, UINT nAddress, WORD wData[], BOOL bDebugDisp) { BYTE pSendBuf[33] = { 0x50, 0x00, 0x00, 0xFF, 0xFF, 0x03, 0x00, 0xCC, 0xCC, 0x10, 0x00, 0x01, 0x14, 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xA8, 0xCC, 0xCC, 0xD1, 0xD1, 0xD2, 0xD2, 0xD3, 0xD3, 0xD4, 0xD4, 0xD5, 0xD5, 0xD6, 0xD6 }; WORD wDataLength = 12+nDataNum*2; DWORD dwDeviceAddr = nAddress + (0xA8<<24); WORD wDeviceNum = nDataNum; memcpy( &pSendBuf[7], &wDataLength, 2); memcpy( &pSendBuf[15], &dwDeviceAddr, 4); memcpy( &pSendBuf[19], &wDeviceNum, 2); memcpy( &pSendBuf[21], &wData, nDataNum); for (int i=0; i<nDataNum; i++){ pSendBuf[22+i*2] = (wData[i]&0xFF00)>>8; pSendBuf[21+i*2] = wData[i]&0x00FF; } int nSend = m_SW.SendBin( pSendBuf, 21+nDataNum*2 ); if (nSend < 0) { SocketDispErrorCode(_T("SendMultiWord(send)")); return FALSE; } if(m_nWtmE1 > 0) Sleep(m_nWtmE1); BYTE pReceiveBuf[11]; long nReceive = m_SW.ReadBin( pReceiveBuf, 11); if ( nReceive < 1 ) { SocketDispErrorCode(_T("SendMultiWord(receive)")); return FALSE; } if ( pReceiveBuf[0]==0xD0 && pReceiveBuf[1]==0x00 && pReceiveBuf[2]==0x00 && pReceiveBuf[3]==0xFF && pReceiveBuf[4]==0xFF && pReceiveBuf[5]==0x03 && pReceiveBuf[9]==0x00 && pReceiveBuf[10]==0x00 ) { if (pReceiveBuf[7]==2) return TRUE; else if (pReceiveBuf[7]==0) return FALSE; } nReceive = m_SW.ReadBin( pReceiveBuf, pReceiveBuf[7]-2); if ( nReceive < 1 ) { SocketDispErrorCode(_T("SendMultiByte(receive)")); return FALSE; } return TRUE; } BOOL CSocketThread::SocketBinReceiveMultiWord(int nDataNum, UINT nAddress, WORD wData[], BOOL bDeviceCode) { BYTE pSendBuf[21] = { 0x50, 0x00, 0x00, 0xFF, 0xFF, 0x03, 0x00, 0xCC, 0xCC, 0x10, 0x00, 0x01, 0x04, 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0x90, 0xCC, 0xCC }; WORD wDataLength = 12; DWORD dwDeviceAddr; if (bDeviceCode==FALSE) dwDeviceAddr = nAddress+(0x90<<24); else dwDeviceAddr = nAddress+(0xA8<<24); WORD wDeviceNum = nDataNum; memcpy( &pSendBuf[7], &wDataLength, 2); memcpy( &pSendBuf[15], &dwDeviceAddr, 4); memcpy( &pSendBuf[19], &wDeviceNum, 2); int nSend = m_SW.SendBin( pSendBuf, 21 ); if (nSend < 0) { SocketDispErrorCode(_T("SendMultiWord(send)")); return FALSE; } if(m_nWtmE1 > 0) Sleep(m_nWtmE1); BYTE pReceiveBuf[21]; int nReadLength; for (int i=0; i<21; i++) pReceiveBuf[i] = 0; long nReceive = m_SW.ReadBin( pReceiveBuf, 11); if ( nReceive < 1 ) { SocketDispErrorCode(_T("SendMultiWord(receive)")); return FALSE; } if ( pReceiveBuf[0]==0xD0 && pReceiveBuf[1]==0x00 && pReceiveBuf[2]==0x00 && pReceiveBuf[3]==0xFF && pReceiveBuf[4]==0xFF && pReceiveBuf[5]==0x03 && pReceiveBuf[9]==0x00 && pReceiveBuf[10]==0x00 ) { if(pReceiveBuf[7]==0 || pReceiveBuf[7]==2 ) return FALSE; else nReadLength = pReceiveBuf[7]-2; } else { return FALSE; } for (int i=0; i<21; i++) pReceiveBuf[i] = 0; nReceive = m_SW.ReadBin( pReceiveBuf, nReadLength); if ( nReceive < 1 ) { SocketDispErrorCode(_T("SendMultiByte(receive)")); return FALSE; } else { for(int i=0; i<nDataNum; i++) wData[i] = pReceiveBuf[2*i] + (pReceiveBuf[2*i+1]<<8); return TRUE; } } BOOL CSocketThread::SocketDisconnect(void) { return m_SW.Shutdown(); } void CSocketThread::SocketDispErrorCode(LPCTSTR strFunc) { CString strCode, strMsg; switch (m_SW.m_nErrorCode) { case 101: strCode="IDP_SOCKETS_INIT_FAILED"; break; case 1201: strCode="SW_ERR_NOERROR"; break; case 1202: strCode="SW_ERR_WSASTARTUP"; break; case 1203: strCode="SW_ERR_GETSERV"; break; case 1204: strCode="SW_ERR_GETHOSTNAME"; break; case 1205: strCode="SW_ERR_GETHOSTENT"; break; case 1206: strCode="SW_ERR_SOCK_STREAM"; break; case 1207: strCode="SW_ERR_BIND"; break; case 1208: strCode="SW_ERR_LISTEN"; break; case 1209: strCode="SW_ERR_ACCEPTTHREAD"; break; case 1210: strCode="SW_ERR_BUFFER_OVER"; break; case 1211: strCode="SW_ERR_READ"; break; case 1212: strCode="SW_ERR_SEND"; break; case 1213: strCode="SW_ERR_CONNECT"; break; case 1214: strCode="SW_ERR_ACCEPT"; break; case 1215: strCode="SW_ERR_RESUME_FAIL"; break; case 1216: strCode="SW_CONNECT_CLOSED"; break; } strMsg.Format(" Function : %s \n ErrorCode : %s \n LastError : %d", strFunc, strCode, m_SW.m_nLastError); MessageBox(NULL, (LPCTSTR)strMsg, _T("CSocketThread::SocketDispErrorCode"), MB_ICONERROR); }
c#如何给台达Plc的D0写入65536,然后读取D0的值?
c# 给台达Plc的D0写入65536,基于ModbusASCII协议,网上都没有例子,可能过于简单别人不屑一顾,本人新手(代码最好注释不然看不懂给我也没用).希望神仙们赐教
C#多线程访问PLC MXComponent
![图片说明](https://img-ask.csdn.net/upload/201904/29/1556549325_63419.png) 开三个线程同时读取三菱PLC内变量数据。不知道问什么报错,用单线程就没有问题。第一个线程能通过,第二个就报错。 public partial class Form1 : Form { public ACTETHERLib.ActQNUDECPUTCP plc1 = null; public ACTETHERLib.ActQNUDECPUTCP plc2 = null; public ACTETHERLib.ActQNUDECPUTCP plc3 = null; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { this.plc1 = new ACTETHERLib.ActQNUDECPUTCP(); this.plc2 = new ACTETHERLib.ActQNUDECPUTCP(); this.plc3 = new ACTETHERLib.ActQNUDECPUTCP(); this.plc1.ActHostAddress ="192.168.1.21"; this.plc1.ActHostAddress = "192.168.1.31"; this.plc1.ActHostAddress = "192.168.1.41"; int rtn1 = this.plc1.Open(); int rtn2 = this.plc2.Open(); int rtn3 = this.plc3.Open(); if (rtn1 == 0) MessageBox.Show("PLC1 Connect Succesful !"); else MessageBox.Show("PLC1 Connect Fail,Please Check Comunication Setting!"); if (rtn2 == 0) MessageBox.Show("PLC1 Connect Succesful !"); else MessageBox.Show("PLC2 Connect Fail,Please Check Comunication Setting!"); if (rtn3 == 0) MessageBox.Show("PLC1 Connect Succesful !"); else MessageBox.Show("PLC2 Connect Fail,Please Check Comunication Setting!"); Thread Read_PLC1_thread = new Thread(new ThreadStart(Read_PLC1)); Thread Read_PLC2_thread = new Thread(new ThreadStart(Read_PLC2)); Thread Read_PLC3_thread = new Thread(new ThreadStart(Read_PLC3)); Read_PLC1_thread.Start(); Read_PLC2_thread.Start(); Read_PLC3_thread.Start(); } private void Read_PLC1() { int[] PLC1_D = new int[100]; int rtn1 = this.plc1.ReadDeviceBlock("D1", 10, out PLC1_D[1]); } private void Read_PLC2() { int[] PLC2_D = new int[100]; int rtn2 = this.plc2.ReadDeviceBlock("D1", 10, out PLC2_D[1]); } private void Read_PLC3() { int[] PLC3_D = new int[100]; int rtn3 = this.plc3.ReadDeviceBlock("D1", 10, out PLC3_D[1]); } } ![图片说明](https://img-ask.csdn.net/upload/201904/07/1554638887_266844.png) }
c# 运用serialport与PLC串口通讯,读取(例如D200)的数据
网上下的 c# 运用serialport与PLC串口通讯程序,小白看不太懂下的程序,求大神帮忙分析下,主要想知道程序中的tebox1、textbox4、textbox5、textbox6、textbox7分别对应图中哪个空,对应的空应填写什么,例如想读取三菱F3X系列PLC D200的数据,初始地址填200?那设备地址和长度填啥? 界面如下:![图片说明](https://img-ask.csdn.net/upload/201806/14/1528961750_92350.png) 主要程序如下: private void btn_open_Click(object sender, EventArgs e) { int nSelect; btn_open.Enabled = false; Object selectedItem = cbxCOMPort.SelectedItem; sp.PortName = selectedItem.ToString();//串口 selectedItem = cbxBaudRate.SelectedItem; sp.BaudRate = int.Parse(selectedItem.ToString());//波特率 nSelect = cbxDataBits.SelectedIndex;//数据位 switch (nSelect) { case 0: sp.DataBits = 8; break; case 1: sp.DataBits = 7; break; case 2: sp.DataBits = 6; break; case 3: sp.DataBits = 5; break; } nSelect = cbxParity.SelectedIndex; switch (nSelect) { case 0: sp.Parity = Parity.None; break; case 1: sp.Parity = Parity.Odd; break; case 2: sp.Parity = Parity.Even; break; case 3: sp.Parity = Parity.Mark; break; case 4: sp.Parity = Parity.Space; break; } nSelect = cbxStopBits.SelectedIndex; switch (nSelect) { case 0: sp.StopBits = StopBits.None; break; case 1: sp.StopBits = StopBits.One; break; case 2: sp.StopBits = StopBits.OnePointFive; break; case 3: sp.StopBits = StopBits.Two; break; } sp.Open(); btn_close.Enabled = true; } private void btn_send_Click(object sender, EventArgs e) { textBox1.Text = ""; int n = 6; byte[] buf = new byte[n]; string ee = textBox4.Text; buf[0] = Convert.ToByte(ee); if (comboBox1.Text == "3X") { buf[1] = Convert.ToByte(3); } else { buf[1] = Convert.ToByte(4); } if (int.Parse(textBox5.Text) <= 255) { buf[2] = Convert.ToByte(0); buf[3] = Convert.ToByte(int.Parse(textBox5.Text)); } else { if (Convert.ToString(int.Parse(textBox5.Text), 16).Length < 4) { int b = Convert.ToInt32(Convert.ToString(int.Parse(textBox5.Text), 16).Substring(0, 1), 16); buf[2] = Convert.ToByte(b); int c = Convert.ToInt32(Convert.ToString(int.Parse(textBox5.Text), 16).Substring(1, 2), 16); buf[3] = Convert.ToByte(c); } else { int b = Convert.ToInt32(Convert.ToString(int.Parse(textBox5.Text), 16).Substring(0, 2), 16); buf[2] = Convert.ToByte(b); int c = Convert.ToInt32(Convert.ToString(int.Parse(textBox5.Text), 16).Substring(2, 2), 16); buf[3] = Convert.ToByte(c); } } if (int.Parse(textBox6.Text) <= 255) { buf[4] = Convert.ToByte(0); buf[5] = Convert.ToByte(int.Parse(textBox6.Text)); } else { if (Convert.ToString(int.Parse(textBox6.Text), 16).Length < 4) { int d = Convert.ToInt32(Convert.ToString(int.Parse(textBox6.Text), 16).Substring(0, 1), 16); buf[4] = Convert.ToByte(d); int f = Convert.ToInt32(Convert.ToString(int.Parse(textBox6.Text), 16).Substring(1, 2), 16); buf[5] = Convert.ToByte(f); } else { int d = Convert.ToInt32(Convert.ToString(int.Parse(textBox6.Text), 16).Substring(0, 2), 16); buf[4] = Convert.ToByte(d); int f = Convert.ToInt32(Convert.ToString(int.Parse(textBox6.Text), 16).Substring(2, 2), 16); buf[5] = Convert.ToByte(f); } } p = int.Parse(textBox6.Text) * 2 + 5; byte[] buf1 = new byte[n + 2]; byte[] ReturnData = new byte[2]; ReturnData = CRC16_C(buf); for (int i = 0; i < n; i++) { buf1[i] = buf[i]; } buf1[n] = ReturnData[1]; buf1[n + 1] = ReturnData[0]; sp.Write(buf1.ToArray(), 0, n + 2); } void sp_DataReceived(object sender, SerialDataReceivedEventArgs e) { int n = sp.BytesToRead; byte[] TxData = new byte[n];//声明一个临时数组存储当前来的串口数据 sp.Read(TxData, 0, n); //读取缓冲数据 m = m + n; this.Invoke((EventHandler) (delegate { Array.Resize(ref TxData2, m);//改写数组大小 TxData.CopyTo(TxData2, m - TxData.Length); if (m == p) { byte[] data = new byte[p - 2]; for (int i = 0; i < TxData2.Length - 2; i++) { data[i] = TxData2[i]; } byte[] data2 = new byte[2]; data2[0] = TxData2[TxData2.Length - 2]; data2[1] = TxData2[TxData2.Length - 1]; byte[] data1 = new byte[2]; data1 = CRC16_C(data); if (data1[0] == data2[1] && data1[1] == data2[0]) { for (int j = 3; j <= m - 4; j = j + 2) { string s1 = TxData2[j].ToString(); string s2 = TxData2[j + 1].ToString(); string s = s1 + s2; int g = Convert.ToInt32(s, 10); string h = g.ToString(); textBox1.Text += h + " "; } textBox7.Text = "读取成功"; } else { textBox7.Text = "读取失败"; } m = 0; } } ) ); } public byte[] CRC16_C(byte[] data) { byte CRC16Lo; byte CRC16Hi; byte CL; byte CH; byte SaveHi; byte SaveLo; byte[] tmpData; int Flag; CRC16Lo = 0xFF; CRC16Hi = 0xFF; CL = 0x01; CH = 0xA0; tmpData = data; for (int i = 0; i < tmpData.Length; i++) { CRC16Lo = (byte)(CRC16Lo ^ tmpData[i]); for (Flag = 0; Flag <= 7; Flag++) { SaveHi = CRC16Hi; SaveLo = CRC16Lo; CRC16Hi = (byte)(CRC16Hi >> 1); CRC16Lo = (byte)(CRC16Lo >> 1); if ((SaveHi & 0x01) == 0x01) { CRC16Lo = (byte)(CRC16Lo | 0x80); } if ((SaveLo & 0x01) == 0x01) { CRC16Hi = (byte)(CRC16Hi ^ CH); CRC16Lo = (byte)(CRC16Lo ^ CL); } } } byte[] ReturnData = new byte[2]; ReturnData[0] = CRC16Hi; ReturnData[1] = CRC16Lo; return ReturnData;
C#如何向PLC中写入小数值?
如题,如何将小数值传给PLC,小数值该用double类型还是float类型
欧姆龙NJ系列c#写的界面程序通过sysmacgateway怎么和PLC通信
欧姆龙NJ系列c#写的界面程序通过sysmacgateway怎么和PLC通信!通过cip这些dll!要怎么使用这些方法对PLC更改变量!有相关例子和文档吗
在虚拟机中安装的AB PLC软件使用以太网通讯总是失败?请大神解答一下
在虚拟机中安装的AB PLC软件使用以太网通讯总是,在与intouch 相连接,使用了很多连接办法,最后只能通过intouch 向plc发送指令,却不能接收状态信号,这是为什么?请大神解答一下
PLC TCP通信报错10061
电脑通过网口连接三菱PLC,可以ping的通,但用以下代码就一直报10061的错误: ``` int main() { // initialize winsock WORD wVer = MAKEWORD(1, 1); // version NO:1.1, #include <WINSOCK.H> WSADATA wData; int err = WSAStartup(wVer, &wData); if (err) { printf("cannot initialize WinSock\n"); return 1; } // 建立SOCKET通信 SOCKET s = 0; s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); struct sockaddr_in server; server.sin_family = AF_INET; server.sin_port = htons(1); // ASA standard port server.sin_addr.s_addr = inet_addr("192.168.3.250"); // 建立CONNECT连接 int i = connect(s, (sockaddr *)&server, sizeof(sockaddr_in)); if (i < 0) // #define SOCKET_ERROR (-1) { printf("connect - error %d\n", WSAGetLastError()); closesocket(s); WSACleanup(); return 1; } return 0; } ``` 运行到connect指令就会返回10061的错误码,在cmd里ping 192.168.3.250是没问题的,但是htons( )里的端口号我不能确定,也不知道三菱PLC有没有默认的端口号,试了很多,除了给0会报10049的错误外,其它都是报10061。 麻烦那位大神帮忙看一下,头大,试了一天了
C#与西门子200通讯,读取超过3个字节,界面就死机,求教
使用C#编写了一个与PLC通讯的串口通讯程序,可以通讯和读取数据,但是不能超过3个字节,不知道什么原因,求教。 if (bz == 1) { byte[] dataa = { 0x68, 0x1B, 0x1B, 0x68, 0x02, 0x00, 0x6C, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x04, 0x01, 0x12, 0x0A, 0x10, 0x02, 0x00, 0x03, 0x00, 0x01, 0x84, 0x00, 0x03, 0x20, 0x8D, 0x0016 };//发送指定的16进制字节数组 serialPort1.Write(dataa, 0, dataa.Length); } 把0x03改成0x04就不行了。
用C++写个软件和PLC进行网络通讯,需要学习些什么?
用C++MFC做个软件和欧姆龙PLC进行网络通讯,实现读写PLC里面的数据,有没有人知道要掌握什么知识,现在已经掌握了C/C++编程和MFC编程 了,需不需要学习C++网络编程的知识?还有MFC界面上要绘制哪些东西?
Java实现与plc的通讯的问题
需要实现与台达plc的通讯,不知道硬件用什么与这个plc连接,软件上目前没调试,不知道modbus4j行不行,现在主要是硬件问题!
PC和PLC通过PPI通讯的问题
pc和plc通过ppi通讯,我用一个usb转485转换器,转换后将数据线直接连接到plc的通讯端口上,然后用串口调试工具发送指令,没有返回值是什么原因呢?
C#写OPC客户端,进行读写。如何批量写入?
C#写OPC客户端,进行读写。如何批量写入?。。单个数据写入PLC的DB段的方法如下。知道要写入的DB段的位置,如:S7:[S7 connection_1]DB53,CHAR30。本人想从53,CHAR30到53,CHAR61批量写入相应的数据。已知DB地址数组和相应的数据数组,如何写入?急!!! private void btnWrite_Click(object sender, EventArgs e) { OPCItem bItem = KepItems.GetOPCItem(itmHandleServer); //S7:[S7 connection_1]DB53,CHAR30 int[] temp = new int[2] { 0, bItem.ServerHandle }; Array serverHandles=(Array)temp; object[] valueTemp = new object[2] {"",txtWriteTagValue.Text }; Array values=(Array)valueTemp; Array Errors; int cancelID; KepGroup.AsyncWrite(1,ref serverHandles,ref values,out Errors, 2009,out cancelID); //KepItem.Write(txtWriteTagValue.Text);//这句也可以写入,但并不触发写入事件 GC.Collect(); }
java程序读取PLC的浮点数,读取到的小数位错误,请问如何解决?
1.采用modbus4j实现了modbus通信,但读取PLC的浮点数时,读取到整数位正确,小数位错误,请问如何解决? 2. 读取PLC保持寄存器的方法如下: ``` readHoldingRegistersTest(master,1,1,4); private static void readHoldingRegistersTest(ModbusMaster master, int slaveId, int start, int len) { try { ReadHoldingRegistersRequest request = new ReadHoldingRegistersRequest( slaveId, start, len); ReadHoldingRegistersResponse response = (ReadHoldingRegistersResponse) master .send(request); if (response.isException()) { System.out.println("Exception response: message=" + response.getExceptionMessage()); } else { System.out.println(Arrays.toString(response.getShortData())); short[] list = response.getShortData(); byte[] bb = shortToBytes(list); Float ff=byte2float(bb,0); System.out.println("读到"+ff); } } catch (ModbusTransportException e) { e.printStackTrace(); } } ``` 3.和PLC通讯时,PLC给出的数字为46.68,程序读取到的数字为46.5,![图片说明](https://img-ask.csdn.net/upload/201912/10/1575987797_782854.png) 4.和modbus slave仿真软件通讯时,数据读取正常。控制台输出如下:
类的定义和它的成员函数的实现分开放会报错
为什么将类的定义和它的成员函数的实现分别放在.h和.cpp中就会报错: LNK2019: 无法解析的外部符号 "public: void __cdecl YtPlc_Mitsubishi_Mc::InitParam(void)" (?InitParam@YtPlc_Mitsubishi_Mc@@QEAAXXZ),该符号在函数 main 中被引用 PLC_test D:\zhoujy\prj\PLC_test\PLC_test\PLC_test.obj .h中的代码如下: ``` class YtPlc_Mitsubishi_Mc // : public YtPlc { public: YtPlc_Mitsubishi_Mc(); //初始化参数 void InitParam(); }; ``` .cpp中的实现如下: ``` #include "ytplc_mitsubishi_mc.h" YtPlc_Mitsubishi_Mc::YtPlc_Mitsubishi_Mc() { } void YtPlc_Mitsubishi_Mc::InitParam() { //发送命令 write_buff_[0] = 0x50; // 副头部 write_buff_[1] = 0x00; // 副头部 write_buff_[2] = 0x00; // 网络编号 write_buff_[3] = (char)0xff; // 可编程控制器编号 write_buff_[4] = (char)0xff; // 请求目标模块I/O编号L write_buff_[5] = 0x03; // 请求目标模块I/O编号H write_buff_[6] = 0x00; // 请求目标模块站号 // 长度从CPU监视定时器L到指令结束 write_buff_[7] = 0x00; //请求数据长度L write_buff_[8] = 0x00; //请求数据长度H //CPU 监视定时器 0:无限等待 0001~FFFF H (1~65535): 等待时间(单位 250ms) @《三菱Q_L系列通信协议参考》3.1.3 P73 write_buff_[9] = 0x01; // CPU监视定时器L write_buff_[10] = 0x00; // CPU监视定时器H // 指令1401 @《三菱Q_L系列通信协议参考》3.3.7 P154 write_buff_[11] = 0x01; // 指令L write_buff_[12] = 0x14; // 指令H write_buff_[13] = 0x00; // 子指令L write_buff_[14] = 0x00; // 子指令H // 字单位的批量写入 write_buff_[15] = 0x00; // 起始软元件 write_buff_[16] = 0x00; // 起始软元件 write_buff_[17] = 0x00; // 起始软元件 write_buff_[18] = 0x00; // 软元件代码 write_buff_[19] = 0x00; // 软元件点数 write_buff_[20] = 0x00; // 软元件点数 // 软元件点数的范围 // e.g 1995H 1202H 1130H -> {95H 19H 02H 12H 30H 12H} for (int i = 0; i < 20; i++) { write_buff_[21 + i * 2] = 0x00; write_buff_[21 + i * 2 + 1] = 0x00; } //读取命令 read_buff_[0] = 0x50; // 副头部 read_buff_[1] = 0x00; // 副头部 read_buff_[2] = 0x00; // 网络编号 read_buff_[3] = (char)0xff; // 可编程控制器编号 read_buff_[4] = (char)0xff; // 请求目标模块I/O编号L read_buff_[5] = 0x03; // 请求目标模块I/O编号H read_buff_[6] = 0x00; // 请求目标模块站号 read_buff_[7] = 0x0c; //请求数据长度L read_buff_[8] = 0x00; //请求数据长度H //CPU 监视定时器 0:无限等待 0001~FFFF H (1~65535): 等待时间(单位 250ms) @《三菱Q_L系列通信协议参考》3.1.3 P73 read_buff_[9] = 0x01; // CPU监视定时器L read_buff_[10] = 0x00; // CPU监视定时器H // 0401 T寄存器读取 @《三菱Q_L系列通信协议参考》3.3.6 P150 // WARNING: M寄存器读取 send_buff_[18] = 0x90 待确认 read_buff_[11] = 0x01; // 指令L read_buff_[12] = 0x04; // 指令H read_buff_[13] = 0x00; // 子指令L read_buff_[14] = 0x00; // 子指令H // 字单位的批量写入 read_buff_[15] = 0x00; // 起始软元件 read_buff_[16] = 0x00; // 起始软元件 read_buff_[17] = 0x00; // 起始软元件 read_buff_[18] = 0x00; // 软元件代码 read_buff_[19] = 0x00; // 软元件点数 read_buff_[20] = 0x00; // 软元件点数 } ``` 但如果把它们都放到头文件中,即把成员函数和构造函数的实现和类的定义放到一起,就不会有这个问题了
Java学习的正确打开方式
在博主认为,对于入门级学习java的最佳学习方法莫过于视频+博客+书籍+总结,前三者博主将淋漓尽致地挥毫于这篇博客文章中,至于总结在于个人,实际上越到后面你会发现学习的最好方式就是阅读参考官方文档其次就是国内的书籍,博客次之,这又是一个层次了,这里暂时不提后面再谈。博主将为各位入门java保驾护航,各位只管冲鸭!!!上天是公平的,只要不辜负时间,时间自然不会辜负你。 何谓学习?博主所理解的学习,它是一个过程,是一个不断累积、不断沉淀、不断总结、善于传达自己的个人见解以及乐于分享的过程。
程序员必须掌握的核心算法有哪些?
由于我之前一直强调数据结构以及算法学习的重要性,所以就有一些读者经常问我,数据结构与算法应该要学习到哪个程度呢?,说实话,这个问题我不知道要怎么回答你,主要取决于你想学习到哪些程度,不过针对这个问题,我稍微总结一下我学过的算法知识点,以及我觉得值得学习的算法。这些算法与数据结构的学习大多数是零散的,并没有一本把他们全部覆盖的书籍。下面是我觉得值得学习的一些算法以及数据结构,当然,我也会整理一些看过...
大学四年自学走来,这些私藏的实用工具/学习网站我贡献出来了
大学四年,看课本是不可能一直看课本的了,对于学习,特别是自学,善于搜索网上的一些资源来辅助,还是非常有必要的,下面我就把这几年私藏的各种资源,网站贡献出来给你们。主要有:电子书搜索、实用工具、在线视频学习网站、非视频学习网站、软件下载、面试/求职必备网站。 注意:文中提到的所有资源,文末我都给你整理好了,你们只管拿去,如果觉得不错,转发、分享就是最大的支持了。 一、电子书搜索 对于大部分程序员...
linux系列之常用运维命令整理笔录
本博客记录工作中需要的linux运维命令,大学时候开始接触linux,会一些基本操作,可是都没有整理起来,加上是做开发,不做运维,有些命令忘记了,所以现在整理成博客,当然vi,文件操作等就不介绍了,慢慢积累一些其它拓展的命令,博客不定时更新 free -m 其中:m表示兆,也可以用g,注意都要小写 Men:表示物理内存统计 total:表示物理内存总数(total=used+free) use...
比特币原理详解
一、什么是比特币 比特币是一种电子货币,是一种基于密码学的货币,在2008年11月1日由中本聪发表比特币白皮书,文中提出了一种去中心化的电子记账系统,我们平时的电子现金是银行来记账,因为银行的背后是国家信用。去中心化电子记账系统是参与者共同记账。比特币可以防止主权危机、信用风险。其好处不多做赘述,这一层面介绍的文章很多,本文主要从更深层的技术原理角度进行介绍。 二、问题引入 假设现有4个人...
程序员接私活怎样防止做完了不给钱?
首先跟大家说明一点,我们做 IT 类的外包开发,是非标品开发,所以很有可能在开发过程中会有这样那样的需求修改,而这种需求修改很容易造成扯皮,进而影响到费用支付,甚至出现做完了项目收不到钱的情况。 那么,怎么保证自己的薪酬安全呢? 我们在开工前,一定要做好一些证据方面的准备(也就是“讨薪”的理论依据),这其中最重要的就是需求文档和验收标准。一定要让需求方提供这两个文档资料作为开发的基础。之后开发...
网页实现一个简单的音乐播放器(大佬别看。(⊙﹏⊙))
今天闲着无事,就想写点东西。然后听了下歌,就打算写个播放器。 于是乎用h5 audio的加上js简单的播放器完工了。 演示地点演示 html代码如下` music 这个年纪 七月的风 音乐 ` 然后就是css`*{ margin: 0; padding: 0; text-decoration: none; list-...
Python十大装B语法
Python 是一种代表简单思想的语言,其语法相对简单,很容易上手。不过,如果就此小视 Python 语法的精妙和深邃,那就大错特错了。本文精心筛选了最能展现 Python 语法之精妙的十个知识点,并附上详细的实例代码。如能在实战中融会贯通、灵活使用,必将使代码更为精炼、高效,同时也会极大提升代码B格,使之看上去更老练,读起来更优雅。
数据库优化 - SQL优化
以实际SQL入手,带你一步一步走上SQL优化之路!
2019年11月中国大陆编程语言排行榜
2019年11月2日,我统计了某招聘网站,获得有效程序员招聘数据9万条。针对招聘信息,提取编程语言关键字,并统计如下: 编程语言比例 rank pl_ percentage 1 java 33.62% 2 cpp 16.42% 3 c_sharp 12.82% 4 javascript 12.31% 5 python 7.93% 6 go 7.25% 7 p...
通俗易懂地给女朋友讲:线程池的内部原理
餐盘在灯光的照耀下格外晶莹洁白,女朋友拿起红酒杯轻轻地抿了一小口,对我说:“经常听你说线程池,到底线程池到底是个什么原理?”
《奇巧淫技》系列-python!!每天早上八点自动发送天气预报邮件到QQ邮箱
将代码部署服务器,每日早上定时获取到天气数据,并发送到邮箱。 也可以说是一个小型人工智障。 知识可以运用在不同地方,不一定非是天气预报。
经典算法(5)杨辉三角
杨辉三角 是经典算法,这篇博客对它的算法思想进行了讲解,并有完整的代码实现。
英特尔不为人知的 B 面
从 PC 时代至今,众人只知在 CPU、GPU、XPU、制程、工艺等战场中,英特尔在与同行硬件芯片制造商们的竞争中杀出重围,且在不断的成长进化中,成为全球知名的半导体公司。殊不知,在「刚硬」的背后,英特尔「柔性」的软件早已经做到了全方位的支持与支撑,并持续发挥独特的生态价值,推动产业合作共赢。 而对于这一不知人知的 B 面,很多人将其称之为英特尔隐形的翅膀,虽低调,但是影响力却不容小觑。 那么,在...
腾讯算法面试题:64匹马8个跑道需要多少轮才能选出最快的四匹?
昨天,有网友私信我,说去阿里面试,彻底的被打击到了。问了为什么网上大量使用ThreadLocal的源码都会加上private static?他被难住了,因为他从来都没有考虑过这个问题。无独有偶,今天笔者又发现有网友吐槽了一道腾讯的面试题,我们一起来看看。 腾讯算法面试题:64匹马8个跑道需要多少轮才能选出最快的四匹? 在互联网职场论坛,一名程序员发帖求助到。二面腾讯,其中一个算法题:64匹...
面试官:你连RESTful都不知道我怎么敢要你?
干货,2019 RESTful最贱实践
刷了几千道算法题,这些我私藏的刷题网站都在这里了!
遥想当年,机缘巧合入了 ACM 的坑,周边巨擘林立,从此过上了"天天被虐似死狗"的生活… 然而我是谁,我可是死狗中的战斗鸡,智力不够那刷题来凑,开始了夜以继日哼哧哼哧刷题的日子,从此"读题与提交齐飞, AC 与 WA 一色 ",我惊喜的发现被题虐既刺激又有快感,那一刻我泪流满面。这么好的事儿作为一个正直的人绝不能自己独享,经过激烈的颅内斗争,我决定把我私藏的十几个 T 的,阿不,十几个刷题网...
为啥国人偏爱Mybatis,而老外喜欢Hibernate/JPA呢?
关于SQL和ORM的争论,永远都不会终止,我也一直在思考这个问题。昨天又跟群里的小伙伴进行了一番讨论,感触还是有一些,于是就有了今天这篇文。 声明:本文不会下关于Mybatis和JPA两个持久层框架哪个更好这样的结论。只是摆事实,讲道理,所以,请各位看官勿喷。 一、事件起因 关于Mybatis和JPA孰优孰劣的问题,争论已经很多年了。一直也没有结论,毕竟每个人的喜好和习惯是大不相同的。我也看...
白话阿里巴巴Java开发手册高级篇
不久前,阿里巴巴发布了《阿里巴巴Java开发手册》,总结了阿里巴巴内部实际项目开发过程中开发人员应该遵守的研发流程规范,这些流程规范在一定程度上能够保证最终的项目交付质量,通过在时间中总结模式,并推广给广大开发人员,来避免研发人员在实践中容易犯的错误,确保最终在大规模协作的项目中达成既定目标。 无独有偶,笔者去年在公司里负责升级和制定研发流程、设计模板、设计标准、代码标准等规范,并在实际工作中进行...
SQL-小白最佳入门sql查询一
不要偷偷的查询我的个人资料,即使你再喜欢我,也不要这样,真的不好;
项目中的if else太多了,该怎么重构?
介绍 最近跟着公司的大佬开发了一款IM系统,类似QQ和微信哈,就是聊天软件。我们有一部分业务逻辑是这样的 if (msgType = "文本") { // dosomething } else if(msgType = "图片") { // doshomething } else if(msgType = "视频") { // doshomething } else { // doshom...
Nginx 原理和架构
Nginx 是一个免费的,开源的,高性能的 HTTP 服务器和反向代理,以及 IMAP / POP3 代理服务器。Nginx 以其高性能,稳定性,丰富的功能,简单的配置和低资源消耗而闻名。 Nginx 的整体架构 Nginx 里有一个 master 进程和多个 worker 进程。master 进程并不处理网络请求,主要负责调度工作进程:加载配置、启动工作进程及非停升级。worker 进程负责处...
【图解经典算法题】如何用一行代码解决约瑟夫环问题
约瑟夫环问题算是很经典的题了,估计大家都听说过,然后我就在一次笔试中遇到了,下面我就用 3 种方法来详细讲解一下这道题,最后一种方法学了之后保证让你可以让你装逼。 问题描述:编号为 1-N 的 N 个士兵围坐在一起形成一个圆圈,从编号为 1 的士兵开始依次报数(1,2,3…这样依次报),数到 m 的 士兵会被杀死出列,之后的士兵再从 1 开始报数。直到最后剩下一士兵,求这个士兵的编号。 1、方...
吐血推荐珍藏的Visual Studio Code插件
作为一名Java工程师,由于工作需要,最近一个月一直在写NodeJS,这种经历可以说是一部辛酸史了。好在有神器Visual Studio Code陪伴,让我的这段经历没有更加困难。眼看这段经历要告一段落了,今天就来给大家分享一下我常用的一些VSC的插件。 VSC的插件安装方法很简单,只需要点击左侧最下方的插件栏选项,然后就可以搜索你想要的插件了。 下面我们进入正题 Material Theme ...
如何防止抄袭PCB电路板
目录 1、抄板是什么 2、抄板是否属于侵权 3、如何防止抄板 1、抄板是什么 抄板也叫克隆或仿制,是对设计出来的PCB板进行反向技术研究;目前全新的定义:从狭义上来说,抄板仅指对电子产品电路板PCB文件的提取还原和利用文件进行电路板克隆的过程;从广义上来说,抄板不仅包括对电路板文件提取、电路板克隆、电路板仿制等技术过程,而且包括对电路板文件进行修改(即改板)、对电子产品外形模具进行三维...
“狗屁不通文章生成器”登顶GitHub热榜,分分钟写出万字形式主义大作
一、垃圾文字生成器介绍 最近在浏览GitHub的时候,发现了这样一个骨骼清奇的雷人项目,而且热度还特别高。 项目中文名:狗屁不通文章生成器 项目英文名:BullshitGenerator 根据作者的介绍,他是偶尔需要一些中文文字用于GUI开发时测试文本渲染,因此开发了这个废话生成器。但由于生成的废话实在是太过富于哲理,所以最近已经被小伙伴们给玩坏了。 他的文风可能是这样的: 你发现,...
程序员:我终于知道post和get的区别
是一个老生常谈的话题,然而随着不断的学习,对于以前的认识有很多误区,所以还是需要不断地总结的,学而时习之,不亦说乎
《程序人生》系列-这个程序员只用了20行代码就拿了冠军
你知道的越多,你不知道的越多 点赞再看,养成习惯GitHub上已经开源https://github.com/JavaFamily,有一线大厂面试点脑图,欢迎Star和完善 前言 这一期不算《吊打面试官》系列的,所有没前言我直接开始。 絮叨 本来应该是没有这期的,看过我上期的小伙伴应该是知道的嘛,双十一比较忙嘛,要值班又要去帮忙拍摄年会的视频素材,还得搞个程序员一天的Vlog,还要写BU...
加快推动区块链技术和产业创新发展,2019可信区块链峰会在京召开
11月8日,由中国信息通信研究院、中国通信标准化协会、中国互联网协会、可信区块链推进计划联合主办,科技行者协办的2019可信区块链峰会将在北京悠唐皇冠假日酒店开幕。   区块链技术被认为是继蒸汽机、电力、互联网之后,下一代颠覆性的核心技术。如果说蒸汽机释放了人类的生产力,电力解决了人类基本的生活需求,互联网彻底改变了信息传递的方式,区块链作为构造信任的技术有重要的价值。   1...
Python 植物大战僵尸代码实现(2):植物卡片选择和种植
这篇文章要介绍的是: - 上方植物卡片栏的实现。 - 点击植物卡片,鼠标切换为植物图片。 - 鼠标移动时,判断当前在哪个方格中,并显示半透明的植物作为提示。
相关热词 c# clr dll c# 如何orm c# 固定大小的字符数组 c#框架设计 c# 删除数据库 c# 中文文字 图片转 c# 成员属性 接口 c#如何将程序封装 16进制负数转换 c# c#练手项目
立即提问