请教Socket编程高手?

xujian1988616 2011-02-23 02:56:27
我想将原先从串口读取的数据该从网口读取数据!我用的是VC MFC!我晓得用SOCKET编程可以实现!但任务比较紧急,学习来不及的!能否帮忙写个类,我只想弄个类似客户端的东西,从服务器读取数据!
...全文
208 点赞 收藏 20
写回复
20 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
dongxiao1198 2011-02-24
我做过一个聊天室程序,是包括的传输文件和聊天的基于mfc和api的socket传输~给你网址去下吧就在csdn下载区~其中还对消息进行了ase128加密~对你应该有帮助~http://download.csdn.net/source/3031946
回复
Wenxy1 2011-02-24
快学习下,有VC的基础,学socket API,一周内搞定.
回复
xengine-qyt 2011-02-24
有那些不清楚的就说呗。你串口的数据是从哪儿来的?
回复
xujian1988616 2011-02-23
我可没说网上的类我都看不懂!有些变量声明的不清楚而已啊!
回复
快乐鹦鹉 2011-02-23
网上给的类你都看不懂,别人给的你更看不懂了。
8楼的你看懂了吗?
回复
xujian1988616 2011-02-23
主要是现在没头绪,给点类参考下也行啊!网上其它的类变量声明的不清楚,看不大懂!
回复
快乐鹦鹉 2011-02-23
去私活网吧
回复
快乐鹦鹉 2011-02-23
那你是找人编程了,不是问技术问题的......
回复
xujian1988616 2011-02-23
网上的实例当中有的实例的变量的声明的不清楚,看了叶不晓得有什么作用!
回复
xujian1988616 2011-02-23
QQ联系也可以,非常的不解!
回复
xujian1988616 2011-02-23
能帮我写个类吗?以前做的是串口,网口不熟悉!任务有紧急!
回复
celerylxq 2011-02-23
//以下是客户端去连服务器,建立好socket(m_Connect)后从这个socket读数据即可[code=C]/C++[/code]
int CMySocketTCP :: OnConnect(CString strIP,WORD port)
{
closesocket(m_Connect);
m_Connect = socket(AF_INET,SOCK_STREAM,0);
if (INVALID_SOCKET == m_Connect)
{
return 0;
}
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.S_un.S_addr = inet_addr(strIP);
addr.sin_port = htons(port);

//设置为非阻塞方式连接
unsigned long ul = 1;
int err;
int ret = ioctlsocket(m_Connect, FIONBIO, (unsigned long*)&ul);
if(ret == SOCKET_ERROR)
{
err = WSAGetLastError();
closesocket(m_Connect);
m_Connect = NULL;
return FALSE;
}
TIMEVAL timeval;
fd_set r;
FD_ZERO(&r);
FD_SET(m_Connect, &r);
timeval.tv_sec = 1; //秒
timeval.tv_usec =200; //毫秒

//上面的代码是要connect在1.2秒之后返回,不管是否已经连接上,这样就不会阻塞啦
int tmp = connect(m_Connect, (SOCKADDR*)&addr, sizeof(SOCKADDR));//connect为阻塞函数,当连接不成功时会出现假死现象

ret = select(0, 0, &r, 0, &timeval);
if ( ret <= 0 )
{
err = WSAGetLastError();
closesocket(m_Connect);
m_Connect = NULL;
((CMainFrame *)AfxGetApp()->GetMainWnd())->P_TCPPara->GetDlgItem(IDC_STATIC_NETSTATUS)->SetWindowText("正在连接...");
return FALSE;
}
else
{
((CMainFrame*)AfxGetApp() ->GetMainWnd())->m_pDownLoadProc->ShowInfo("建立连接成功!");
::AfxMessageBox("建立连接成功!", MB_USER_MESSAGEBOX,MB_ICONINFORMATION);
((CMainFrame *)AfxGetApp()->GetMainWnd())->P_TCPPara->GetDlgItem(IDC_STATIC_NETSTATUS)->SetWindowText("建立连接成功!");
Sleep(1000);
ConnectSucc = 1;
WSAAsyncSelect(m_Connect,m_hWnd,WM_SOCKET_CLOSE,FD_CLOSE);
return 1;
}
//设回阻塞模式
ul = 0 ;
ret = ioctlsocket(m_Connect, FIONBIO, (unsigned long*)&ul); //返回之后,记得要设置为阻塞模式哟

return 0;
}
BOOL CMySocketTCP::InitSocket()
{//加载套接字库
WSADATA WSAData;
if (WSAStartup(MAKEWORD(2,0),&WSAData) != 0)
{
return FALSE;
}
return TRUE;
}
回复
xujian1988616 2011-02-23
高手可以QQ联系!744031540
回复
fishion 2011-02-23
http://hi.baidu.com/tooker/blog/item/7d9907f32bf94ecb0a46e0af.html
回复
xujian1988616 2011-02-23
任务比较紧急,CSocket类没用过!麻烦指点下
回复
xujian1988616 2011-02-23
/*****************************************************************
** 函数名:DealCommError
** 返 回:
** 错误代码。0:正常;1:本串口不是AVR
** 功能描述:清除本串口对应AVR的数据,并置错误标志
** 修改:
** 版本:v1.0.0
*****************************************************************/
int CSerialComm::DealCommError()
{
int err = 0, i, j;

// 清除对应AVR的数据
memset(&gSttWf, 0, sizeof(gSttWf));
memset(&gAnalog, 0, sizeof(gAnalog));
for (i=0; i<ParaTotalNum; i++)
{
for (j=0; j<4; j++)
{
gPara[i].Para[j] = 0;
}
}
memset(&gSysState, 0, sizeof(gSysState));

gSysState.ComError = TRUE;

return err;
}

