VisualEleven和各位高手,遇到一个socket问题,请你们进来给解解呗!

jessie4736 2011-07-19 09:20:58
这个程序主要是完成即时通信的,通信双方IP地址已经有了。在一个Dlg类中添加了一个线程,用来接收数据,由于在初始化OnInitDialog() 中初始化了套接字。再打开一个窗口或者关闭窗口再打开时,就绑定失败。(PS:代码是网上下载的,我调整过几次,也试验过把初始化套接字放到别的地方去,都不好使)。
请问如何调整一下,可以达到同时打开多个窗口,和多个人同时即时通信,或者达到关闭此窗口再打开时,不至于绑定失败,还可以继续通信。
代码如下:
在类的头文件中添加的结构体,用于传送数据的
struct RECVPARAM
{
SOCKET sock;
HWND hwnd;
};
初始化套接字
BOOL CIcqMess::InitSocket()
{
m_socket=socket(AF_INET,SOCK_DGRAM,0);
if(INVALID_SOCKET==m_socket)
{
MessageBox("套接字创建失败!");
return FALSE;
}
SOCKADDR_IN addrSock;
addrSock.sin_family=AF_INET;
addrSock.sin_port=htons(2047);
addrSock.sin_addr.S_un.S_addr=htonl(INADDR_ANY);

int retval;
retval=bind(m_socket,(SOCKADDR*)&addrSock,sizeof(SOCKADDR));
if(SOCKET_ERROR==retval)
{
closesocket(m_socket);
MessageBox("绑定失败!");
return FALSE;
}
return TRUE;
}

在初始化对话框中调用初始化套接字
BOOL CIcqMess::OnInitDialog()
{
CDialog::OnInitDialog();

InitSocket();
RECVPARAM *pRecvParam=new RECVPARAM;
pRecvParam->sock=m_socket;
pRecvParam->hwnd=m_hWnd;
HANDLE hThread=CreateThread(NULL,0,RecvProc,(LPVOID)pRecvParam,0,NULL);
CloseHandle(hThread);

return TRUE;
}

接收数据的线程
DWORD WINAPI CIcqMess::RecvProc(LPVOID lpParameter)
{
SOCKET sock=((RECVPARAM*)lpParameter)->sock;
HWND hwnd=((RECVPARAM*)lpParameter)->hwnd;
delete lpParameter;

SOCKADDR_IN addrFrom;
int len=sizeof(SOCKADDR);

char recvBuf[200];
char tempBuf[300];
int retval;
while(TRUE)
{
retval=recvfrom(sock,recvBuf,200,0,(SOCKADDR*)&addrFrom,&len);
if(SOCKET_ERROR==retval)
break;
sprintf(tempBuf,"%s说: %s",inet_ntoa(addrFrom.sin_addr),recvBuf);
::PostMessage(hwnd,WM_RECVDATA,0,(LPARAM)tempBuf);
}
return 0;
}

处理接收到的数据的 消息响应函数
void CIcqMess::OnRecvData(WPARAM wParam,LPARAM lParam)
{
CString str=(char*)lParam;
CString strTemp;
GetDlgItemText(IDC_EDIT_RECV,strTemp);
str+="\r\n";
str+=strTemp;
SetDlgItemText(IDC_EDIT_RECV,str);
}

发送按钮
void CIcqMess::OnBtnSend()
{
// TODO: Add your control notification handler code here

SOCKADDR_IN addrTo;
addrTo.sin_family=AF_INET;
addrTo.sin_port=htons(2047);
addrTo.sin_addr.S_un.S_addr=inet_addr(m_IP);

CString strSend;
GetDlgItemText(IDC_EDIT_SEND,strSend);
sendto(m_socket,strSend,strSend.GetLength()+1,0,(SOCKADDR*)&addrTo,sizeof(SOCKADDR));
SetDlgItemText(IDC_EDIT_SEND,"");
}


void CIcqMess::OnDestroy()
{
CDialog::OnDestroy();

// TODO: Add your message handler code here
closesocket(m_socket);
WSACleanup();
}

同时感谢提供此代码的高手!!!
...全文
130 点赞 收藏 18
写回复
18 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
Eleven 2011-07-20
[Quote=引用 17 楼 hmm7e 的回复:]

引用 16 楼 jessie4736 的回复:

沉的太快了,自己顶顶


到已经解决或推荐里面去找,源码N多。
[/Quote]
呵呵~
回复
「已注销」 2011-07-20
[Quote=引用 16 楼 jessie4736 的回复:]

沉的太快了,自己顶顶
[/Quote]

到已经解决或推荐里面去找,源码N多。
回复
jessie4736 2011-07-20
沉的太快了,自己顶顶
回复
jessie4736 2011-07-19
[Quote=引用 13 楼 smwhotjay 的回复:]
LZ是recvfrom 这udp通讯嘛.

查看孙鑫的mfc socket那节录象。 照着打。 我编译通过了。运行也可以聊
[/Quote]
就是他的那段程序,是可以聊天,但是,只能打开一个窗口~
我把这段程序,放到自己程序中,用非模态对话框打开,关闭后,再打开,就绑定失败了~
回复
smwhotjay 2011-07-19
LZ是recvfrom 这udp通讯嘛.

