0

    [doc] 没有QQ我照样聊天!——自己动手制作一个局域网聊天器

    2023.04.12 | admin | 245次围观

    [doc]没有QQ我照样聊天自己动手制作一个局域网聊天器没有QQ我照样聊天自己动手制作一个局域网聊天器没有我照样聊天自己动手制作一个局域网聊天器起因曾经有一段时间我在一个单位上班那个单位是允许上网的所以我能经常在单位开QQ聊天暗爽可是好景不长老总们终于发现了问题的严重性一个命令下去网被封了我们屋里是一个非常和谐的集体大家一上班就建群聊天突然间没有了QQ还真是有点不适应了一天中午大家吃饭聊天的时候一名女硬件工程师突然说了一句你们这帮搞软件的不挺牛的嘛最近也没事儿给我们作个QQ吧我们几个想了想虽然这话是逗着玩的但是也是啊虽然不能上互联网聊局域网里大家聊天也挺爽啊而且Socket编程又不是很难我们几个商量了一下一不做二不休回到办公室我们就开始了行动原理现在最流行的软件中聊天软件占有相当的比重QQ更可以说是在中国几乎每台机器上必装的小软件了表面上看聊天软件短小精悍只要用简单的Socket的传出和发送就可以了而且聊天软件本身并不需要过多的安全我指的安全是对发送信息而言的我们发的聊天信息并不是多重要的没发出去重发就可以了编起来也不是什么难事儿从结构上看一个聊天软件除了要有很好的Socket的发送传输技术支持还要有非常好的互动性我想后者对于用户而言是更重要的比如QQ在接收到信息的时候会通过声音和不停的闪动来告诉用户你有信息了实际上聊天软件的制作并不是很难主要的难点也并不是集中在信息的发送与接收QQ等聊天软件最让人觉得喜欢使用的原因也并不是在于其快速的数据传递而是因为其多变的好看的视图我这里撰文张蓐讲的视图不是指所谓的软件的皮肤而是软件除了数据处理部分以外和用户交互的一切窗口变化比如说当某个用户发信息给你的时候你的QQ上的对应人物的图标就会闪动如图1再比如在QQ被最小化呆在系统托盘中当有信息到达QQ的图标就会变成相应发来信息人的图标闪动如图2不要说圈1oo圈标闪动效果这些和底层的数据比并不算圈2oo任务栏圈标闪动什么经过我们实际编程我们发现搭建数据完成服务器端和客户端的数据传输编程并没有占用我们太长的时间而我们在做一个字体闪动效果的时候却花费了很多的时间目前流行的聊天软件大部分使用了UDP协议这是一个非常简单的协议它只管把信息发出去就完了而且在链接上UDP协议规定只要知道对方的端口和II就可以发送信息了所以UDP协议的速度非常快而且建立起来也非常容易但由于UDP是面向非连接的所以它的安全性确实比较低另一种协议也就是TCP协议正好相反可能速度上稍微慢了一点但是由于TCP是面向连接的所以有很好的安全保障但是发送和接收信息的双方要先进行了握手连接才可以互发信息所以从连接上TCP稍微麻烦了些我是使用TCPIP协议制作的软件一个原因呢我比较习惯了TCP的做法另一个原因呢由于TCP的Socket编程稍微难一些这样覆盖的技术面也大些读者可以学到更多再有有的程序员可能认为聊天软件的发送与接收magh1mmt85只是一些聊天信息的传递实际上聊天信息的传递只不过是聊天软件信且发送的一个非常小的部舟举个例子当你登陆QQ的时候你的所有在线好友都可以看到你的QQ图标从黑白色变成了彩色同qq群聊对话生成器在线制作

    时发出叮咚的声音这当然不是一个全自动的过程而是当你登陆的时候发送了一条信息给了服务器告诉服务器你登陆了然后服务器向所有你在线的QQ好友发送你登陆的淌且所以他们的Qq里你的国标变成了彩色由此我们知道在做聊天软件之前我们还要定义一个通信标准一个统一所有爵令信息的标准而软件里发送的所有信息都要符台这个标准这样我们就可以实现消息的统一传递其他的聊天软件也就不能看懂这种我们规定好的信息了准备工作好了有了理论基础我可以开工了在编程之前我们要确定一下使用哪一种编程环境做Socket开发建议使用VC6现在Soeke的使用上有两种方式一个是使用WindowsAPISocket一个是MFC里的CSocket类相t之下WindowsAPiSocket给了开发者更大的控制能力CSocket的使用面稍窄但是使用起来非常地容易方便毕竟相关的类都是现成的我们只要对必要的虚函数进行重载和覆盖就可以了所以最终我们选择了立于用的CSocket在VC60平台上开发蒋有就是一个非常重要的司题了上面提到过要给我们的信息传输定义一个标准这个标准指导我们对要传送的信息进行打包和解包大家都遵守同样的标准彼此的工作才能相互配台这是进行酉队开发的重要关建个结构用采存储时间txstructfshorty魄r口nlotlth日munBYIEminute髓1Ese几d峨5htc蚀瞻蟾自l匈乜nctcharFr口H网这是个标志位如累是SEllV1ER那么就是从服务薯蝴发I如集是cuE唧厶就是从客户媾发来的1cnnd这个是命令类型根据就是上面的邪几个命令charFrmmerrte]发避信息的用户名dHrL目[瑚接收信息的用户名char0叫]伯息内容惟oJrime发避采的时茼txamt有了这个结构我们发送和接收信皂就有了一个共同的标准这里要注意几个问题首先我们编的是一个聊天软件并不需要很多的安全措施但是Fromlog可以作为安全措施的一种方法比如如果我不告诉你我的信患头有一个Fromlog你就不知道应该怎么解析其实在很多信息传输软件里这就是关键一般都是会在信息头里写入很多的代码用来保证安全和信鼠的准确发布这样别人截获了你的信息也不清楚到底是什么意愚还有就是Corlmand如果你有兴趣你可以接着加上一些其他命令扩充系统功能是很容易的此外并不是每一条信息都有相应的发送者和接收者信且有可能只有一个名称并无实际内容比如服务器端向所有的客户端发送的系统关闭下线命令只要键下面是我们定义的信息打包结构对Fromlog设置为SKRVERCommand设置为JSYSOFF定义Frmlog标志dgf腮jNIOiERVERNBmreRIE舟neJPtfIZEffruE盯定义各种omrmlmd命令类型靠IfineJuseRINla00defineRD1dne3SYSIN息强赶觅卢终啻专开始制作第一步服务器制作在制作这个聊天软件上我们采用了传统的CS《客白机服务器模式而且采用的是客户端直接把信息发送给服务器端然后再让服务器端转发的一种模式下页图3这里本身我也不是很提倡这样做但是这样敞能很简单地实现我们的目的我建议大家可以尝试下p2Pqq群聊对话生成器在线制作

    的方式由两个客户端直接进行消传送而不需要通过服务器中转圈3情境服务嚣窖户转发懂式OnAcct函数是当有客户端要和服务器端链接的时候触发的一个函数dsterlFcket-0哺口c鲫f憎roe总结一下服务器端要完或以下任务1可以发送信息给任何一个登陆的客户端当然包括系统广播2接收并转发客户端发来的一切信息3保夺当前登陆用户信息表4强行让某个用户下线为了完成以上功能我们耍建立两个CSocket的继承类分别是ListenSocket和ServerSocket其中ListenSocket用来监听客白端登陆ServerSocke是用桌和客户端对接的socket每当ListenSocket监听到一个客户端的连接请求我们就可以自动建立一个ServerSocket和客户端连接在一起以后就通过这个ServerSocket发送给这个客户端指定的信邑这是典型ServerSocket亡]1eatSocketnewServersccketO这样眼务器就可以完成监听客户端信息了这里这个ClientSocket指针要保存起来因为以后想给这个客户发信患就是要通过这个ClictSecket原理就是图4表达的意思LiszenSocket只不过是用来负责监听的真正的发送和接收信息的都是serverS0cket接下来捷们要在ServerSockez的OnReceive函数里添加一些操作了OnReceive函数也是一个虚函数它是当Socket接收到信息的时候触发的一个函数想一想服务器端会接收到什么信息呢当然是我们已经定义好格式的信息包服务器端要在接收到这些信息后立刻实现转发监听眦SocketInitUXTPort救是螭口号随意一个数字载可以倒建SOCketm-LstenSocket是一个CSocketf1fu1stenSocketcreatePortSOOSTRFAMreturllFALSEf1stenSocketListenOsecket开姐监听returtlFALSEl然后实现ListenSocket的一个虚函数OnAccept投穑信箱tougaocsdnnot如果这些信息处驾写好了了邪么我1还剩下的一个问题就是要存储巳登陆用户的信息列表就好墩QQ上的你的个人资料由于我们都认识也就不在这十方面使劲了所以我们使用了如下的一个非常简单的结构mjgcsdElIlet87CStringuerNameCsocketsocketuserItypedefArraylt]userlnfO]userlnfogtCUserst用户囊OJserList_UserLiSt其中socket指针用来存储当前和客户端socket链接一一一一的一个Serv如ck吼对象的指针而urNamerAU由于服务器井没有什厶视图的变化要求而且有也这个客户端的唯一标讽它的胃户名基本迷两个就够了不怎厶难实现昕以我们被好了基本的信息发送接收岔口果你想做的更丰富些就可以在这个结掏里再添加年目罡每器端就基本做好了a龄啊星窿啊反正随你想吧一发送信鼠方面服务器大翻分是在转发信息也就是得至信息的同时解析信息得到指定的ToUser信息发给的用户

    [doc] 没有QQ我照样聊天!——自己动手制作一个局域网聊天器

    名然后再把信a转发培这个T0r服务器也有一些直接发送的信息比如系统广播系统下线命令和强行让某个用户下线的命令为了方便以后的发送函数调用我们不妨先做两个第二步客户端制作客户端在数据传输上的代码比服务器端多一些因为毕竟直接发出信且的是客户端直接接收数据的也是客端方法也和刚才拽1看到的服务器端非常相似实际上客户端的难点基本上都集中在视图上了像指定的用户名动等等操作都是很耗功夫的东西很多做过发送的ferintOCOUnt1]userInfouserznfoLUSerListGetAti扭粜是发话方的用户名郝幺就不发送ifusenu岫I江De灶呻f州ers惜sa9ee呲user卫_fosocke七程里最简单的一个但实际上聊天器真的一点儿都不简单有损多很多复杂的视图显示开发起来都非常地麻烦首先我们要在程序开始的时候创建一个客户端BOOLsketznitCStringlipUINTPot七]f亡1entsocketm_clientcketneCle眦sOc创建5ocket_-ureturnFALSE链接指定的I嘟蠕口的服务置ffm_c1dd口rnretu几IFALSEretlmTRuE这个时候我们要考虑一个问题那就是客户端的登陆问题登陆绝对不是一个简单的事情首先我们要让客户端发一个登陆信息给服务器同时服务器则检测最仅拿服务卷端的系统群发发送命令TSYSALL代用白的登陆是不是台法如果台法郡就建立连接码为例其他的大同小异髓3dngwords首先建立一个COntext结构然后在这个结构里存入需要自l信息最后发进Jcontextcontext难r啕[dccnt00szem彦0]s七僦R咖R旧信息来自服务嚣contetCCmland]SYSALL龠令粪整墨膳务蜜群篮1st咖t岫-W玳幻发送的内窑cn惟tcri憎融brr日哪惟0蓑i罨当砷时间contextolrTimeyeartGetearO生成时间ctexttuttimemonthtGetM0nth088髑帅并重膏Iu如果不台法那么当然断开Socket这就完了么当熊没有别忘了把服务器端的用户列表发给客户端至少客户端的用户得知道都有谁在线hE然后在ClientSOeket类里也要实现虚函数OnReceive建立一个用户表存储当前的在线用户方法和Server端完全一样这里不作赘述了接着我们要完成一些发送的指令客户端要发送的指令基本上有四个分别是发送登陆指令发送下线指令发送一般聊天信息发送群发消息发送的方法也和上面的服务器一样我仅拿发送一般聊天信息举例voldc1ientSocket5enrcst一嘲IDserCStringwords1t先建立一个]context哪fromuser倌蠹量后发送JContextcontextlstrcFr咖信息来自客户端ctextca帅land一3WORD糖聊天信息发送命1strq田佃c七R口H瞄rfr口『发选甩户名1疆幢垃H聩托发结用户名1stl田僦r发送的聊天内窖climetCTmeJr啦0嘲当曹钔对间『Tb呲QIrn腱跚GetYearO生翩寸间It呷廿U00e啦Ol糖econdtGe

    tSe0sEfd岫ssagen呲好了指令你也做好了那么我们就可以实现服务器和客户端的信息交互了你觉得大功告成了我想没有做过的一定这样认为其实这只是聊天软件信直交互部分你想一想一个信息成功的发给了指定的用户那个用户怎么知道就青信息了比如Qq会发出声音井晃动用户的头像而这才是客户端最重要的东西下面用V-C的代码来解释如何实现这种视图反馈效果我们在OrLReceive里得到了消息经过判断确定这是一个甩户发来的一般聊天消息voiddieSocketonRecve1ntnErrorCodetCStringIPIP地址u口uport0蝻口3rltextc0e壮投穰信箱tougaocMdnnetB00LPlaySoundLFCSTRpszSoundHIVOfJLEhmoda粕fdwsound知道笨个参数是这十声音戈件的路陉就行了我们把这个数先加到函数里voidcle1s0cketh自veinnErrOodeCStringIPiP地址u尚r-tO靖口]0惝目c0next发采的信息内窖获耨裳送来的信息6RdIPugort各种f酊舳处理LLsN戋算_蜘明一一一一„„„„薹薯好了声音实现了下面我们要产生一个晟简单的字体闪烁效果但设我们使用的是一个列表框那么我们要让这个列表框的某一项闪烁实际上就是让这一项不悼地让文字消戋和出现这样就可以让用户觉得一个用户的名字在闪动现在来研究一下这个闪动的过程首先我们可以知道的是当一个Jw0RD类型的JContext数据发到客户端的时候就是这个闪烁的开始而当用户双击某个用户的时候也就是打开信息的时候结束闪动在此期间列表框内指定的用户名必须不停地在闪动而且最麻烦的是不一定就是一个在闪大多数情况下应该是有很多用户的名字在列表框上闪动的这样控制可就麻烦了另外一个问题我们知道用户肯定不会在Socket刚刚获得数据的圃5Jet8g同时马上打开信息看要不闪动效具也没有用了所以信息的得到和显示是不同步的这时我们很自然的想到了缓存对没错技需要建一个JContext类型的缓存数据表啪j鞠H毗t鞠吣TW这样当获得新获得信息的时候我们就将信且加入Carray中TemDSaveAddJContextTempSave扮填了一个缓存器的角色而男一个问题也有了着落需要闪烁图标的用户就是TempSave里的全部消息的FromUser怎样实现有很多的用户名可能在屑一时刻闪烁同时可由用户决定哪个停止l烁当他想看哪爪信且的时候呢这让最们很容易地想起了线程我们可以在客户端刚刚获得信息的时候打开一个线程在这个线程中是让列表框的某一项不停的闪烁具体开发代码如下ifcontextCommand一0哪转发数据发出声音船用户驵列匡里掘田胃建里嘲壁j啊岫rdcselItn0-碍的显示信息量为垒H目眦Ut示遮到的内窖sleepS00擀半秒retum001L好了我们把线程中闪烁图标的代码写好了下一步就是在上面介绍过的Oneceive函数里添加上启动线程的代码ddlentScketOReceiveintnErrorCodertrlnOIPIP地幢UITuPtrt0端口Xntextntext发

    采的信息内窖H筻j盖来的信息腱蟠耽nIxt0理c悝帕mIP各种信息的蛀理90-丹重臻可以自动的产生了但我们的任务还没有完我们得让自动闪动的线程能够自动地终止掉所以还需要一个线程的指针集合用户每双击一次的时候我们就从指针集舍中找到这个线程指针终止这个线程这样就可以实现了自动的闪动和停止闪动了技们定义一个线程指针集合哆同时在OnReceve里藤加fctextCcmanrgargn岫r由read岫arg1istm_LYstCtrla叼selItem靶1ItemCwinThrEadmpThreadAfxBegnThreadsereadFuncargmJessageThredsAddm_pThread最后我们再把上面提到的缓存TemSave电加到这个函数里大功就告成了v01d亡1ieraocketOtIReceiveilitnErrorCodefCStrselItemt0f0rinti日rLL1sttr1鼬tIt圈血ut1ifmJ_is1-Ir1啦虹牲呻戡ta0雹mBaIselxb咄r日出rgzrgnrdThreadgargIistm_L1stctrlarg5eIItemselItemcwinThreadm_pThreadsrdThreadFumarg线程删除的方法是1宦定m_pThread是一个线程擗fDORDexitcode0exitcode好了如果你掌握了这种方法系统消息的IN动群的消且闪动以及其他任何闪动效果就都一一迎刃而解了星集工作室也开发了一个专门处理JContext结掏的类同时也开发了客户端和服务器端的相应Socket你可以lmttpIIIOIlCON0恤1cha吁枷0鲴tcna眦l蠲rar]_载这个类代码它可以让你省去很多时间去制作寐烦的数据传输与接收功能你耍作的只是在指定得函数里写上适当的视图变化就可以了同时囤6ShitCheter聊天器星集工怍室也利用这个类库制作了一个tChat日聊天器如图6这个软件包括了客户端和服务器端你可以到htwwwm嘲00粥fcha也rWI10adsh仕cH协rar下载AfxSeginThread后记-一一可以发现TempSave的第几个信息就是线程的第几个信息因为在葫孵蚺-础甄E的同时磷川a两个是一致的所以当用户双击某一个用户的时候我们耍删除指定的TemlgtSave的同时找到和TempSave删除的指定的ID一致的那个线程终止它就可以了投稿信箱tougaocsdnnet我想强调一个东西我们很多软件工程师大都很重视数据操作的编程认为数据编程编好了就万事大吉了实际上这只不过是程序的一半而已我们知道MEC里提倡的是文档视图技术换句话说我们大都重视在了文档上实际上视图的制作也是相当复杂的而且往往被工程师认为是不重要的东西而经常地忽视有的工程师会说皮肤的东西要交给美工我不会做实际上菝觉得他忽视了视图部分的意义视图实际上也是程序的一个部分这个部分也应该是我们非常重视的一个编程工作这次ShitC_hater的编程让我觉得视图的编程真的也很有难度也很值得我们探讨如果你有兴趣也可以做一个自己的QQ哦Cmagcmlc91

    版权声明

    本文仅代表作者观点。
    本文系作者授权发表,未经许可,不得转载。

    发表评论