win socket 即时通讯 多线程问题不解

QQ282881515 2010-12-25 01:57:23
小弟初涉socket编程,做了个小例子 暂不涉及select和其他机制。里边的线程是根据自己感觉去创建的,希望高人予以指教。代码如下,粘贴即可运行。

#include "stdafx.h"
#include <iostream.h>
#include <Winsock2.h>

//初始化socket
void Init_net()
{
WSADATA wsaData;
int ret = WSAStartup(MAKEWORD(2, 2),&wsaData);
}

DWORD WINAPI AcceptThread(LPVOID lpvoid);

DWORD WINAPI ReceiveInfo(LPVOID lpvoid);

DWORD WINAPI SendInfo(LPVOID lpvoid);


int main(int argc, char* argv[])
{
Init_net();

int af = AF_INET;

int type = SOCK_STREAM;

int protocol = 0;

SOCKET listensock = socket(af, type, protocol);//创建套接字

SOCKADDR_IN addr;
addr.sin_port=htons(5555);
addr.sin_family=AF_INET;
addr.sin_addr.s_addr=htonl(INADDR_ANY);

int len = sizeof(addr);

int ret = bind(listensock, (LPSOCKADDR)&addr, len);//绑定套接字

ret = listen(listensock, 5);//监听套接

HANDLE h = CreateThread(0, 0, AcceptThread, (LPVOID)&listensock, 0, 0);

WaitForSingleObject(h, INFINITE);//等待结束

CloseHandle(h);

closesocket(listensock);


return 0;
}

//接受连接线程
DWORD WINAPI AcceptThread(LPVOID lpvoid)
{
SOCKET *plistsock = (SOCKET*)lpvoid;
while(1)
{
sockaddr_in addr;
int len = sizeof(addr);

SOCKET clientsock = accept(*plistsock, (LPSOCKADDR)&addr, &len);

HANDLE hr = CreateThread(0, 0, ReceiveInfo, (LPVOID)&clientsock, 0, 0);

HANDLE hs = CreateThread(0, 0, SendInfo, (LPVOID)&clientsock, 0, 0);
}
return 1;
}

//接受数据线程
DWORD WINAPI ReceiveInfo(LPVOID lpvoid)
{
SOCKET *pclisock = (SOCKET*)lpvoid;

while(1)
{
char buf[100];

int l = recv(*pclisock, buf, 100, 0);
if(-1 == l)
{
continue;
}

cout<<buf<<endl;
}
}

//发送数据线程
DWORD WINAPI SendInfo(LPVOID lpvoid)
{
SOCKET *pclisock = (SOCKET*)lpvoid;

while(1)
{
char buf[100];
strcpy(buf, "服务器:");

int len = strlen("服务器:");

gets(buf+len);

send(*pclisock, buf, 100, 0);
}
}

/////////////////////////////////////////
/////////////////////////////////////////

include "stdafx.h"
#include <Winsock2.h>
#include <iostream.h>

void Init_net()
{
WSADATA wsaData;
int ret = WSAStartup(MAKEWORD(2, 2),&wsaData);
}

DWORD WINAPI SendInfo(LPVOID lpvoid);
DWORD WINAPI ReceiveInfo(LPVOID lpvoid);

int main(int argc, char* argv[])
{
Init_net();

int af = AF_INET;

int type = SOCK_STREAM;

int protocol = 0;

SOCKET clisock = socket(af, type, protocol);//创建套接字


sockaddr_in serv_addr;
serv_addr.sin_family=AF_INET; /* to结构体中的sin_family定义地址族 */
serv_addr.sin_port=htons(5555);
serv_addr.sin_addr.s_addr=inet_addr("127.0.0.1"); /* 填写IP,并转换成in_addr */

int len = sizeof(serv_addr);
int ret = connect(clisock, (LPSOCKADDR)&serv_addr, len);
if(0 == ret)
{
cout<<"成功连接服务器!"<<endl;
}

HANDLE h = CreateThread(0, 0, SendInfo, (LPVOID)&clisock, 0, 0);
HANDLE hr = CreateThread(0, 0, ReceiveInfo, (LPVOID)&clisock, 0, 0);

WaitForSingleObject(h, INFINITE);

return 0;
}

//发送数据线程
DWORD WINAPI SendInfo(LPVOID lpvoid)
{
SOCKET *pclisock = (SOCKET*)lpvoid;

while(1)
{
char buf[100];
strcpy(buf, "客户端:");

int len = strlen("客户端:");

gets(buf+len);;

int data = send(*pclisock, buf, 100, 0);
}
}

//接受数据线程
DWORD WINAPI ReceiveInfo(LPVOID lpvoid)
{
SOCKET *pclisock = (SOCKET*)lpvoid;

while(1)
{
char buf[100];

int l = recv(*pclisock, buf, 100, 0);
if(l==-1)
{
continue;
}

cout<<buf<<endl;
}
}
...全文
260 33 打赏 收藏 转发到动态 举报
写回复
用AI写文章
33 条回复
切换为时间正序
请发表友善的回复…
发表回复
QQ282881515 2010-12-28
  • 打赏
  • 举报