查看孙鑫的mfc socket那节录象。 照着打。 我编译通过了。运行也可以聊
回复
Eleven 2011-07-19
[Quote=引用 11 楼 jessie4736 的回复:]
引用 9 楼 visualeleven 的回复:
引用 7 楼 jessie4736 的回复:
引用 5 楼 visualeleven 的回复:
SOCKADDR_IN addrSock;
addrSock.sin_family=AF_INET;
addrSock.sin_port=htons(2047);
addrSock.sin_addr.S_un.S_addr=htonl(INA……
[/Quote]
不能通讯,Debug下看看哪个函数调用失败?sendto,recvfrom?
回复
jessie4736 2011-07-19
[Quote=引用 9 楼 visualeleven 的回复:]
引用 7 楼 jessie4736 的回复:
引用 5 楼 visualeleven 的回复:
SOCKADDR_IN addrSock;
addrSock.sin_family=AF_INET;
addrSock.sin_port=htons(2047);
addrSock.sin_addr.S_un.S_addr=htonl(INADDR_ANY);

int retval;
……
[/Quote]
而且和127.0.0.1也不能通讯了~
回复
jessie4736 2011-07-19
[Quote=引用 9 楼 visualeleven 的回复:]
引用 7 楼 jessie4736 的回复:
引用 5 楼 visualeleven 的回复:
SOCKADDR_IN addrSock;
addrSock.sin_family=AF_INET;
addrSock.sin_port=htons(2047);
addrSock.sin_addr.S_un.S_addr=htonl(INADDR_ANY);

int retval;
……
[/Quote]
这个这个。。。
我什么都没改啊,就改了个0~
WSAGetLastError()是什么啊,如何用啊~~
回复
Eleven 2011-07-19
[Quote=引用 7 楼 jessie4736 的回复:]
引用 5 楼 visualeleven 的回复:
SOCKADDR_IN addrSock;
addrSock.sin_family=AF_INET;
addrSock.sin_port=htons(2047);
addrSock.sin_addr.S_un.S_addr=htonl(INADDR_ANY);

int retval;
retval=bind(m_socket,(SO……
[/Quote]
无法通讯,调试一下,看看是哪里调用的问题,WSAGetLastError()?
回复
jessie4736 2011-07-19
[Quote=引用 4 楼 shenyi0106 的回复:]
socket初始化放到app类的InitInstance中初始化,重复帮顶一个端口肯定会失败的
[/Quote]
还是绑定失败~~
回复
jessie4736 2011-07-19
[Quote=引用 5 楼 visualeleven 的回复:]
SOCKADDR_IN addrSock;
addrSock.sin_family=AF_INET;
addrSock.sin_port=htons(2047);
addrSock.sin_addr.S_un.S_addr=htonl(INADDR_ANY);

int retval;
retval=bind(m_socket,(SOCKADDR*)&addrSock,size……
[/Quote]
绑定到0后,的确不提示“绑定失败了”,但是,无法通讯了!
回复
jessie4736 2011-07-19
[Quote=引用 5 楼 visualeleven 的回复:]
SOCKADDR_IN addrSock;
addrSock.sin_family=AF_INET;
addrSock.sin_port=htons(2047);
addrSock.sin_addr.S_un.S_addr=htonl(INADDR_ANY);

int retval;
retval=bind(m_socket,(SOCKADDR*)&addrSock,size……
[/Quote]
大哥你终于来了~眼泪哗哗的~
我自己用的端口不得1024以上的么?
我就想,在打开一个窗口,同时和N个人即时通讯!
可不可以调整一下把绑定的放到别的地方,绑定一次,然后,和N个IP地址进行通讯~
回复
Eleven 2011-07-19
SOCKADDR_IN addrSock;
addrSock.sin_family=AF_INET;
addrSock.sin_port=htons(2047);
addrSock.sin_addr.S_un.S_addr=htonl(INADDR_ANY);

int retval;
retval=bind(m_socket,(SOCKADDR*)&addrSock,sizeof(SOCKADDR));
----------------
你说的是这里的bind失败?
你多次调用这个,bind同一个端口(2047)上,肯定会失败的吧
这里
addrSock.sin_port = htons(0);这样试试~
回复
shenyi0106 2011-07-19
socket初始化放到app类的InitInstance中初始化,重复帮顶一个端口肯定会失败的
回复
jessie4736 2011-07-19
[Quote=引用 2 楼 shenyi0106 的回复:]
其他的没看出来问题,倒是一下这段代码有点问题:
C/C++ code

char recvBuf[200];
char tempBuf[300];
int retval;
while(TRUE)
{
retval=recvfrom(sock,recvBuf,200,0,(SOCKADDR*)&addrFrom,&len);
if(SOCKET_ERROR==ret……
[/Quote]
我第一用PoseMessage,还是用的别人的代码,刚学MFC~那怎么改呢?
回复
shenyi0106 2011-07-19
其他的没看出来问题,倒是一下这段代码有点问题:

char recvBuf[200];
char tempBuf[300];
int retval;
while(TRUE)
{
retval=recvfrom(sock,recvBuf,200,0,(SOCKADDR*)&addrFrom,&len);
if(SOCKET_ERROR==retval)
break;
sprintf(tempBuf,"%s说: %s",inet_ntoa(addrFrom.sin_addr),recvBuf);
::PostMessage(hwnd,WM_RECVDATA,0,(LPARAM)tempBuf);

请看看PostMessage的工作方式,你会知道哪里有问题的
回复
buyong 2011-07-19
你再线程中初始化套接字行不行?
回复
jessie4736 2011-07-19
[Quote=引用 12 楼 visualeleven 的回复:]
引用 11 楼 jessie4736 的回复:
引用 9 楼 visualeleven 的回复:
引用 7 楼 jessie4736 的回复:
引用 5 楼 visualeleven 的回复:
SOCKADDR_IN addrSock;
addrSock.sin_family=AF_INET;
addrSock.sin_port=htons(2047);
addrSock.sin_a……
[/Quote]
要不你看看,我在一个类中bind UDP的socket 6000端口,然后,把m_socket传到令一类中应用通讯
行不行~
m_socket都是Public类型的,类之间的数据传递你已经教过我了~~~

行么?
回复
发帖
网络编程
创建于2007-09-28

1.8w+

社区成员

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