UDP聊天小程序的问题?

werflychen 2011-03-28 11:18:06
功能描述:实现在局域网内聊天功能。
问题:分别在局域网内两台电脑打开该应用程序。输入另一方的ip地址进行聊天。
若A先发送信息给B,B可以正常接收并显示,但此时B发送信息给A的时候,发送成功,A却无法接收。
不知道如何查找原因,请各位大侠指点,谢谢!!
//////////////////////////////////////////////////////////////////////////////
#include "iostream"
#include <winsock2.h>
#include <Windows.h>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
#define Const_BufLength 1024
#define Const_Port 12345

BOOL InitServerSocket(void);
BOOL InitClientSocket(void);
WSADATA wsaData;
SOCKET m_socket;
SOCKET m_client_socket;
sockaddr_in SerAdd,CliAdd;

int iLength=sizeof(CliAdd);
int retval;
char strSendMsg[Const_BufLength];
char strRecvMsg[Const_BufLength];

void ReceiveData();
void SendData();


int main()
{
if(!InitServerSocket())
{
cout<<"服务套接字初始化出错,即将退出"<<endl;
WSACleanup();
system("pause");
return -1;
}

if(!InitClientSocket())
{
cout<<"客户套接字初始化出错,即将退出"<<endl;
WSACleanup();
system("pause");
return -1;
}
char ip[20];
cout << "input ip" << endl;
cin >> ip;
CliAdd.sin_addr.s_addr = inet_addr(ip);

HANDLE handle1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ReceiveData, NULL, 0, NULL);

while(1)
{
memset(strSendMsg,0,sizeof(strSendMsg));
cout<<"回复:"<<endl;
cin >> strSendMsg;
if(strcmp(strSendMsg,"exit")==0)
{
strcpy(strSendMsg,"收到客户下线的消息,我是服务器,我也下线了");
retval=sendto(m_socket,strSendMsg,sizeof(strSendMsg),0,(SOCKADDR*)&CliAdd,sizeof(CliAdd));
closesocket(m_socket);
WSACleanup();
return 0;
}

CliAdd.sin_family = AF_INET;
retval=sendto(m_client_socket,strSendMsg,sizeof(strSendMsg),0,(SOCKADDR*)&CliAdd,sizeof(CliAdd));
if(retval==SOCKET_ERROR)
{
cout<<"发送失败,错误ID为:"<<WSAGetLastError()<<endl;
break;
}
else if(retval==0)
{
break;
}
else
{
cout<<"发送成功!"<<endl;
}
}
CloseHandle(handle1);
closesocket(m_socket);
WSACleanup();
return 0;
}

void ReceiveData()
{
while(1)
{
memset(strRecvMsg,0,sizeof(strRecvMsg));
retval=recvfrom(m_socket,strRecvMsg,Const_BufLength,0,(SOCKADDR*)&CliAdd,&iLength);
if(retval==SOCKET_ERROR)
{
cout<<"接受失败,错误ID为:"<<WSAGetLastError()<<endl;
break;
}
else if(retval==0)
{
break;
}
else
{
cout<<"IP:Port\t"<<inet_ntoa(CliAdd.sin_addr)<<":"<<ntohs(CliAdd.sin_port)<<'\t'<<strRecvMsg<<endl;
}
}
}


BOOL InitServerSocket(void)
{
if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0)
{
cout<<"加载winsock失败,错误ID为:"<<WSAGetLastError()<<endl;
exit(0);
}
m_socket=socket(AF_INET,SOCK_DGRAM,0);

SerAdd.sin_family=AF_INET;
SerAdd.sin_port=htons(Const_Port);
SerAdd.sin_addr.S_un.S_addr=htonl(INADDR_ANY);

int retval;
retval=bind(m_socket,(SOCKADDR*)&SerAdd,sizeof(SOCKADDR));
if(SOCKET_ERROR==retval)
{
closesocket(m_socket);
cout<<"端口绑定失败! 错误ID为:"<<WSAGetLastError()<<endl;
return FALSE;
}
return TRUE;
}

BOOL InitClientSocket(void)
{
if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0)
{
cout<<"加载winsock失败,错误ID为:"<<WSAGetLastError()<<endl;
exit(0);
}
m_client_socket=socket(AF_INET,SOCK_DGRAM,0);
if(INVALID_SOCKET==m_client_socket)
{
cout<<"套接字创建失败!错误ID为:"<<WSAGetLastError()<<endl;
return FALSE;
}
CliAdd.sin_addr.s_addr = inet_addr("127.0.0.1");
CliAdd.sin_port = htons(Const_Port);
return TRUE;
}
...全文
154 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
singwhatiwanna 2011-03-30
  • 打赏
  • 举报
回复
收消息需要绑定到固定端口,然后另一方直接往你的端口发消息即可。

另,你采用的是udp协议,本来就无客户端和服务器之分,想实现二者之间的正常通信,一个socket即可,绑定到12345端口,给不同的人发消息 就有不同的sockaddr_in。
werflychen 2011-03-30
  • 打赏
  • 举报
回复
错在把发送的地址作为recvfrom的返回值的,这样会改写发送的地址,关键是改写了发送的端口,因为udp发送时的端口是随机的。
retval=recvfrom(m_socket,strRecvMsg,Const_BufLength,0,(SOCKADDR*)&CliAdd,&iLength);
这里不能用CliAdd作为返回值。

正确可运行代码如下:
#include "iostream"
#include <winsock2.h>
#include <Windows.h>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
#define Const_BufLength 1024
#define Const_Port 12345

BOOL InitServerSocket(void);
BOOL InitClientSocket(void);
WSADATA wsaData;
SOCKET m_socket;
SOCKET m_client_socket;
sockaddr_in SerAdd,CliAdd;