回复
[Quote=引用 29 楼 longren331100 的回复:]
你发的代码为何有2个文件,而且又相互冲突,lz想问问题的话可否问清楚点,代码别贴的太乱了
[/Quote]

至于问题 就是感觉线程那块怪怪的 具体我提不出来 抱歉
QQ282881515 2010-12-28
  • 打赏
  • 举报
回复
[Quote=引用 30 楼 visualeleven 的回复:]
引用 13 楼 qq282881515 的回复:
引用 12 楼 fantiyu 的回复:
楼主给你点建议
暂时先对每个连接进来的socket开启一个线程,线程针对socket进行一对一服务
等做熟了,看看select模型,然后研究一下IOCP
然后就可以毕业了

谢谢12楼 iocp我还真的不了解
我暂时没定义链表管理每个客户端套接字 暂时只限于一个客户端 就想搞清楚线程和套接字……
[/Quote]谢谢兔子组长
QQ282881515 2010-12-28
  • 打赏
  • 举报
回复
[Quote=引用 29 楼 longren331100 的回复:]
你发的代码为何有2个文件,而且又相互冲突,lz想问问题的话可否问清楚点,代码别贴的太乱了
[/Quote]
不好意思 看的晚了
哦 那是一个客户端 一个服务端的代码

/////////////////////////////////////////
/////////////////////////////////////////
隔开的
QQ282881515 2010-12-27
  • 打赏
  • 举报
回复
2010-12-27
还有问题!!!!!!!!!!!
我服务器里边的线程函数AcceptThread中所写那样:每连接一个客户端 我都要创建两个线程,分别去发送和接数据,也就是说我有N个客户端连接 就需要创建1+2N个线程。感觉不对啊……请教高人!!!!
Eleven 2010-12-27
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 qq282881515 的回复:]
引用 12 楼 fantiyu 的回复:
楼主给你点建议
暂时先对每个连接进来的socket开启一个线程,线程针对socket进行一对一服务
等做熟了,看看select模型,然后研究一下IOCP
然后就可以毕业了

谢谢12楼 iocp我还真的不了解
我暂时没定义链表管理每个客户端套接字 暂时只限于一个客户端 就想搞清楚线程和套接字的关系
至于 线程一对一的服务 这句话 假如连……
[/Quote]
一个线程维护一个客户端的连接
longren331100 2010-12-27
  • 打赏
  • 举报
回复
你发的代码为何有2个文件,而且又相互冲突,lz想问问题的话可否问清楚点,代码别贴的太乱了
QQ282881515 2010-12-26
  • 打赏
  • 举报
回复
[Quote=引用 26 楼 fantiyu 的回复:]
引用 15 楼 meteor_code 的回复:
你这个是最容易实现的网络通信方式,也是小型服务器的实现方式(没有测试过,但感觉1000个线程没问题),
你应该把发送数据的部分放在接收中,一般是,接收数据,分析数据是什么,处理数据,然后发送出去,就是c/s模式服务器那样。这就是我要给你的建议了


1000个线程?这个不是凭感觉能感觉出来的
1000个线程,光堆栈就要占掉1G内存,co……
[/Quote]

额 没有一个进程会创建那么多线程,当然也不可能 呵呵 谢了 再给点其他建议呗。
fantiyu 2010-12-26
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 meteor_code 的回复:]
你这个是最容易实现的网络通信方式,也是小型服务器的实现方式(没有测试过,但感觉1000个线程没问题),
你应该把发送数据的部分放在接收中,一般是,接收数据,分析数据是什么,处理数据,然后发送出去,就是c/s模式服务器那样。这就是我要给你的建议了
[/Quote]

1000个线程?这个不是凭感觉能感觉出来的
1000个线程,光堆栈就要占掉1G内存,context切换起来cpu直接被玩死
即使线程里几乎什么都不做,到处都sleep,系统都很难撑住

针对socket开线程,只能满足小规模初级应用,谁也不会写服务器代码的时候这么干的
QQ282881515 2010-12-25
  • 打赏
  • 举报
回复
继续等待高人 感谢大家
QQ282881515 2010-12-25
  • 打赏
  • 举报
回复
[Quote=引用 23 楼 nklwg 的回复:]
引用 15 楼 meteor_code 的回复:
你应该把发送数据的部分放在接收中,一般是,接收数据,分析数据是什么,处理数据,然后发送出去,就是c/s模式服务器那样。

说的就是接受的数据和发送的有联系嘛
要是没联系,还是分开些好
[/Quote]
恩 我没想到 接收和发送数据有联系这个情况 某些场合应该会这样要求的吧!
谢谢
nklwg 2010-12-25
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 meteor_code 的回复:]
你应该把发送数据的部分放在接收中,一般是,接收数据,分析数据是什么,处理数据,然后发送出去,就是c/s模式服务器那样。
[/Quote]
说的就是接受的数据和发送的有联系嘛
要是没联系,还是分开些好
QQ282881515 2010-12-25
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 arong1234 的回复:]
无论系统提供多少线程,还是要节约使用,你应该按需设计,而不是按系统容量设计

