使用CC++实现Socket聊天程序

上传人:m**** 文档编号:53625748 上传时间:2022-02-10 格式:DOC 页数:20 大小:212KB
返回 下载 相关 举报
使用CC++实现Socket聊天程序_第1页
第1页 / 共20页
使用CC++实现Socket聊天程序_第2页
第2页 / 共20页
使用CC++实现Socket聊天程序_第3页
第3页 / 共20页
亲,该文档总共20页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
使用C/C+实现Socket聊天程序Initsock.h 文件/ initsock.h 文件#include #include #include #include #pragma comment(lib, WS2_32 / 链接到 WS2_32.libclass CInitSockpublic:CInitSock(BYTE minorVer = 2, BYTE majorVer = 2/ 初始化 WS2_32.dllWSADATA wsaData 。WORD sockV ersion = MAKEWORD(minorVer, majorVer 。 if(:WSAStartup(sockV ersion, &wsaData != 0exit(0 。CInitSock(:WSACleanup( 。TCP版TCPClient.cpp 文件/ TCPClient.cpp 文件/*使用说明0.运行程序前请查看是否将 initsock.h 文件引入到项目中。1首先修改聊天对方的IP地址2请首先运行服务端TCPServer)程序,再运行客户端 TCPCIient)程序: 如配置正确服务端会收到相关连接信息。3连接成功后,需要由服务器端首先发起会话 输入消息并确认发送),客户端收到消息后才能输入消息并确认发送到服务器端。 并且双方每次只能发送一条消息。如想发送第二条消息,需要等待该方成功 接受到另一方的消息后才能继续输入消息。*/#in elude In itSock.h#in clude #include CInitSock initSock 。 / 初始化 Winsock 库int main(/ 创建套节字SOCKET s = :socket(AF_INET, SOCK_STREAM, IPPROTO_TCP 。 if(s = INV ALID_SOCKETprintf( Failed socket( n 。return 0 。/ 也可以在这里调用 bind 函数绑定一个本地地址/ 否则系统将会自动安排/ 填写远程地址信息sockaddr_in servAddr 。servAddr.sin_family = AF_INET 。servAddr.sin_port = htons(4567 。/注意,这里要填写服务器程序 。if(:connect(s, (sockaddr*&servAddr, sizeof(servAddr = -1printf( Failed connect( n 。return 0 。char buff256 。char szText256 。while(TRUE/从服务器端接收数据int nRecv = :recv(s, buff, 256, 0 。if(nRecv 0buffnRecv = 0 。printf( 接收到数据: %sn, buff 。/ 向服务器端发送数据cinszText 。szText255 = 0 。:send(s, szText, strlen(szText, 0 。/ 关闭套节字:closesocket(s 。return 0 。TCPServer.cpp 文件/ TCPServer.cpp 文件/*使用说明0.运行程序前请查看是否将 initsock.h 文件引入到项目中。1. 首先修改聊天对方的IP地址2. 请首先运行服务端TCPServer)程序,再运行客户端TCPCIient)程序: 如配置正确服务端会收到相关连接信息。3. 连接成功后,需要由服务器端首先发起会话输入消息并确认发送) ,客户端收到消息后才能输入消息并确认发送到服务器端。 并且双方每次只能发送一条消息。如想发送第二条消息,需要等待该方成功 接受到另一方的消息后才能继续输入消息。*/#incIude InitSock.h#incIude #incIude Clni tSock ini tSock。/ 初始化 Win sock 库int main(/ 创建套节字SOCKET sListen = :socket(AF_INET, SOCK_STREAM, IPPROTO_TCP 。if(sListen = INV ALID_SOCKETprintf(FaiIed socket( n 。return 0 。/ 填充 sockaddr_in结构sockaddr_in sin 。sin.sin_famiIy = AF_INET 。sin.sin_port = htons(4567 。sin.sin_addr.S_un.S_addr = INADDR_ANY 。/ 绑定这个套节字到一个本地地址if(:bind(sListen, (LPSOCKADDR&sin, sizeof(sin = SOCKET_ERRORprintf(FaiIed bind( n 。return 0 。/ 进入监听模式if(:Iisten(sListen, 2 = SOCKET_ERRORprintf(FaiIed Iisten( n 。return 0 。/ 循环接受客户的连接请求sockaddr_in remoteAddr 。int nAddrLen = sizeof(remoteAddr 。SOCKET sClient = 0 。char szText = TCP Server Demo! rn 。while(sClient=0/ 接受一个新连接sClient = :accept(sListen, (SOCKADDR*&remoteAddr, &nAddrLen if(sClient = INV ALID_SOCKETprintf(Failed accept( 。printf( 接受到一个连接: %s rn, inet_ntoa(remoteAddr.sin_addr 。 continue 。while(TRUE/ 向客户端发送数据gets(szText 。:send(sClient, szText, strlen(szText, 0 。/ 从客户端接收数据char buff256 。int nRecv = :recv(sClient, buff, 256, 0 。if(nRecv 0buffnRecv = 0 。printf( 接收到数据: %sn, buff 。/ 关闭同客户端的连接:closesocket(sClient 。/ 关闭监听套节字:closesocket(sListen 。return 0 。UDP版/ Chat.cpp : Defines the entry point for the console application./*使用说明0.运行程序前请查看是否将initsock.h文件引入到项目中。1首先修改聊天对方的IP地址2. 运行程序:如配置正确另一方会收到相关连接信息。3. 输入消息:在每次输入完欲发送的消息后,需要连续敲击两次回车。4. 本程序有诸多缺陷:对用户输入的消息不能即时回显到控制台, 需要在敲击两次回车后回显到屏幕。*/#include stdafx.h#include #include #include #include #include InitSock.husing namespace std。CInitSock initSock 。/ 初始化 Winsock 库DWORD receiverMark 。 /接收消息者线程标识符DWORD senderMark 。 /发送者线程标识符/*定义信号量*/DWORD WINAPI Receiver(LPVOID 。DWORD WINAPI Sender(LPVOID 。/ 接收数据char buff1024 。sockaddr_in addr 。int nLen = sizeof(addr 。SOCKET s 。int main(int argc, char *argv/ 创建套节字s = :socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP。/u_long iMode = 1 。/ioctlsocket(s, FIONBIO, &iMode 。if(s = INV ALID_SOCKETprintf(Failed socket( n 。return 0 。/ 填充 sockaddr_in 结构sockaddr_in sin 。sin.sin_family = AF_INET 。sin.sin_port = htons(4567 。sin.sin_addr.S_un.S_addr = INADDR_ANY 。addr.sin_family = AF_INET 。addr.sin_port = htons(4567 。/注意,这里要填写服务器程序所在机器的IP地址/ 如果你的计算机没有联网,直接使用即可addr.sin_addr.S_un.S_addr = inet_addr(192.168.1.129 。 / 绑定这个套节字到一个本地地址if(:bind(s, (LPSOCKADDR&sin, sizeof(sin = SOCKET_ERRORprintf(Failed bind( n 。 return 0 。/ 发送数据 char szText = PC 请求连接 . rn 。:sendto(s, szText, strlen(szText, 0, (sockaddr*&addr, sizeof(addr 。 CreateThread(NULL,0,Receiver,NULL,0,&receiverMark 。CreateThread(NULL,0,Sender,NULL,0,&senderMark 。 bool isContinue = true 。while(isContinueif(getche(=96 / 按 后终止程序运行 isContinue = false 。system(PAUSE 。 return 0 。/*接收者*/DWORD WINAPI Receiver(LPVOID lpParam while(1int nRecv = :recvfrom(s, buff, 1024, 0, (sockaddr*&addr, &nLen 。 if(nRecv 0buffnRecv = 0 。printf( Received data(%s : %sn, :inet_ntoa(addr.sin_addr, buff 。 return 0 。/* *发送者*/DWORD WINAPI Sender(LPVOID lpParawhile(1couttext 。text255 = 0 。couttext, 0, (sockaddr*&addr, sizeof(addr 。return 0 。本文来自 CSDN 博客,转载请标明出处:使用C/C+实现Socket聊天程序解决该问题的思路解决该问题的整体方案不外有二:1)基于TCP的Socket连接;2)基于UDP的Socket连接;但是,针对每种方案又各有很多具体的实现方法。在本次实验中,我先后开发了基于TCP连接和UDP连接的Socket聊天程序。具体实现思路如下:一) 基于TCP连接Socket聊天程序基于该连接的聊天程序需要至少具备一个服务器端Server)和一个客户端Client )。在本程序中,一个用户作为 Server端,另一个用户作为 Clie nt端。也就是说,作为Server端的用 户,需要首先启动程序,等待Clie nt端的连接请求。当TCP连接握手以后,双方方可进行交互。从Server端接收消息向Server端发送消息while(TRUE向Clie nt端发送消息从Clie nt端接收消息二) 基于UDP连接Socket聊天程序基于该连接的聊天程序不需要具备服务器端Server),每个客户端Client)既是服务器端也是客户端。也就是说每个 Clie nt端自身既可以自行接收其它用户发来的消息,也可以向其 它Clie nt端发送消息,不需要事先与其他用户进行握手连接。因为在默认情况下 Win Sock接口的recvfrom(和sen dto(都会在被调用时阻塞当前线程,也 就是说如果程序正在接受其他用户发来的数据,那么它就不能够执行发送数据的任务,反 之相同。所以为解决该问题一般有以下几种解决方案:采用Select模型、WSAAsyncSelect模型、WSAEventSelect 模型、重叠(Overlapped )模型和完成接口 Completion port)模型。在本程序中,因为我没能在短时间内学会上述方案中的任一种,因此采用了 多线程技术去实现消息接收和发送的同步问题。也就是说,在程序中创建两个线程,一个 线程负责发送消息,另一个消息负责接受消息。两个线程交替运行,从而达到同时收发消 息的目的。当然采用多线程方式解决消息收发同步问题可以移除上个程序中每个用户一次 只能发送一条消息的限制。本周开发源代码代码的功能简述使用C/C+实现Socket聊天程序:TCP版:服务器端用户和客户端用户在成功连接后,其中一方通过控制台输入消息,依次 轮流向另一方发送数据。要求,服务器端首先发起会话,并且双方每次只能发送一条消息。UDP版:任一端用户通过指定IP地址将消息发送到另一端的用户。交互双方通过控制台输 入消息向另一方发送数据。没有任何发送限制。开发的收获理解了 TCP连接和UDP连接的基本原理和工作过程。复习了关于Windows多线程及进程同步的相关知识。开发中碰到的主要困难对于TCP版:在考虑如何解决消息的收发同步问题上遇到了困难。最终使用了不佳方案:通过在服务器 端和客户端分别运行while循环并依次进行数据收发工作的方式解决数据收发同步问题。对于UDP版: 同样在考虑如何解决消息的收发同步问题上遇到了困难。但这次使用了多线程解决该问题 开发中未能解决的问题对于UDP版:为何第一次消息输入完毕敲击一次回车后,只有消息的第一个字符没能发送出去,而其它 字符却可以被成功发送出去?而且当第二次输入消息敲回车后消息就能被全部发送出去? 为何消息输入完毕后需要按两次回车键才能将消息发送到另一端?为什么输入的消息不能即时回显到发送者屏幕上?只有当敲击二次回车后用户输入的欲发 送消息才会显现出来?如何才能避免用户在输入消息的同时也能正常接收消息?也就是不至于打断用户已输入的 消息的前提下,显示接收到的消息。针对本周训练内容自己设计的案例案例的主要功能 同代码的功能简述 用到的基本知识相关Win sock编程接口; TCP连接和UDP连接基本工作原理;Win dows多线程;进程同步程序注意了哪些规范代码格式、常量的定义、函数的声明你进行了哪些测试略程序进行了哪些有效性检查略你是如何保证程序的高效率的略本文来自 CSDN 博客,转载请标明出处:北航软件学院一级实践实验报告学号: GS0821594 姓名:叶现一 第 13 周 内容训练使用C/C+实现Socket聊天程序解决该问题的思路解决该问题的整体方案不外有二:1)基于TCP的Socket连接;2)基于UDP的Socket连接;但是,针对每种方案又各有很多具体的实现方法。在本次实验中,我先后开发了基于TCP连接和UDP连接的Socket聊天程序。具体实现思路如下:一) 基于TCP连接Socket聊天程序基于该连接的聊天程序需要至少具备一个服务器端Server)和一个客户端Client )。在本程序中,一个用户作为 Server端,另一个用户作为 Clie nt端。也就是说,作为Server端的用 户,需要首先启动程序,等待Clie nt端的连接请求。当TCP连接握手以后,双方方可进行交互。注:在本程序中Server端并不是单独存在。它也可以向他的Client端发送消息。)但是本程序实现的交互功能十分简单,具有很多限制。当Client端与Server端握手以后,Server端需要首先发起会话;Clie nt端在收到消息后再回复一条消息给Server端;同样,Server端在收到消息后再回复一条消息给Client端以此类推。并且,无论是 Server端还是Client端 每次发送消息只能发送一条。造成交互操作具有诸多限制的主要原因是,我在Server端和Client端使用了一个 While循环,它们的伪代码分别如下:Clie nt 端Server 端while(TRUE从Server端接收消息向Server端发送消息while(TRUE向Clie nt端发送消息从Clie nt端接收消息二) 基于UDP连接Socket聊天程序基于该连接的聊天程序不需要具备服务器端Server),每个客户端Client)既是服务器端也是客户端。也就是说每个 Clie nt端自身既可以自行接收其它用户发来的消息,也可以向其 它Clie nt端发送消息,不需要事先与其他用户进行握手连接。因为在默认情况下 Win Sock接口的recvfrom(和sen dto(都会在被调用时阻塞当前线程,也 就是说如果程序正在接受其他用户发来的数据,那么它就不能够执行发送数据的任务,反 之相同。所以为解决该问题一般有以下几种解决方案:采用Select模型、WSAAsyncSelect模型、WSAEventSelect 模型、重叠(Overlapped )模型和完成接口 Completion port)模型。在本程序中,因为我没能在短时间内学会上述方案中的任一种,因此采用了 多线程技术去实现消息接收和发送的同步问题。也就是说,在程序中创建两个线程,一个 线程负责发送消息,另一个消息负责接受消息。两个线程交替运行,从而达到同时收发消 息的目的。当然采用多线程方式解决消息收发同步问题可以移除上个程序中每个用户一次 只能发送一条消息的限制。本周开发源代码代码的功能简述使用C/C+实现Socket聊天程序:TCP版:服务器端用户和客户端用户在成功连接后,其中一方通过控制台输入消息,依次轮流向另一方发送数据。要求,服务器端首先发起会话,并且双方每次只能发送一条消息UDP版:任一端用户通过指定IP地址将消息发送到另一端的用户。交互双方通过控制台输 入消息向另一方发送数据。没有任何发送限制。开发的收获理解了 TCP连接和UDP连接的基本原理和工作过程。复习了关于Windows多线程及进程同步的相关知识。 开发中碰到的主要困难对于TCP版:在考虑如何解决消息的收发同步问题上遇到了困难。最终使用了不佳方案:通过在服务器 端和客户端分别运行while循环并依次进行数据收发工作的方式解决数据收发同步问题。 对于UDP版:同样在考虑如何解决消息的收发同步问题上遇到了困难。但这次使用了多线程解决该问题开发中未能解决的问题对于UDP版:为何第一次消息输入完毕敲击一次回车后,只有消息的第一个字符没能发送出去,而其它 字符却可以被成功发送出去?而且当第二次输入消息敲回车后消息就能被全部发送出去? 为何消息输入完毕后需要按两次回车键才能将消息发送到另一端?为什么输入的消息不能即时回显到发送者屏幕上?只有当敲击二次回车后用户输入的欲发 送消息才会显现出来?如何才能避免用户在输入消息的同时也能正常接收消息?也就是不至于打断用户已输入的消息的前提下,显示接收到的消息。针对本周训练内容自己设计的案例案例的主要功能同代码的功能简述用到的基本知识相关Win sock编程接口; TCP连接和UDP连接基本工作原理;Win dows多线程;进程同步程序注意了哪些规范 代码格式、常量的定义、函数的声明 你进行了哪些测试略程序进行了哪些有效性检查略你是如何保证程序的高效率的略 注意:实验报告和案例源代码须在本次小组讨论会前提交 本文来自 CSDN 博客,转载请标明出处:clipboardprint?comment(lib,ws2_32.lib#includeviewplaincopyto#pragma#includeusingnamespacestd 。stringstrCurMsg=。voidrecvProc(SOCKETsockConnect。charmsgRcv100=0while(true#includeif(SOCKET_ERROR=recv(sockConnect,msgRcv,sizeof(msgRcv,0coutstrCurMsg.erase(strCurMsg.end(-7,strCurMsg.end(strCurMsg+=He said:strCurMsg+=msgRcvstrCurMsg+=nIIstrCurMsg+=input:system(clscoutWORDWSADA TAwVersionRequestedwsaDatawVersionRequestederr = WSAStartup( (ifintMAKEWORD( wVersionRequested, !=errreturnif(HIBYTE(LOBYTE(wsaData.wVersionwsaData.wVersionerr1,&wsaData!=o1|WSACleanup(returnSOCKET sockSrv=socket(AF_INET,SOCK_STREAM,IPPROTO_TCPsockaddr_in addrSrv memset(&addrSrv,0,sizeof(addrSrvaddrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY。addrSrv.sin_family=AF_INET。addrSrv.sin_port=htons(5000。if(bind(sockSrv,(sockaddr*&addrSrv,sizeof(sockaddr=SOCKET_ERROR coutbind error=SOCKET_ERROR coutlistenerror 。 while(true cout&addrClient,&len 。if(sockConnect=INV ALID_SOCKETcoutinvalidsocketendl 。return0。elsecoutrecvProc,(void*sockConnect,0,NULL 。 while(true char buf100=0 。 strCurMsg+=input: 。system(cls。cout。strCurMsg.erase(strCurMsg.end(-7,strCurMsg.end(。strCurMsg+=Yousaid:。strCurMsg+=buf。strCurMsg+= n。send(sockConnect,buf,sizeof(buf,0。 closesocket(sockConnect。WSACleanup(return#pragma0。 comment(lib,ws2_32.lib #include #include#include using namespace std 。 string strCurMsg= 。 void recvProc(SOCKET sockConnect char msgRcv100=0 。 while(true if(SOCKET_ERROR=recv(sockConnect,msgRcv,sizeof(msgRcv,0 coutstrCurMsg.erase(strCurMsg.end(-7,strCurMsg.end(strCurMsg+=He said: strCurMsg+=msgRcvstrCurMsg+=nIIstrCurMsg+=input:system(clscoutWORDWSADA TAwVersionRequestedwsaDatawVersionRequestederr = WSAStartup( (ifintMAKEWORD( wVersionRequested, err !=err1,&wsaDatareturnif(HIBYTE(LOBYTE(wsaData.wVersionWSACleanup(returnwsaData.wVersion!=1|coutSOCKETwhile(truecout&addrClient,&lenif(sockConnect=INV ALID_SOCKETIIcoutinvalidreturnsocketendl0elsecout。sockaddr_in addrSrv 。 memset(&addrSrv,0,sizeof(addrSrv。addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY。addrSrv.sin_family=AF_INET。addrSrv.sin_port=htons(5000。if(bind(sockSrv,(sockaddr*&addrSrv,sizeof(sockaddr=SOCKET_ERROR coutbind error=SOCKET_ERROR errorrecvProc,(void*sockConnect, 0,NULLwhile(truebuf100=0IIcharstrCurMsg+=input:system(clscout 。strCurMsg.erase(strCurMsg.end(-7,strCurMsg.end(strCurMsg+=You said: strCurMsg+=bufstrCurMsg+=nsend(sockConnect,buf,sizeof(buf,0closesocket(sockConnect。 WSACleanup(。return 0 。 全国计算机等级测试网,加入收藏客户端程序代码: view plaincopy to clipboardprint?#pragma comment(lib,ws2_32.lib #include #include #includeusingnamespace std。stringstrCurMsg=。voidrecvProc(SOCKETsockClient。charmsgRcv100=0while(true if(SOCKET_ERROR=recv(sockClient,msgRcv,sizeof(msgRcv,0 cout strCurMsg.erase(strCurMsg.end(-7,strCurMsg.end(。strCurMsg+=He said: 。 strCurMsg+=msgRcv。strCurMsg+= n。strCurMsg+=input: 。system(cls coutwVersionRequestedWORDWSADA TA intwVersionRequested wsaData errMAKEWORD(1, 1 err = WSAStartup( wVersionRequested, &wsaData if( err != return01。1if (LOBYTE( wsaData.wVersion!=1|HIBYTE(wsaData.wVersion !=1WSACleanup(。return1。SOCKET sockClient=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP 。 SOCKADDR_IN addrSrv 。 addrSrv.sin_addr.S_un.S_addr=inet_addr(127.0.0.1。addrSrv.sin_family=AF_INET。addrSrv.sin_port=htons(5000。if (connect(sockClient,(sockaddr*&addrSrv,sizeof(sockaddr = SOCKET_ERROR coutconnected failedn 。 return 1 。 else coutrecvProc,(void*sockClient, 0,NULL 。while(true char buf100=0 。 strCurMsg+=input: 。system(cls。cout。strCurMsg.erase(strCurMsg.end(-7,strCurMsg.end(。strCurMsg+=Yousaid:。strCurMsg+=buf。strCurMsg+= n。send(sockClient,buf,sizeof(buf,0。 closesocket(sockClient。WSACleanup(。return 0 。#pragmacomment(lib,ws2_32.lib#include#includeusingnamespacestd 。stringstrCurMsg=。voidrecvProc(SOCKETsockClient。charmsgRcv100=0while(true#includeif(SOCKET_ERROR=recv(sockClient,msgRcv,sizeof(msgRcv,0coutstrCurMsg.erase(strCurMsg.end(-7,strCurMsg.end(strCurMsg+=He said:strCurMsg+=msgRcvstrCurMsg+=nIIstrCurMsg+=input:system(clscoutWORDWSADA TAwVersionRequestedwsaDatawVersionRequestederr = WSAStartup( (ifintMAKEWORD( wVersionRequested, !=errreturnif(HIBYTE(LOBYTE(wsaData.wVersionwsaData.wVersionerr1,&wsaData!=o1|WSACleanup(returnSOCKET sockClient=socket(AF_INET,SOCK_STREAM,IPPROTO_TCPSOCKADDR_IN addrSrvaddrSrv.sin_addr.S_un.S_addr=inet_addr(127.0.0.1 addrSrv.sin_family=AF_INETaddrSrv.sin_port=htons(5000if (connect(sockClient,(sockaddr*&addrSrv,sizeof(sockaddr= SOCKET_ERROR。coutconnectedfailednreturn1。 else。coutrecvProc,(void*sockClient, 0,NULL 。 while(true char buf100=0 。 strCurMsg+=input: 。system(cls。cout。strCurMsg.erase(strCurMsg.end(-7,strCurMsg.end(。strCurMsg+=Yousaid:。strCurMsg+=buf。strCurMsg+= n。send(sockClient,buf,sizeof(buf,0。 closesocket(sockClient。WSACleanup(。return
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 办公文档 > 活动策划


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!