int iLength=sizeof(CliAdd);
int retval;
char strSendMsg[Const_BufLength];
char strRecvMsg[Const_BufLength];

void ReceiveData();
void SendData();


int main()
{
if(!InitServerSocket())
{
cout<<"服务套接字初始化出错,即将退出"<<endl;
WSACleanup();
system("pause");
return -1;
}

if(!InitClientSocket())
{
cout<<"客户套接字初始化出错,即将退出"<<endl;
WSACleanup();
system("pause");
return -1;
}
char ip[20];
cout << "input ip" << endl;
cin >> ip;
CliAdd.sin_addr.s_addr = inet_addr(ip);

HANDLE handle1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ReceiveData, NULL, 0, NULL);

while(1)
{
memset(strSendMsg,0,sizeof(strSendMsg));
cout<<"回复:"<<endl;
cin >> strSendMsg;
if(strcmp(strSendMsg,"exit")==0)
{
strcpy(strSendMsg,"收到客户下线的消息,我是服务器,我也下线了");
retval=sendto(m_socket,strSendMsg,sizeof(strSendMsg),0,(SOCKADDR*)&CliAdd,sizeof(CliAdd));
closesocket(m_socket);
WSACleanup();
return 0;
}

CliAdd.sin_family = AF_INET;
retval=sendto(m_client_socket,strSendMsg,sizeof(strSendMsg),0,(SOCKADDR*)&CliAdd,sizeof(CliAdd));
if(retval==SOCKET_ERROR)
{
cout<<"发送失败,错误ID为:"<<WSAGetLastError()<<endl;
break;
}
else if(retval==0)
{
break;
}
else
{
cout<<"发送成功!"<<endl;
}
}
CloseHandle(handle1);
closesocket(m_socket);
WSACleanup();
return 0;
}

void ReceiveData()
{
sockaddr_in socktmp;
while(1)
{
memset(strRecvMsg,0,sizeof(strRecvMsg));
retval=recvfrom(m_socket,strRecvMsg,Const_BufLength,0,(SOCKADDR*)&socktmp,&iLength);
if(retval==SOCKET_ERROR)
{
cout<<"接受失败,错误ID为:"<<WSAGetLastError()<<endl;
break;
}
else if(retval==0)
{
break;
}
else
{
cout<<"IP:Port\t"<<inet_ntoa(CliAdd.sin_addr)<<":"<<ntohs(CliAdd.sin_port)<<'\t'<<strRecvMsg<<endl;
}
}
}


BOOL InitServerSocket(void)
{
if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0)
{
cout<<"加载winsock失败,错误ID为:"<<WSAGetLastError()<<endl;
exit(0);
}
m_socket=socket(AF_INET,SOCK_DGRAM,0);

SerAdd.sin_family=AF_INET;
SerAdd.sin_port=htons(Const_Port);
SerAdd.sin_addr.S_un.S_addr=htonl(INADDR_ANY);

int retval;
retval=bind(m_socket,(SOCKADDR*)&SerAdd,sizeof(SOCKADDR));
if(SOCKET_ERROR==retval)
{
closesocket(m_socket);
cout<<"端口绑定失败! 错误ID为:"<<WSAGetLastError()<<endl;
return FALSE;
}
return TRUE;
}

BOOL InitClientSocket(void)
{
if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0)
{
cout<<"加载winsock失败,错误ID为:"<<WSAGetLastError()<<endl;
exit(0);
}
m_client_socket=socket(AF_INET,SOCK_DGRAM,0);
if(INVALID_SOCKET==m_client_socket)
{
cout<<"套接字创建失败!错误ID为:"<<WSAGetLastError()<<endl;
return FALSE;
}
CliAdd.sin_addr.s_addr = inet_addr("127.0.0.1");
CliAdd.sin_port = htons(12345);
return TRUE;
}
jinjunmax_78 2011-03-30
  • 打赏
  • 举报
回复
我建议你在 sendto之前加上一句 CliAdd.sin_port = htons(Const_Port); 试试
MervynChina 2011-03-30
  • 打赏
  • 举报
回复
你还是做个小服务器,转发这些数据吧。服务器作出结构就好了 容易做的
werflychen 2011-03-30
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 singwhatiwanna 的回复:]

收消息需要绑定到固定端口,然后另一方直接往你的端口发消息即可。

另,你采用的是udp协议,本来就无客户端和服务器之分,想实现二者之间的正常通信,一个socket即可,绑定到12345端口,给不同的人发消息 就有不同的sockaddr_in。
[/Quote]

恩,是的,我也正是这样实现的。。。
werflychen 2011-03-30
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 mervynchina 的回复:]

你还是做个小服务器,转发这些数据吧。服务器作出结构就好了 容易做的
[/Quote]
我想做个在局域网内的聊天工作,觉得没必要做成CS的,呵呵。。做成P2P的就很方便。。。
werflychen 2011-03-30
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 jinjunmax_78 的回复:]

我建议你在 sendto之前加上一句 CliAdd.sin_port = htons(Const_Port); 试试
[/Quote]
恩,是的,就错在这里。因为把CliAdd作为返回值了,改变了它的端口,下次发送的时候的端口变了,这样改的话可以正确运行。。。
jues 2011-03-30
  • 打赏
  • 举报
回复
收藏一下
samhuang123456789 2011-03-30
  • 打赏
  • 举报
回复
ReceiveData里把客户端的IP拿来做参数,改变了它的ip了
werflychen 2011-03-29
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 visualeleven 的回复:]

你把服务端和客户端都写在一起?
[/Quote]
恩,是的,我想把两个都写在一起。。。。。
Eleven 2011-03-29
  • 打赏
  • 举报
回复
你把服务端和客户端都写在一起?

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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