引用 16 楼 qq282881515 的回复:
引用 15 楼 meteor_code 的回复:
你这个是最容易实现的网络通信方式,也是小型服务器的实现方式(没有测试过,但感觉1000个线程没问题),
你应该把发送数据的部分放在接收中,一般是,接收数据,分析数据是什么,处理数据,然后发送出去,就是c/s模式服……
[/Quote]
接受 谢谢楼上 您的答案给我感觉上边程序线程创建“还行”,呵呵!我下去会将连接到服务器的套接字管理起来, 自定义一个数据包 去写个稍微“大”的例子 多谢楼上

同时也感谢楼上各位,各位给我的回答我会仔细思考 谢谢
QQ282881515 2010-12-25
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 arong1234 的回复:]
在很多情况下这很正常,一个多线程socket程序,一个socket最多可能有4个线程操作:1个是accept的,1个是专门处理连接的建立的,一个收数据,一个发数据

不同线程的最大原因是:不是每个socket通讯都是应答式的,你接收的报文和你发送的报文可以毫无关系(这样的东西非常多),这样如果收发在一起,等于把两个毫无关系的东西放在同一个线程,是多线程程序大忌

引用 7 楼 fantiy……
[/Quote]
谢谢楼上 四个线程 比我的还多一个 呵呵
“1个是专门处理连接的建立的”是什么情况?谢谢
arong1234 2010-12-25
  • 打赏
  • 举报
回复
无论系统提供多少线程,还是要节约使用,你应该按需设计,而不是按系统容量设计[Quote=引用 16 楼 qq282881515 的回复:]
引用 15 楼 meteor_code 的回复:
你这个是最容易实现的网络通信方式,也是小型服务器的实现方式(没有测试过,但感觉1000个线程没问题),
你应该把发送数据的部分放在接收中,一般是,接收数据,分析数据是什么,处理数据,然后发送出去,就是c/s模式服务器那样。这就是我要给你的建议了

恩 线程我试了下 在xp下好像是5000个线程数多吧 是最容易的 我差点把listen()函数……
[/Quote]
arong1234 2010-12-25
  • 打赏
  • 举报
回复
在很多情况下这很正常,一个多线程socket程序,一个socket最多可能有4个线程操作:1个是accept的,1个是专门处理连接的建立的,一个收数据,一个发数据

不同线程的最大原因是:不是每个socket通讯都是应答式的,你接收的报文和你发送的报文可以毫无关系(这样的东西非常多),这样如果收发在一起,等于把两个毫无关系的东西放在同一个线程,是多线程程序大忌
[Quote=引用 7 楼 fantiyu 的回复:]
为什么发数据,接数据,用不同的线程?
[/Quote]
QQ282881515 2010-12-25
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 meteor_code 的回复:]
一般来说,发送和接收是应该在同一个线程里
[/Quote]

哦 我也感觉分开放 线程有些累赘
但我不解的是 放在一起的话 每while一次就会执行 发送 和 接收 两个操作。假如我没输入数据,它一直等着我输入发送内容, 但是 客户端给我发了信息 这时候一直阻塞在等待我输入数据 咋办?
Meteor_Code 2010-12-25
  • 打赏
  • 举报
回复
一般来说,发送和接收是应该在同一个线程里
QQ282881515 2010-12-25
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 meteor_code 的回复:]
你这个是最容易实现的网络通信方式,也是小型服务器的实现方式(没有测试过,但感觉1000个线程没问题),
你应该把发送数据的部分放在接收中,一般是,接收数据,分析数据是什么,处理数据,然后发送出去,就是c/s模式服务器那样。这就是我要给你的建议了
[/Quote]
恩 线程我试了下 在xp下好像是5000个线程数多吧 是最容易的 我差点把listen()函数也放在辅助线程上(惭愧)。我用mfc套接字做过类似c/s模式服务器 但那不需要我去起辅助线程 只是覆盖mfc套接字的虚方法。 至于“应该把发送数据的部分放在接收中”这句话 是不是就像七楼说的 发送和接收放在一个线程里边?谢谢
Meteor_Code 2010-12-25
  • 打赏
  • 举报
回复
你这个是最容易实现的网络通信方式,也是小型服务器的实现方式(没有测试过,但感觉1000个线程没问题),
你应该把发送数据的部分放在接收中,一般是,接收数据,分析数据是什么,处理数据,然后发送出去,就是c/s模式服务器那样。这就是我要给你的建议了
QQ282881515 2010-12-25
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 fantiyu 的回复:]
为什么发数据,接数据,用不同的线程?
[/Quote]

额 我想起了 那发送那块 压根不输入语句 而另一端发送了数据 等待他去接受 不久阻塞到那块了么!
加载更多回复(12)

18,356

社区成员

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

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