关于linux下socket编程的问题,高手入。

jihen 2010-10-15 01:02:51
最近在写一个迷你QQ程序,通过epoll和socket配合实现,
问题挺奇怪的,
一开始我发送的 注册或者登陆数据包都没有任何错误,服务器,客户端实现了良好通信,
接着登陆之后,客户端向服务器发送了一个 聊天信息 用 sendMsg 封装处理,然后发送,
服务器端用 packetDeal 先识别包的类型,然后进行特定处理。
但是,错误出现在,客户端发送数据包后,服务器接受的数据包类型成了登陆时输入的ID
感觉非常神奇,望高手解答。谢谢
客户端发送的程序段:

int sendMsg() //鍙戦€佹秷鎭暟鎹墦鍖?
{
CHAT chatData;
PREQ reqData;
char cId[11],msg[141];
int sendState;

memset(&chatData, 0, sizeof(CHAT));
scanf("%s",cId);
chatData.dstID = atoi(cId);
chatData.srcID = clientInfo.ID;
strcpy(chatData.srcNickname, clientInfo.nickname);
scanf("%s",msg);
strcpy(chatData.msg, msg);
chatData.sendTime = time(NULL);

reqData = (PREQ)calloc( sizeof(int)+
sizeof(enum REQTYPE)+sizeof(CHAT), 1);

reqData->length = sizeof(CHAT);
reqData->reqType = chat;
memcpy(reqData->buf, &chatData, sizeof(CHAT));

sendState = write(clientInfo.socket, &reqData, sizeof(int)+
sizeof(enum REQTYPE)+sizeof(CHAT));

//vestigeInfo
DEBUG("length:%d,reqType:%d,msg:%s\n",
(int)(*((int *)reqData)),
(enum REQTYPE)(*((int *)reqData+1)),
((CHAT *)reqData->buf)->msg);
if(sendState == -1)
{
perror("sendMsg:send");
}
else{
DEBUG("sendMsg:send success\n");
}

free(reqData);
}


服务器接受的程序端

int packetDeal(int sockfd)
{
REQ reqData;
PCLIENT pclientNode = clientList;
PCLIENT qclientNode = clientList;

memset(&reqData, 0, sizeof(REQ));

int ret = recv(sockfd, &reqData, sizeof(REQ), MSG_PEEK);

if(ret < 0)
{
epoll_ctl(epfd, EPOLL_CTL_DEL, sockfd, NULL);
//vestigeInfo
perror("recv:");
}
if(ret == 0)
{
//1:閾捐〃鍒犻櫎璇ョ敤鎴凤紝2:鍚屾椂epoll鍒犻櫎璇ョ洃鍚?3:鍏抽棴濂楁帴瀛?
//vestigeInfo
DEBUG("绔彛宸茬粡鍏抽棴\n");
epoll_ctl(epfd, EPOLL_CTL_DEL, sockfd, NULL);
clientNum--;

pthread_mutex_lock(&clLock);
while(qclientNode->next != NULL)
{
pclientNode = qclientNode;
qclientNode = qclientNode->next;
if(qclientNode->socket == sockfd)
{
pclientNode->next = qclientNode->next;
free(qclientNode);
break;
}
}
pthread_mutex_unlock(&clLock);
close(sockfd);

return 0;
}
//vestigeInfo
DEBUG("packetDeal %d, sockfd:%d\n",reqData.reqType, sockfd);

switch(reqData.reqType)
{
case regist:
//vestigeInfo
DEBUG("REGIST\n");
regist_func(sockfd);
break;
case login:
//vestigeInfo
DEBUG("LOGIN\n");
login_func(sockfd);
break;
case chat:
//vestigeInfo
DEBUG("CHAT\n");
chat_func(sockfd);
break;
case sendFile:
//vestigeInfo
DEBUG("SENDFILE\n");
sendFile_func(sockfd);
break;
case set:
//vestigeInfo
DEBUG("SET\n");
set_func(sockfd);
break;
}
}


...全文
124 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
jihen 2010-10-16
  • 打赏
  • 举报
回复
郁闷死,被我找到原因了。在发送数据的时候,sendMsg包里面

sendState = write(clientInfo.socket, &reqData, sizeof(int)+
sizeof(enum REQTYPE)+sizeof(CHAT));

这里 reqdata不需要加取地址符号。
去掉之后就对了。真郁闷
jihen 2010-10-15
  • 打赏
  • 举报
回复
msg_peek 是为了事先查看数据的类型用的,在各个函数里,已经对每个数据包都读取了各自的信息。发送什么类型,读取完什么类型的包。
oyster2008 2010-10-15
  • 打赏
  • 举报
回复
不会,一般神奇的问题都是应用程序本身造成的
你用MSG_PEEK标志来接收数据,是不是前面的处理,比如登录过程,将数据从TCP的缓冲区复制出来之后数据留在缓冲区,而下一次你读到的实际上是上一次的数据呢
[Quote=引用 4 楼 jihen 的回复:]

不知道有没有什么情况是会出现 发出去接受到不一样的呢?
[/Quote]
jihen 2010-10-15
  • 打赏
  • 举报
回复
不知道有没有什么情况是会出现 发出去接受到不一样的呢?
jihen 2010-10-15
  • 打赏
  • 举报
回复
justkk,你说的问题应该不存在,结构体的最大元素我用的也是int型,所以对齐的时候用的也是 4 + 4 + 4的整数倍196 = 204呢。。不过谢啦,我去试试看。
justkk 2010-10-15
  • 打赏
  • 举报
回复
怀疑与这句话有关
reqData = (PREQ)calloc( sizeof(int)+ sizeof(enum REQTYPE)+sizeof(CHAT), 1);
由于内存对其的原因,整个结构体的大小不一定是每个成员大小之和

分配内存的大小直接用sizeof(结构体),试试看
「已注销」 2010-10-15
  • 打赏
  • 举报
回复
看代码头疼 不会是感冒的原因吧。

23,125

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