/*****************************************************************
** 函数名:LocateAVR
** 返 回:
** 错误代码。0:找到包头;1:未找到包头
** 功能描述:定位AVR通讯协议包头位置
** 修改:
** 版本:v1.0.0
*****************************************************************/
int CSerialComm::LocateAVR()
{
int i, j, err = 1;
uInt8 sumCheck;

for (i=0; i<m_ComInfo.StrLen-AVRPackageLen; i++)
{
if ((170==m_ComInfo.RxStr[i])&&(170==m_ComInfo.RxStr[i+AVRPackageLen])) // 找到包头
{
sumCheck = CalSumCheck(m_ComInfo.RxStr+i, AVRPackageLen - 1);
if (sumCheck == m_ComInfo.RxStr[i+AVRPackageLen-1]) // 校验和正确
{
// 删除无效数据
for (j=i; j<m_ComInfo.StrLen; j++)
{
m_ComInfo.RxStr[j-i] = m_ComInfo.RxStr[j];
}

// 设置标志,并计算数据长度
m_ComInfo.FindHead = TRUE;
m_ComInfo.StrLen = m_ComInfo.StrLen - i;

err = 0;
break;
}
}
}

if (!m_ComInfo.FindHead) //未找到包头,则删除所有数据
{
m_ComInfo.StrLen = 0;
}

return err;
}

