服务器发送消息给客服端的问题

qscool1987 2012-04-19 03:06:22
问题描述:服务器一个,客服端两个,现在服务器给客服端发消息,却只有一个客服端收到,然后再发又只有一个收到,不过这个时候是另一个客服端收到,依次轮流收到服务器的信息,感觉有些奇怪,有些问题是想不明白

//服务器端代码:
#include "stdafx.h"
#include <windows.h>
#include <process.h>
#include <iostream>
#include <string>
using namespace std;
#pragma comment(lib,"ws2_32.lib")

/*recive message thread*/
DWORD WINAPI ClientThread(LPVOID lp)
{
SOCKET sock = (SOCKET)lp;//----------
char szbuff[1024];
int ret;
while(1)
{
//perform a blocking recv() call
ret = recv(sock,szbuff,1024,0);
if(ret == 0)
break;
else if(ret == SOCKET_ERROR)
{
cout << "recv() failed " << WSAGetLastError() << endl;
break;
}
szbuff[ret] = '\0';
cout << "RECV:" << szbuff << " " << ret << "bytes" << endl;
}
return 0;
}

/*send message thread*/
DWORD WINAPI SendThread(LPVOID lp)
{
SOCKET sock = (SOCKET)lp;
char buff[1024];
string msg;
int ret;
while(1)
{
cin >> msg;
char buff[1024];
strcpy(buff,msg.c_str());
ret = send(sock,buff,msg.length() + 1,0);
if(ret == 0)
break;
else if(ret == SOCKET_ERROR)
{
cout << "send failed " << WSAGetLastError() << endl;
break;
}
}
return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
//cout << *(int*)lp << endl;
//Initialize Winsock
WSADATA wsd;
if(WSAStartup(MAKEWORD(2,2),&wsd) != 0)
{
cout << "Failled to load Winsock!" << endl;
return 1;
}
//create our listening socket
SOCKET sListen,sClient;
sListen = socket(AF_INET,SOCK_STREAM,IPPROTO_IP);
if(sListen == SOCKET_ERROR)
{
cout << "socket() failed " << WSAGetLastError() << endl;
return 1;
}
//Select local interface and bind to it
struct sockaddr_in local,client;
int iport = 5000;
local.sin_addr.s_addr = htonl(INADDR_ANY);
local.sin_port = htons(iport);
local.sin_family = AF_INET;
if(bind(sListen,(SOCKADDR*)&local,sizeof(local)) == SOCKET_ERROR)
{
cout << "bind() failed " << WSAGetLastError() << endl;
return 1;
}
listen(sListen,8);
cout << "server side is in listening status!" << endl;
//Waitfor incoming clients,Once one is detected,create thread and pass
//the handle off to it
int iAddrSize(0);
HANDLE hThread;
DWORD dwThreadId,dwSendThreadId;
while(1)
{
iAddrSize = sizeof(client);
sClient = accept(sListen,(SOCKADDR*)&client,&iAddrSize);
if(sClient == INVALID_SOCKET)
{
cout << "accept() failed " << WSAGetLastError() << endl;
break;
}
cout << "Accept client:" << inet_ntoa(client.sin_addr) << endl;
cout << ntohs(client.sin_port) << endl;

hThread = CreateThread(NULL,0,ClientThread,
(LPVOID)sClient,0,&dwThreadId);
HANDLE hSendThread = CreateThread(NULL,0,SendThread,
(LPVOID)sClient,0,&dwSendThreadId);
if(hThread == NULL)
{
cout << "CreateThread() failed " << GetLastError() << endl;
break;
}
CloseHandle(hThread);
CloseHandle(hSendThread);
}
closesocket(sListen);
WSACleanup();
return 0;
}


//客服端代码:
#include "stdafx.h"
#include <windows.h>
#include <process.h>
#include <iostream>
#include <string>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
#pragma comment(lib,"ws2_32.lib")

/*recive message thread*/
DWORD WINAPI ClientThread(LPVOID lp)
{
SOCKET sock = (SOCKET)lp;
char szbuff[1024];
int ret;
while(1)
{
ret = recv(sock,szbuff,1024,0);
if(ret == 0)
break;
else if(ret == SOCKET_ERROR)
{
cout << "recv() failed " << WSAGetLastError() << endl;
break;
}
szbuff[ret] = '\0';
cout << "recv " << szbuff << " " << ret << "bytes" << endl;
}
return 0;
}
/*send message thread*/
DWORD WINAPI SendThread(LPVOID lp)
{
SOCKET sock = (SOCKET)lp;
string msg;
char buff[1024];
int ret;
while(1)
{
cin >> msg;
strcpy(buff,msg.c_str());
ret = send(sock,buff,msg.length() + 1,0);
if(ret == 0)
break;
else if(ret == SOCKET_ERROR)
{
cout << "send failed " << WSAGetLastError() << endl;
break;
}
}
return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
WSADATA wsd;
SOCKET sClient;
struct sockaddr_in server;
struct hostent *host = NULL;
//load Winsock
if(WSAStartup(MAKEWORD(2,2),&wsd) != 0)
{
cout << "Failled to load Winsock!" << endl;
return 1;
}
//create socket and attempt to connect to the server
sClient = socket(AF_INET,SOCK_STREAM,IPPROTO_IP);
if(sClient == INVALID_SOCKET)
{
cout << "socket failed " << WSAGetLastError() << endl;
return 1;
}
string szServer;
u_long iport;
cout << "please input IP address: " << endl;
cin >> szServer;
cout << "please input port number: " << endl;
cin >> iport;
server.sin_addr.s_addr = inet_addr(INADDR_ANY);
server.sin_family = AF_INET;
server.sin_port = htons(iport);
//if the supplied server address isn't in the form
//"aaa.bbb.ccc.ddd" it's a host name,so try to resolve it
if(server.sin_addr.s_addr == INADDR_NONE)
{
host = gethostbyname(szServer.c_str());
if(host == NULL)
{
cout << "unable to resolve server: " << szServer << endl;
return 1;
}
CopyMemory(&server.sin_addr,host->h_addr_list[0],host->h_length);
}

if(connect(sClient,(SOCKADDR*)&server,sizeof(server))==SOCKET_ERROR)
{
cout << "connect failed " << WSAGetLastError() << endl;
return 1;
}
cout << "connect succeed!" << endl;
DWORD dwThreadId,dwSendThreadId;
HANDLE hThread = CreateThread(NULL,0,ClientThread,
(LPVOID)sClient,0,&dwThreadId);
HANDLE hSendThread = CreateThread(NULL,0,SendThread,
(LPVOID)sClient,0,&dwSendThreadId);
if(hThread == NULL)
{
cout << "CreateThread() failed " << GetLastError() << endl;
}
if(hSendThread == NULL)
{
cout << "CreateThread() failed " << GetLastError() << endl;
}
CloseHandle(hThread);
CloseHandle(hSendThread);

//prevent main thread exit;
while(1)
{

}
closesocket(sClient);
WSACleanup();
return 0;
}

