帮忙看一个Socket通信问题,谢谢!

962veiri 2002-11-20 03:57:46
我现在用SOCKET做客户端/服务器的聊天程序。计划允许20个客户端连接,双方都用的是SDI结构,在服务器端的Doc类的OnNewDocument()里面创建的侦听Socket,现在有问题如下:
1、服务程序启动后为什么我点击“新建”快捷按钮他就会弹出Bind错误呢?怎么解决?
BOOL CServerDoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;

//((CEditView*)m_viewList.GetHead())->SetWindowText(NULL);

SOCKADDR_IN addr;
int ret;

m_ListenSocket = socket(AF_INET,SOCK_STREAM,0);
addr.sin_family = AF_INET;
addr.sin_port = htons(nPORT);
addr.sin_addr.S_un.S_addr = INADDR_ANY;

ret = bind(m_ListenSocket,(LPSOCKADDR)&addr,sizeof(addr));
if( ret == SOCKET_ERROR)
{
AfxMessageBox("bind error");
return FALSE;
}
AfxBeginThread(ListenThread,(LPVOID)m_ListenSocket);//线程来处理 侦听
return TRUE;
}

2、服务端要把从客户端接收的消息发给所有客户端,怎么做呀???另外怎么来管理客户的通信Socket?
...全文
22 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
joners 2002-11-22
  • 打赏
  • 举报
回复
上面是服务器端的源代码
joners 2002-11-22
  • 打赏
  • 举报
回复
给你一个聊天室的源代码:)vc6.0下调试通过
/*------------------------*/
#include "stdio.h"
#include "winsock2.h"
#include "stdlib.h"
#include "conio.h"
#include "windows.h"
#pragma comment(lib,"ws2_32.lib")
#define buffsize 1024
#define MAXUSER 20

int user_number=0;
int localport;
int user=0;
int in_for=0;
DWORD dwExitCode;
int flag_user[20];
struct sockaddr_in local_struct;
SOCKET conne[MAXUSER];
HANDLE thread[MAXUSER];
DWORD WINAPI function_thread(LPVOID);
int main(int argc,char **argv[])
{
SOCKET slisten;
int w;
DWORD waitfor;
int search;
int isize;
int dwThreadID;
struct sockaddr_in client;
WSADATA wsd;
if(argc!=2)
{
printf("\n usage server: <localport>");
return 1;
}
localport=atoi(argv[1]);
__try
{
if(WSAStartup(MAKEWORD(1,1),&wsd)!=0)
{
printf("wsastarup error!");
__leave;
}
slisten=socket(AF_INET,SOCK_STREAM,IPPROTO_IP);
if(slisten==INVALID_SOCKET)
{
printf("create listen socker error!");
__leave;
}
local_struct.sin_family=AF_INET;
local_struct.sin_addr.s_addr=htonl(INADDR_ANY);
local_struct.sin_port=htons(localport);
if(bind(slisten,(struct sockaddr*)&local_struct,sizeof(local_struct)))
{
printf("\nbind error!");
__leave;
}
if(listen(slisten,4)==SOCKET_ERROR)
{
printf("\nlisten socker error");
__leave;
}
while(1)
{
printf("\n--------------------等待对方连接--------------------");
for(;1;){
in_for=1;
isize=sizeof(client);
for(search=0;search<MAXUSER&&in_for==1;search++)
if(flag_user[search]!=1){
conne[search]=accept(slisten,(struct sockaddr *)&client,&isize);
if(conne[search]==INVALID_SOCKET){
printf("\n accept error");
break;
}
printf("\n :-) 对方==>%s:%d 连接成功!\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port));
user_number++;
flag_user[search]=1;
thread[search]=CreateThread(NULL,0,function_thread,(LPVOID)&conne[search],0,&dwThreadID);
in_for=0;
if(thread[0]==NULL){
printf("\ncreate thread 1 error");
break;
}
}
}//end for
if((waitfor=WaitForMultipleObjects(user,thread,FALSE,INFINITE))==WAIT_FAILED)
{
printf("\nwaitformultipleobjects error");
break;
}
for(w=0;w<user;w++)
if(waitfor-(WAIT_OBJECT_0+w)==0){
TerminateThread(thread[w],1);
CloseHandle(thread[w]);}
//closesocket(conne[0]);
printf("\n -------------------------------server close--------------");

}



}
__finally
{
if(listen!=INVALID_SOCKET) closesocket(listen);
//if(conne[0]!=INVALID_SOCKET) closesocket(conne[0]);
WSACleanup();
}
return 0;

}

DWORD WINAPI function_thread(SOCKET *s)
{
int check;
fd_set fdread;
int next=0;
int selt;
char *null;
char *a;
int g;
int iRet;
int ret;
//char str_recv[buffsize];
a=(char *)malloc(buffsize*sizeof(char));
null=a;
while(1){
FD_ZERO(&fdread);
FD_SET(*s,&fdread);
if((ret=select(0,&fdread,NULL,NULL,NULL))==SOCKET_ERROR)
{
////////
}
if(ret<=0||(!FD_ISSET(*s,&fdread)))
{
////////
}else{
iRet=recv(*s,null,buffsize,0);

if(iRet==SOCKET_ERROR){
printf("\n用户已离开!");
user_number--;
ExitThread(dwExitCode);
}else if(iRet==0)
break;
Sleep(100);
for(g=0;g<MAXUSER;g++){
if(flag_user[g]==1){
//send(conne[g],&user_number,2,0);
selt=send(conne[g],a,buffsize,0);
if(selt==SOCKET_ERROR)
{
close(conne[g]);
printf("\nsend error.one sock close");
flag_user[g]=0;
}

}
}
}
}//end while
/*printf("\n我要说:");
while((*(null+next)=getchar())!='\n'){
if(*(null+next)==' '){
*(null+next)='`';
}
next+=1;
}
*(null+next)='\0';
selt=send(*s,a,80,0);
if(selt==SOCKET_ERROR)
{
printf("\nsend error");
}
while(1){
next=0;
if(kbhit())
{
printf("\n我要说:");
while((*(null+next)=getchar())!='\n'){
if(*(null+next)==' '){
*(null+next)='`';
}
next+=1;
}
*(null+next)='\0';
selt=send(*s,a,80,0);
if(selt==SOCKET_ERROR)
{
printf("\nsend error");
break;
}
}

Sleep(100);
}*/
return 0;
}
这是我以前学习socket编程的练习,你拿去看看吧
joners 2002-11-22
  • 打赏
  • 举报
回复
把你的客户端贴出来;')
962veiri 2002-11-22
  • 打赏
  • 举报
回复
能否给出服务端发送给所有连接的客户端消息的程序,以及客户点对点的发送。
962veiri 2002-11-22
  • 打赏
  • 举报
回复
哦,看错了。不过看不大明白,没有注释呀……
962veiri 2002-11-22
  • 打赏
  • 举报
回复
客户端的代码我现在没有。在宿舍。我现在在公司。
另外,楼上的,你用的是SDK开发的吧?不用多线程不会死机嘛?你的for(;1;)
循环,不用多线程不死机?另外,能否给一个SDI的程序呀? :)不好意思了,俺是初学
joners 2002-11-21
  • 打赏
  • 举报