/*****************************************************************
** 函数名:AnalyseAVR
** 返 回:
** 错误代码。0:正常;1:数据通道号出错;2:数据校验码出错;3:数据包头出错
** 功能描述:分析AVR通讯协议,将结果存入全局变量中
** 修改:
** 版本:v1.0.0
*****************************************************************/
int CSerialComm::AnalyseAVR()
{
int i, j, k, err=0;
uInt8 sumCheck, chNo;
float temp;

// 若数据太短,则留到下一循环处理
if (m_ComInfo.StrLen < AVRPackageLen*2)
{
err = 1;
return err;
}

// 解释协议,将数据写入各个变量
for (i=0; (i+1)*AVRPackageLen<(m_ComInfo.StrLen+1); i++)
{
if (170 == m_ComInfo.RxStr[i*AVRPackageLen]) // 包头正确
{
sumCheck = CalSumCheck(m_ComInfo.RxStr+i*AVRPackageLen, AVRPackageLen-1);
if (sumCheck == m_ComInfo.RxStr[i*AVRPackageLen+AVRPackageLen-1]) // 校验和正确
{
chNo = m_ComInfo.RxStr[i*AVRPackageLen+1];
// 通道号0x0~0x21
if((chNo>=0)&&(chNo<AnalogNum))
{
// 是模拟状态量
if(chNo < AnalogNum)
{
// 判断是否为负,为负则求补码asd
if(m_ComInfo.RxStr[i*AVRPackageLen+3]<128)
{
temp=(float)(m_ComInfo.RxStr[i*AVRPackageLen+2]+256*m_ComInfo.RxStr[i*AVRPackageLen+3]);
}
else
{
temp=(float)(m_ComInfo.RxStr[i*AVRPackageLen+2]+256*m_ComInfo.RxStr[i*AVRPackageLen+3]-65536);
}

// 除以相应通道的放大倍数
temp=temp/AnalogueGain[chNo];
gAnalog[chNo]=temp;
}

// 写状态波形
for(j=0;j<SttWfNum;j++)
{
if(m_ComInfo.RxStr[i*AVRPackageLen+5+j*2]<128)
{
temp=(float)(m_ComInfo.RxStr[i*AVRPackageLen+4+j*2]+256*m_ComInfo.RxStr[i*AVRPackageLen+5+j*2]);
}
else
{
temp=(float)(m_ComInfo.RxStr[i*AVRPackageLen+4+j*2]+256*m_ComInfo.RxStr[i*AVRPackageLen+5+j*2]-65536);
}
temp=temp/10000;

k=(int)gSttWf[j][SttWfPointNum-1]; // 表头
gSttWf[j][k]=temp;
if(++k==SttWfPointNum-1)
{
k=k-(SttWfPointNum-1);
}
gSttWf[j][SttWfPointNum-1]=(float)k;
}
}
//保存参数到Parameters
else if((chNo>=128)&&(chNo<=140))
{
if(m_ComInfo.RxStr[i*AVRPackageLen+14]==0x80) // RAM中的参数
{
k=2;
gSysState.ParaUpdated = TRUE;
gSysState.ParaUpdateNo = chNo-127; //参数组号,1~10
}
else if(m_ComInfo.RxStr[i*AVRPackageLen+14]==0xC0) // E2PROM中的参数
{
k=1;
gSysState.ParaUpdated = TRUE;
}
else // Flash中参数
{
k=0;
gSysState.ParaUpdated = TRUE;
}

for(j=0; j<6; j++) // 每个包有6个参数
{
if(m_ComInfo.RxStr[i*AVRPackageLen+3+j*2]<128)
{
gPara[(chNo-128)*6+j].Para[k] = m_ComInfo.RxStr[i*AVRPackageLen+2+j*2]+256*m_ComInfo.RxStr[i*AVRPackageLen+3+j*2];
}
else
{
gPara[(chNo-128)*6+j].Para[k] = m_ComInfo.RxStr[i*AVRPackageLen+2+j*2]+256*m_ComInfo.RxStr[i*AVRPackageLen+3+j*2]-65536;
}
//更新当前参数为运行参数
if (2 == k)
{
gPara[(chNo-128)*6+j].Para[3] = gPara[(chNo-128)*6+j].Para[2];
}
}
}
else
{
err = 1; // 数据通道号出错
}
}
else
{
err = 2; // 数据校验和出错
}
}
else
{
err = 3; // 包头出错
}
}

if (0 == err) // 没有错误,将处理过的数据删除
{
m_ComInfo.StrLen = m_ComInfo.StrLen - i*AVRPackageLen;
for (j=0; j<m_ComInfo.StrLen; j++)
{
m_ComInfo.RxStr[j] = m_ComInfo.RxStr[j+i*AVRPackageLen];
}
m_ComInfo.ErrCount = 0;
}
else // 出错,则丢弃当前所有数据
{
m_ComInfo.StrLen = 0;
m_ComInfo.FindHead = FALSE;
}

return err;
}