我开两个客服端,然后和服务器端连接,然后服务器发消息,就出现这种情况。。。我以为是创建线程调用同一个函数的问题,但是我写测试代码不会出现这种情况。。。
...全文
229 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
qscool1987 2012-04-20
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 的回复:]
一个send线程,一个socket数组,不行么? 循环发送。
[/Quote]
可以,已经实现了
qscool1987 2012-04-20
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 的回复:]
服务器端先不发送,接收到客户端的直接返回客户端,你看看还有问题吗?
[/Quote]
你这样的设计肯定是不行的,只要连接成功,服务器就应该可以给客服端发消息而不是说等客服端发消息来它才响应
huangwenshen 2012-04-20
  • 打赏
  • 举报
回复
一个send线程,一个socket数组,不行么? 循环发送。
lijianli9 2012-04-20
  • 打赏
  • 举报
回复
服务器端先不发送,接收到客户端的直接返回客户端,你看看还有问题吗?
qscool1987 2012-04-19
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 的回复:]
设置一个static内部静态变量, 发送过一次后设置为false 以后就不用再发送了·

我对LZ的代码有个问题··


为什么你的服务器用的地址是INDADDR_ANY呢

每次启动服务器 地址不知道··客户端怎么连接呢?
[/Quote]
这个是默认绑定,因为可能有多个网卡,这个是让计算机选择默认的,具体的我也是从网上看来的
Evanue 2012-04-19
  • 打赏
  • 举报
回复
设置一个static内部静态变量, 发送过一次后设置为false 以后就不用再发送了·

我对LZ的代码有个问题··


为什么你的服务器用的地址是INDADDR_ANY呢

每次启动服务器 地址不知道··客户端怎么连接呢?



qscool1987 2012-04-19
  • 打赏
  • 举报
回复
急救。。。
现在我开个线程专门从控制台读取消息,保存在一个全局变量中,然后在send线程里获取这个全局变量,发送给客户端,
这里涉及到两个问题
1.同步,这个主要是线程里面的cin >> message;这个不是大问题
2.消息分发,我如何控制每个send线程只对读入的message发送一次?
如下是服务器端的send线程:

DWORD WINAPI SendThread(LPVOID lp)
{
SOCKET sock = (SOCKET)lp;
char buff[1024];
int ret;
while(1)
{
string msg = message; //continue get the to be send message
char buff[1024];
if(msg.length() > 0)
{
strcpy(buff,msg.c_str());
ret = send(sock,buff,msg.length() + 1,0);
if(ret == 0)
break;
else if(ret == SOCKET_ERROR)
{
cout << "send failed " << WSAGetLastError() << endl;
break;
}
}
}
return 0;
}

这是有问题的,这样写,读入一次客服端就会收到无穷个消息,可是我怎么想都想不出好办法。。求解。。。
qscool1987 2012-04-19
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 的回复:]
不好意思,看错了。

你两个SendThread线程,都在从控制台读取数据,有问题。
[/Quote]
恩。。。我改下,明白你的意思了
qscool1987 2012-04-19
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]
你两套线程(一读一写为一套,总共四个线程),用的是同一对 DWORD dwThreadId,dwSendThreadId;值
[/Quote]
我将这句代码放到循环里面还是解决不了问题。。。
我现在想想,应该不是这个问题,这个参数只是返回线程ID,创建的时候这几个线程的ID应该都是不同的,所以问题不应该是这里,但肯定是在服务器端
youngwolf 2012-04-19
  • 打赏
  • 举报
回复
正确的做法是单独一个线程,或者主线程来读取控制台数据,然后分发到各个send线程。
youngwolf 2012-04-19
  • 打赏
  • 举报
回复
不好意思,看错了。

你两个SendThread线程,都在从控制台读取数据,有问题。
qscool1987 2012-04-19
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]
你两套线程(一读一写为一套,总共四个线程),用的是同一对 DWORD dwThreadId,dwSendThreadId;值
[/Quote]
谢了,一点就懂了,哎,平时真没注意这个问题
youngwolf 2012-04-19
  • 打赏
  • 举报
回复
你两套线程(一读一写为一套,总共四个线程),用的是同一对 DWORD dwThreadId,dwSendThreadId;值

18,356

社区成员

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

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