初识用UDP协议做的windows窗口聊天程序---此处是单向的同步多线程对话框通信_下部分讲双向通信_VC网络编程_百度空间
初识用UDP协议做的windows窗口聊天程序---此处是单向的"同步"多线程对话框通信.下部分讲双向通信_VC网络编程_百度空间
个人中心
我的主页
好友
消息 站内消息 :无新消息提醒互动请求 :无新消息提醒系统通知 :无新消息提醒 paopaocayay200|装扮 |设置|退出VC网络编程
每天进步一点点主页博客相册个人档案好友查看文章 初识用UDP协议做的windows窗口聊天程序---此处是单向的"同步"多线程对话框通信.下部分讲双向通信
2010年06月11日 星期五 上午 11:38
问题1:进程与线程基础知识?
1.进程从来不执行任何东西,它只是线程的容器(注:每个进程必须有一线程.操作系统会自动创建)
2.线程拥有自己的私有地址空间(例:进程1与2都有一个地址0x1234,那么同时访问时,1只能访问1中的,2也只能访问2中的,互不干扰)
3.线程同时运行的原因?操作系统为每个运行线程安排"CPU时间片",一人用一段时间,轮流(注:轮流时间很短,可以用time函数推迟时间)
问题2:编写一个最基本的多线程,为什么代码一样,却出现乱码?
-----出现这种原因的根本问题是,以前使用的是单核CPU,现在使用的是多核,所以造成并发运行,混乱输出
解决办法---就是在输出之前给足时间片sleep(其中随输出大小而定,越大时间越长),这是之前的解决办法(不要用),最好办法设置线程保护
问题3:在问题2上增加while(i++<100)函数,出现多核CPU并发运行?
-----问题3同问题2一样,都是多核引起,CPU并发,造成乱码.怎样解决?只有实现线程保护,参看问题4线程保护之一:互斥对象
问题4:在多核环境下编写一个多线程售票?
------解决:线程保护一定要在线程还没创建之前就开启,否则一量创建就运行,保护就迟了. ------单与多核区别之处?单核在线程创建之后(注:并没规定必须要后,只是书上介绍,此处为纠正错误才提出,最好在前),多核在创建之前保护
------详见代码(正常运行是图上结果,此处改动为线程2专门卖票,是为了说明一个问题,若想正常运行,只需复制线程1代码即可,cout<<"线程1(这个1要改为2,好区分)) #include
#include
using namespace std;
int ticket=100;
DWORD WINAPI fun1_thread(LPVOID lpParameter ); DWORD WINAPI fun2_thread(LPVOID lpParameter ); HANDLE hMutex;
void main()
{hMutex=CreateMutex(0,0,0);//注:线程保护一定要在线程还没创建之前就开启,否则一量创建就运行,保护就迟了
HANDLE hThread1=CreateThread(0,0,fun1_thread,0,0,0);HANDLE
hThread2=CreateThread(0,0,fun2_thread,0,0,0); CloseHandle(hThread1);CloseHandle(hThread2); Sleep(4000);//时间必须要延迟的,否则很可能处理不完.当然时间长短随传输的大小而定 }
DWORD WINAPI fun1_thread(LPVOID lpParameter ) {
while(1)
{
WaitForSingleObject(hMutex, INFINITE);
if(ticket>0)
cout<<"线程1卖了第"<0)
cout<<"线程2卖了第"<
规则
编码规则下载淘宝规则下载天猫规则下载麻将竞赛规则pdf麻将竞赛规则pdf
.自动ID为0,并将计数器归0,这样就释放了自己的保护权
-----举例:2个没有ReleaseMutex的线程.一旦线程1,运行完,就运行线程2 -----详细代码:复制过去就能用
#include
#include
using namespace std;
int ticket=100;
DWORD WINAPI fun1_thread(LPVOID lpParameter ); DWORD WINAPI fun2_thread(LPVOID lpParameter ); HANDLE hMutex;
void main()
{hMutex=CreateMutex(0,0,0);//注:线程保护一定要在线程还没创建之前就开启,否则一量创建就运行,保护就迟了
HANDLE hThread1=CreateThread(0,0,fun1_thread,0,0,0);HANDLE
hThread2=CreateThread(0,0,fun2_thread,0,0,0); CloseHandle(hThread1);CloseHandle(hThread2); Sleep(4000);//时间必须要延迟的,否则很可能处理不完.当然时间长短随传输的大小而定 }
DWORD WINAPI fun1_thread(LPVOID lpParameter ) {
WaitForSingleObject(hMutex, INFINITE);//这2行单独的代码
表
关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf
示是
cout<<"线程1卖了第"<
#include
using namespace std;
DWORD WINAPI fun1_thread(LPVOID lpParameter ); DWORD WINAPI fun2_thread(LPVOID lpParameter ); HANDLE hMutex;
void main()
{
hMutex=CreateMutex(0,0,"1号");//此段最重要的地方:一定要给互斥对象取名.否则不能获得重复错误.
if(hMutex)
{
if(GetLastError()==ERROR_ALREADY_EXISTS)//注:ERROR_INVALID_HANDLE错误.因为它匹
配的是参数3的1号,而此匹配的是整个
{cout<<"只能同时运行一个实例"<>文章已详细介绍使用
方法
快递客服问题件处理详细方法山木方法pdf计算方法pdf华与华方法下载八字理论方法下载
与兼容处理方法
#####################################
------------------为确保正确,所以亲自做出了那个程序,下面就是讲解步骤.注:备注1(代码区)与第1步(讲解区)同步------------------ 前提:创建对话框应用程序,界面随意
第1步:初始化线程------->AfxSocketInit(至于头文件与放在哪,MSDN已说的很详细) 第2步:创建与绑定套接字->socket与bind--->放在哪?放在OnInitDialog()函数中(考虑到代码全放在一起不方便看,所以需建一个函数放)
------>用BOOL类型(为什么要用BOOL?因为出了问题,可以通过返回值判断提示.而void虽说可用,但出错了,却没有判断提示,不用)
第3步:创建线程(见备注3原因)--->CreateThread(注:记的用完后,用CloseHandle关闭线程)
第4步:等待消息--->recvfrom--->放在哪?放在子线程中,避开了阻塞--->记的收到的消息
放到::PostMessage传递给别人
第5步:发送消息--->sendto--->完成了.
提示一下:此处最难的一点,就是防止阻塞,线程就避开了,所以重点是添加并处理好线程,第2个功臣就是::PostMessage传送消息
----------------------------
备注1:
BOOL CMy3App::InitInstance()
{ AfxSocketInit();
---
#include //支持初始化winsock的头文件,放在StdAfx.h头文件中 ---
备注2:
InitSock();这个放在OnInitDialog()函数中
m_socket在类中定义为私有,因为套接字是公开使用的,用私有,也就是封装性会安全些 BOOL CMy3Dlg::InitSock()
{
////////////////////////////////第2步:创建socket//////////////////////////
m_socket=socket(AF_INET,SOCK_DGRAM,0); ////////////////////////////////第3步:创建bind////////////////////////////
SOCKADDR_IN sbind;
sbind.sin_family=AF_INET;
sbind.sin_addr.S_un.S_addr=htonl(INADDR_ANY); sbind.sin_port=htons(6000);
bind(m_socket,(SOCKADDR*)&sbind,sizeof(SOCKADDR)); return TRUE;//创建完后就返回了.注:返回1,继续运行
}
备注3:
1.为什么要创建线程?因为accept是一个死循环,如果你把它放在主线程中,就会造成对话框阻塞.解决办法是放在线程中,因为线程中有个时间
片,主与线程可以同时运行,又不发生阻塞.2全齐美
2.是不是很难创建线程?不是,别看教材上讲的乱七八糟,其实很有秩序的.你这样做:先在OnInitDialog函数中创建一个线程,然后看缺什么就写
什么.
3.The thread object remains in the system until the thread has terminated and
all handles to it have been closed through a call to CloseHandle. 翻译:1.只要线程不关,线程就一直运行
2.所有用完后的句柄要通过CloseHandle收回(注:句柄收回不代表关闭线程)
------下面就是部分代码,有很多是可以直接复制过去直接用的.比如获取IP,获取端口,直接复制过去就能用-----
InitSock();
StructThread *thread_3=new
StructThread;thread_3->socket=m_socket;thread_3->hwnd=m_hWnd;
HANDLE
hThread=CreateThread(0,0,fun_thread,(LPVOID)thread_3,0,0);CloseHandle(hThread);
BOOL CMy3Dlg::InitSock()
{
////////////////////////////////第2步:创建socket////////////////////////// m_socket=socket(AF_INET,SOCK_DGRAM,0);
////////////////////////////////第3步:创建bind//////////////////////////// SOCKADDR_IN sbind;
sbind.sin_family=AF_INET;
sbind.sin_addr.S_un.S_addr=htonl(INADDR_ANY); sbind.sin_port=htons(6000);
bind(m_socket,(SOCKADDR*)&sbind,sizeof(SOCKADDR)); return TRUE;//创建完后就返回了.注:返回1,继续运行
}
DWORD WINAPI CMy3Dlg::fun_thread( LPVOID lpParameter ) {
////////////////////////////////第4步:创建recvfrom//////////////////////// char c1[50];CString str_recv,str_send;SOCKADDR_IN srecv;int len=sizeof(SOCKADDR);
SOCKET s1=((StructThread*)lpParameter)->socket;HWND h1=((StructThread*)lpParameter)->hwnd;//注:为什么打括号
delete lpParameter;
while(1)
{
recvfrom(s1,c1,50,0,(SOCKADDR*)&srecv,&len);
::PostMessage(h1,WM_RECV,0,(LPARAM)c1);
}
return 0;//虽然说是返回0,结束,但是此前有个while(1)死循环,其实此段仅是做样子,按格
式写的好看的.必要的格式
}
void CMy3Dlg::OnS(WPARAM wParam,LPARAM lParam) {
CString str_recv=(char*)lParam;
SetDlgItemText(IDE_RECV,str_recv);
}
void CMy3Dlg::OnSend()
{
char serverIP[16]; CString
str_cip;GetDlgItemText(IDE_S_IP,str_cip);strncpy(serverIP,LPCTSTR(str_cip),16);
CString str_cport;GetDlgItemText(IDE_S_PORT,str_cport);UINT m_cport;m_cport=UINT(atoi(LPCSTR(str_cport)));
SOCKADDR_IN ssend;
ssend.sin_family=AF_INET;
ssend.sin_addr.S_un.S_addr=inet_addr(serverIP); ssend.sin_port=htons(m_cport);
CString str_recv,str_send;int len=sizeof(SOCKADDR);
GetDlgItemText(IDE_SEND,str_send); sendto(m_socket,str_send,50,0,(SOCKADDR*)&ssend,sizeof(SOCKADDR));
SetDlgItemText(IDE_SEND,"");
}
总结
初级经济法重点总结下载党员个人总结TXt高中句型全总结.doc高中句型全总结.doc理论力学知识点总结pdf
:
第1点:另外本代码是经过封装处理的.很多直接可以复制过去,直接就能用.典型的例子,就是获取IP,获取端口,直接复制过去就能用.
第2点:本章省去枝叶(即错误提示),保存了精华部分,目的是让主题明确.当然在你真正开发时,务必加上这些枝叶,因为它可以为你判断错误,以后维护起来会更方便,而且也不会因错误发生,而无法停止,导致更严重事故等等,切记!
第3点:本章与DOS下完全一样.只是多了一个多线程处理.虽然书上写的乱七八糟,那是误导你.你只有一眼抓住主题,也就是CreateThread,其它部分不攻而破了.因为所有函数就是围绕它来.
当你第1次写这个程序时,或许需要好几天才能理解透.但是当你第2次写时,其实10分钟就能写完
附注1:本章源代码已保存至邮箱中.即取即用
上一篇>> 端口映射图文教程 下一篇>> winsock2.h与afxsock.h发生冲突,... 类别:我的小程序 | | 添加到搜藏 | 分享到i 贴吧 | 浏览(797) | 评论 (1) 网友评论回复 1 wusoule 2010年08月26日
星期四 上午 09:55
感谢版主,拜读了你的博客之后,顿悟——.为什么要创建线程?因为accept是一个死循环,如果你把它放在主线程中,就会造成对话框阻塞.解决办法是放在线程中,因为线程中有个时间片,主与线程可以同时运行,又不发生阻塞.2全齐美。
可以请问一下你的学习历程吗,比如从哪些书开始看。谢谢~
发表评论 姓 名:paopaocayay200
*姓名最长为50字节
内 容:
同时将此文章分享给好友
验证码: 请点击后输入四位验证码,字母不区分大小写
看不清?
取消回复
推荐文章美女管理员:如果喜欢我,那就搭讪我吧
那些朋友们,又有谁能陪我走到最后,
空间管理社,在最美的季节,遇见你……
让我们一起努力吧,亲爱的空间管理社~
感谢版主,拜读了你的博客之后,顿悟——.为什么要创建线程?因为accept是一个死循环,如果你把它放在主线程中,就会造成对话框阻塞.解决办法是放在线程中,因为线程中有个时间片,主与线程可以同时运行,又不发生阻塞.2全齐美。
可以请问一下你的学习历程吗,比如从哪些书开始看。谢谢~
新消息
有人对你心动了,
Ta想和你测测默契!点击查看>>