uInt8 CSerialComm::CalSumCheck(uInt8 *Str, uInt32 Length)
{
uInt8 sumCheck;
uInt32 temp,i;

temp=0;
for(i=0; i<Length; i++)
{
temp = temp+Str[i];
}
sumCheck=temp-(temp/256)*256;

return sumCheck;
}

/*****************************************************************
** 函数名:SendCommand
** 输 入:
** Data1~3:三个字节命令
** 返 回:
** 错误代码。
** 功能描述:
** 向AVR发送控制命令,第一个字节是0xBB,第五个字节是校验码,因此需要传入中间三个字节数据。
** 修改:将SendCommand从CGlobalFunc改到CSerialComm中,删除Des参数,改为由调用者判断串口编号
** 版本:v1.0.1
*****************************************************************/
int CSerialComm::SendCommand(uInt8 Data1, uInt8 Data2, uInt8 Data3)
{
uInt8 sendBuf[5];
DWORD sendLen;
int err = 0;

sendBuf[0] = 0xBB;
sendBuf[1] = Data1;
sendBuf[2] = Data2;
sendBuf[3] = Data3;
sendBuf[4] = CalSumCheck(sendBuf, 4);

WriteFile(m_hCom, sendBuf, 5, &sendLen, NULL);
Sleep(WaitForWriteCom);

return err;
}

/*****************************************************************
** 函数名:GetComHandle
** 返 回:
** 串口句柄
** 功能描述:
** 获取当前串口类对应的串口句柄。目前仅用于AVR通讯
** 修改:
** 版本:v1.0.0
*****************************************************************/
HANDLE CSerialComm::GetComHandle()
{
return m_hCom;
}

/*****************************************************************
** 函数名:GetErrCnt
** 返 回:
** 串口出错次数
** 功能描述:
** 获取当前串口类对应的串口错误次数。目前仅用于AVR通讯
** 修改:
** 版本:v1.0.0
*****************************************************************/
uInt8 CSerialComm::GetErrCnt()
{
return m_ComInfo.ErrCount;
}
回复
xujian1988616 2011-02-23
补充下,原先写的串口类奉上!
#include "stdafx.h"
#include "ECU.h"
#include "ECUDlg.h"
#include "SerialComm.h"
#include "GlobalFunc.h"
#include "memory.h"

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

// 全部变量声明
extern Real32 gSttWf[SttWfNum][SttWfPointNum];
extern Real32 gAnalog[AnalogNum];
extern ParaStruct gPara[ParaGroupNum*13];
extern SysState gSysState;
extern int AnalogueGain[AnalogNum];

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CSerialComm::CSerialComm()
{

}

CSerialComm::~CSerialComm()
{

}

/*****************************************************************
** 函数名:Init
** 输 入:
** ComName:串口资源名
** ComNo:串口编号,1、2为AVR,4为DCS
** 返 回:
** 错误代码。0:初始化成功;其它:GetLastError()返回结果
** 功能描述:串口初始化
** 修改:
** 版本:v1.0.0
*****************************************************************/
int CSerialComm::Init(LPCSTR ComName)
{
int err = 0;

// 初始化串口Info结构体
memset(&m_ComInfo, 0, sizeof(ComInfo));

// 打开串口
m_hCom = CreateFile(ComName,
GENERIC_READ|GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);

// 串口打开错误
if (INVALID_HANDLE_VALUE == m_hCom)
{
err = GetLastError();
}
else
{
// 设置串口
ConfigCom();
}

// 初始化串口数据
memset(&m_ComInfo, 0, sizeof(ComInfo));

return err;
}

