项目10 TCP一对多通信程序

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

处理线程t1
多线程模式(并行模式) recv()
主线程 server = socket();
bind(server);
listen(server);
send()
close() 处理线程t2
recv()
client = accept(server); CreateThread()
send()
close() 处理线程t3
21
线程与线程之间传递参数
问题:子线程如何向主线程或其他线程传递参数 SendMessage()函数将指定的消息发送到一个或多个
窗口。此函数为指定的窗口调用窗口程序,直到窗 口程序处理完消息再返回。
PostMessage()函数,将一个消息寄送到一个线程的 消息队列后立即返回。
BooL PostMessage(HWND hWnd,UINT Msg, WPARAM wParam,LPARAM lParam);
33
多线程在Server(TCP)程序中的使用
DWORD WINAPI ThreadFunc(LPVOID param) {
SOCKET sAccept = (SOCKET)param; ……
while(true) {
memset(RecvBuf,0,sizeof(RecvBuf)); iRecv=recv(sAccept,RecvBuf,sizeof(RecvBuf),0); …… iSend = send(sAccept,buf,sizeof(buf),0); …… } closesocket(sAccept); // //关闭同客户端的连接 …… }
22
PostMessage()函数
PostMessage()函数使用举例 ::PostMessage(hwnd,WM_RECVDATA,0,(LPARA
M)buff);
PostMessage 是异步的,SendMessage 是同步的。 PostMessage 只把消息放到队列,不管消息是不是
25
何时采用多线程??
如果一个应用程序,有多个任务需要同时进行处理, 则适合使用多线程机制。
对于网络上客户机软件:采用多线程,能克服在 单线程的编程模式下,由于阻塞等待而产生的客 户程序就不能及时响应用户的操作命令的问题。
对于网络上服务器软件:采用多线程的编程技术, 能更好地为多个客户服务。
线程函数
DWORD WINAPI ThreadFunc (LPVOID param)
12
线程函数
线程函数:每个线程的进入点函数,线程从这个进 入点开始运行
主线程的进入点函数 m a i n Wi n M a i n
自定义线程函数: DWORD WINAPI ThreadFunc(LPVOID param) MFC中 UINT CSelwinsDlg::ThreadFunc(LPVOID a)
主线程
传递值
子线程
用PostMessage()发送消息
24
为何多线程程序能自动接收消息
WSAAsyncSelect()模型
FD_READ事件触发时
Socket
发送消息
对话框
TCP多线程程序
recv() 所在子线程
PostMessage() 发送消息
对话框
多线程程序手工实现了异步发送通知消息给对话框
对于一个客户:采用多线程机制也能大大提高应 用程序的运行效率。
26
此时套接字工作在阻塞模式下 将阻塞方式的I/O操作在单独的线程中进行,保证
整个程序(进程)是非阻塞的。 使用多线程而不使用非阻塞模式的套接字,可以
实现同时处理多个连接的功能—并发服务器
27
控制台版TCP一对多通信
28
14
创建线程示例——倒计时程序
15
16
WaitForSingleObject()函数的使用
…… #include <windows.h> // 线程函数
DWORD WINAPI ThreadMain(LPVOID param) {
LONG i,PassVal; PassVal = (LONG)param; …… return 0; }
使用CreateThread() 等Win32 API线程函数; #include <windows.h>
使用MFC线程类CWinTread:编程时用 AfxBeginTread()建立CWinTread对象
使用C多线程库函数 _beginthread() ;
#include <process.h>
10
CreateThread()
#include <windows.h>
HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes,
DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId);
send()
recv()
closesocket() 派生线程
单线程模式(串行模式)
server = socket();
知名端口 bind(server);
listen(server阻); 塞,直到客
户端连接到来
client = accept(server); 生成新socket(client)
影 recv(client); 响 请求数据处理 并 send(client); 发 性closesocket(client);
19
多线程程序编程的步骤
1. 编写线程函数 所有线程必须从一个指定的函 数开始执行,该 函数称为线程函数,它必须具有下列原型: DWORD ThreadFunc( LPVOID lpvThreadParm);
2. 创建一个线程 一个进程的主线程由操作系统自动创建,如果要让
主线程创建额外的线程,可以调用CreateThread() 函数完成。
18
什么时候需要多线程
有多个任务需要同时进行处理,比如TCP服务器端需 要同时与多个客户端进行通信。
避免在单线程模式下,由于阻塞等待而产生 的应用程序不能及时响应用户操作的问题。
应用程序产生阻塞等待的原因: 调用了引起阻塞的函数,如scanf,accept等 调用了死循环,如while(true) 如文件传输程序
recv()
send()
30 closesocket(server);
close()
31
创建多线程的服务器
可以用并发性能来衡量一个服务器同时响应多个客 户的能力。一个具有好的并发性能的服务器,必须 符合两个条件: 能同时接收并处理多个客户连接。 对于每个客户,都会迅速给予响应。
服务器同时处理的客户连接数目越多,并且对每个 客户做出响应的速度越快,就表明并发性能越高。
被处理就返回,消息可能不被处理; SendMessage等待消息被处理完了才返回,如果消
息不被处理,发送消息的线程将一直处于阻塞状态 ,等待消息的返回。23Fra bibliotek实例演示
将accept()函数写到一个子线程中,关键点: 如何将监听套接字传递给子线程 如何将子线程中的值传递给主界面线程
用CreateThread()的第4个参数
32
多线程在Server(TCP)程序中的使用
#include "windows.h" DWORD WINAPI Thread(LPVOID param); //声明线程函数 HANDLE hThread[TotalThread]; //线程句柄 DWORD ThreadID[TotalThread]; //用于取得线程标识
在其调用进程的进程空间里创建一个新的线程, 如果创建成功则返回线程的句柄,否则返回NULL。
11
CreateThread()的参数
必须设置的参数: 参数3:lpStartAddress 参数4: lpParameter 参数6: lpThreadId
DWORD WINAPI ThreadFunc(LPVOID param); HANDLE hThread; DWORD ThreadID; …… hThread=CreateThread(NULL,0,ThreadFunc,hDCT,NULL, &ThreadID);
…… //为每个新连接创建线程,accept返回的socket作为参数传递给
线程函数 while(true) {
sAccept = accept(sListen,(LPSOCKADDR)&cli,&iLen); ……
hThread[iTotal] = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)T hreadFunc,(LPVOID)sAccept,NULL,&ThreadID[iTotal]);
13
注意
如果线程函数不是DWORD WINAPI 类型,可 用下面的方法强制转换
(LPTHREAD_START_ROUTINE)ThreadFunc,
例如: hThread=CreateThread(NULL,0,
(LPTHREAD_START_ROUTINE)ThreadFunc, NULL,0, &ThreadID);
5
进程 vs. 线程
Win32操作系统是多任务的,并且支持一个进程中 有多个线程
进程是系统进行资源分配和调度的一个独立单位。 线程是进程的实体,属于进程,是CPU调度和分配
的基本单位。
以多进程形式,允许多个任务同时运行。 以多线程形式,允许一个任务拆分成多个线程运行 CPU提供协调机制,允许线程之间共享资源,防止
线程之间产生冲突。
6
进程 vs. 线程
每个进程都有自己独立的代码和数据空间 (进程环境),进程切换开销大
每个进程中的多个线程共享相同的代码和 数据空间,线程切换代价小
7
线程与CPU的关系
单核心CPU分时地运行进程中的各个线程
8
VC多线程编程 关键问题
怎样用编程语言创建线程?
9
创建多线程的3种方法
20
线程函数的参数传递
创建线程时可以给线程传递参数。 由CreateThread()函数原形可以看出,线程函数可
以有一个void 指针类型参数,该参数值在创建线程 时由CreateThread函数的第4个参数传入。 能直接传递的参数个数值只有一个,如果需要传送 的值为多个,可定义为结构体。
项目10 TCP一对多通信程序
唐四薪
引言
如何实现TCP一对多的通信?
对于TCP编程来说,要实现一对多通信,最简单的 办法是采用多线程来实现,在每个线程中分别与一 个客户端建立连接并传输数据。
解决方案:
多线程 Select模型 I/O完成端口模型
2
以后再讲
TCP一对多通信程序
3
控制台版TCP一对多程序
并发服务器
WSAStartup() socket() bind() listen()
等待客户连接请求的到来 accept()
CreateThread() closesocket()
WSACleanup() 服务器端
29
主进程在accept之后派 生新线程,然后主进程 继续listen,处理新的连 接请求,新线程自行和 客户端通信
17
int _tmain(int argc, _TCHAR* argv[]) {
DWORD ThreadID, dwRet; HANDLE hTh; // 创建线程,执行ThreadMain()函数 hTh=CreateThread(NULL,0,(LPTHREAD_START_ROUTI NE)ThreadMain,(LPVOID)10,0,&ThreadID); …… dwRet = WaitForSingleObject(hTh,INFINITE); switch(dwRet) {……} return 0; }
4
应用程序、进程及线程的关系
进程(process)
程序的一次执行,操作系统分配资源的基本单位
线程(thread)
进程中的执行的一段程序片段,操作系统执行的基本单位
同一进程所产生的线程共享同一内存空间 一个进程中至少要有一个线程,称为主线程。当启 动了一个应用程序时,操作系统将为它创建了一个进 程,同时创建该进程的主线程,并开始执行主线程 主线程可以创建并启动其他辅助线程,由主线程创 建的线程又可以创建并启动更多的线程
相关文档
最新文档