回复
或者是你建立一个SCOCKET chat_server[20]的数组,
像这样chat_server[i]=Accept(...);
知道怎么做了吧,以后每一个用户都由一个固定的socket来负责....send(),or,recv()...........
joners 2002-11-21
  • 打赏
  • 举报
回复
第一次出现的错误是,因为你绑定了一个已经使用的端口;)(你肯定多次运行了"新建"菜单)

后来,因为你使用了SO_REUSEADDR选项,绑定已经使用的同一个端口.
后来,ACCEPT()出错,肯定是是你的SO_REUSEADDR 参数设置方面的问题:)
设置SO_REUSEADDR套接字选项来绑定一个已经使用的端口!!但是,SO_LINGER 选项的含义是"当你的SOCKET套接字队列中没有数据发送的时候,将关闭这个套接字"!!
呵呵.问题找到了:)
你的SOCKET被关闭了,怎么能ACCEPT()呢??
至于第二个问题,很好解决,你在服务器端纪录下对方的地址,然后遍历发送不就可以了吗?
还有很多解决办法的....要看你的具体实现了呵呵
Crystal_arrow 2002-11-21
  • 打赏
  • 举报
回复
up
962veiri 2002-11-21
  • 打赏
  • 举报
回复
其中chat_server[]是我在服务端定义的一个SOCKET数组。Buff是char Buff[6];
962veiri 2002-11-21
  • 打赏
  • 举报
回复
我在我的线程函数里这样做为什么不行?遍历所有的SOCKET,法信息,但是结果却是执法送给了一个客户端,而且发三次就出错了。我在自己的机器上开了三个客户程序,但是只有前两个连接的时候可以单独(不是同时,我的意愿就是要同时发送给所有连接了的客户端)收到消息,到第三个就不行(发送错误)了。
while(1)
{
chat_server[i] = accept(pServer,NULL,NULL);
if( chat_server[i] == SOCKET_ERROR)
{
AfxMessageBox("Start DoSocket Failure");
return 0;
}
for( int j=-1; j<i; j++)
{
ret = send(chat_server[j+1],Buff,6,0);
int Error = WSAGetLastError();
if( ret != 6)
{
AfxMessageBox("send error");
return 0;
}
}
i++;
}
962veiri 2002-11-21
  • 打赏
  • 举报
回复
楼上的,你能否具体一点回答呀??? 谢谢了。真的谢谢,具体一点吧,我实在是卡在这里了。
962veiri 2002-11-20
  • 打赏
  • 举报
回复
现在我把下面的代码加到bind前面去,
struct linger e;
e.l_linger = 0;
e.l_onoff = 1;
setsockopt(m_ListenSocket,SOL_SOCKET,SO_REUSEADDR, (char*) &e,sizeof(e));
好像救没错了。但是出了新的错误,就是accept错误了。我的程序是用线程来处理侦听的,线程函数ListenThread如下:
UINT ListenThread(LPVOID lpParam) // the listen socket
{
SOCKET pSocket = (SOCKET)lpParam;
int ret = listen(pSocket,5);
if ( ret<0 )
{
AfxMessageBox("listen 错误");
return 0;
}
while(1)
{
SOCKET s = accept(pSocket,NULL,NULL);
if( s == INVALID_SOCKET )
{
AfxMessageBox("Accept 错误");
return 0;
}
}
点击“新建”快捷按钮时,accept错误。为什么了?另外还有我提出的第二个问题,望高手答复
imquestion 2002-11-20
  • 打赏
  • 举报
回复
bind错误,你看错误代码是什么?
用MessageBox看错误值是多少?

很有可能是所用的端口已经被占用了。
962veiri 2002-11-20
  • 打赏
  • 举报
回复
自己up,

4,356

社区成员

发帖
与我相关
我的任务
社区描述
通信技术相关讨论
社区管理员
  • 网络通信
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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