/*****************************************************************
** 函数名:ConfigCom
** 返 回:
** 错误代码。0:设置成功;其它:GetLastError()返回结果
** 功能描述:串口设置。设置串口波特率和缓冲区大小
** 修改:
** 版本:v1.0.0
*****************************************************************/
int CSerialComm::ConfigCom()
{
int err = 0;
DCB dcb;

// 获取串口设置,若失败则返回错误代码
if(!GetCommState(m_hCom,&dcb))
{
err = GetLastError();
return err;
}

dcb.BaudRate = CBR_9600; //baudRate=9600
dcb.ByteSize = 8; //8 bit data
dcb.fParity = FALSE; //no parity checkout
dcb.StopBits = ONESTOPBIT; //1 stop bit
dcb.fOutxDsrFlow = FALSE;
dcb.fRtsControl = RTS_CONTROL_DISABLE;
dcb.fOutX = FALSE;
dcb.fInX = FALSE;

// 清除串口缓冲,并中止任何读写操作
PurgeComm(m_hCom, PURGE_TXABORT|PURGE_TXCLEAR|PURGE_RXABORT|PURGE_RXCLEAR);

// 设置串口Buffer
SetupComm(m_hCom, MaxComBuffer, MaxComBuffer);

// 设置串口,若失败则返回错误代码
if (!SetCommState(m_hCom,&dcb))
{
err = GetLastError();
}

return err;
}

/*****************************************************************
** 函数名:Release
** 返 回:
** 错误代码。0:释放成功;1:串口未打开
** 功能描述:串口释放。清除串口缓冲区,释放串口资源
** 修改:
** 版本:v1.0.0
*****************************************************************/
int CSerialComm::Release()
{
int err = 0;

if (INVALID_HANDLE_VALUE != m_hCom)
{
PurgeComm(m_hCom, PURGE_TXABORT|PURGE_TXCLEAR|PURGE_RXABORT|PURGE_RXCLEAR);
CloseHandle(m_hCom);
}
else
{
err = 1;
}

return err;
}

/*****************************************************************
** 函数名:ReadCom
** 返 回:
** 错误代码。0:正常;1:串口无数据;2:串口未打开
** 功能描述:读串口数据,并查找包头,分析协议。若出现错误,则累加错误计数器
** 修改:
** 版本:v1.0.0
*****************************************************************/
int CSerialComm::ReadCom()
{
int err = 0;
COMSTAT ComStat;
DWORD Err, RxLen;

if (INVALID_HANDLE_VALUE != m_hCom)
{
// 清除串口错误,并得到串口状态信息
ClearCommError(m_hCom, &Err, &ComStat);

// 得到串口Buffer中的字符串长度
RxLen = ComStat.cbInQue;

if (0 == RxLen) // 若没有数据,则不处理
{
err = 1;
}
else
{
if (RxLen > 1024) // 如果超过1024则只读1024个字节
{
RxLen = 1024;
TRACE("Data in Com buffer is too many!\n");
}

// 读串口数据到RxStr
ReadFile(m_hCom, &m_ComInfo.RxStr[m_ComInfo.StrLen], RxLen, &RxLen, NULL);
m_ComInfo.StrLen = m_ComInfo.StrLen + RxLen;

// 如果未找到包头,则先查找包头
if (!m_ComInfo.FindHead)
{
err = LocateAVR();
}

// 如果已经找到包头,则进行协议分析
if (m_ComInfo.FindHead)
{
err = AnalyseAVR();
}
}
}
else // 串口打开错误
{
err = 2;
}

if (0 != err) // 若出现错误,则累加错误计数器
{
if (255 != m_ComInfo.ErrCount) // 若错误计数器小于255,则加1
{
m_ComInfo.ErrCount++;
}
}

// 如果错误计数器大于4,则认为通讯故障,同时清除该套数据。
// 之所以选择5作为判断,是为了故障后只执行一次DealCommError()
if (5 == m_ComInfo.ErrCount)
{
DealCommError();
}

return err;
}
回复
快乐鹦鹉 2011-02-23
既然你是用VC MFC,那么你只要用class wizard从CSocket派生一个子类,然后响应OnReceive接收数据就行了。
回复
Eleven 2011-02-23
看看Windows网络编程的例子
回复
相关推荐
发帖
网络编程
创建于2007-09-28

1.8w+

社区成员

VC/MFC 网络编程
申请成为版主
帖子事件
创建了帖子
2011-02-23 02:56
社区公告
暂无公告