一个简单的基于UDP字符界面的聊天应用程序(C/C++)

编写一个简单的基于字符界面的聊天应用程序

        基于聊天的应用程序软件通常用会采用基于UDP的应用协议来实现,因为UDP不需要建立连接,而且没有数据确认和数据重传的机制,所以实时性较高。在聊天时即使丢失一些数据也不会影响信息的交流,我们可以通过上下文语义知道对方所要表达的意思,或者根据对方的信息重新发送我们要说的话;对于TCP来说,在通讯前要经过三次握手协议建立连接,而建立连接的过程往往是比较耗费时间的,连接建立之后,我们在聊天时候可能过很长时间才说一句话,那么连接是保持呢还是先断开,等对方说话时再建立连接呢?所以在聊天中TCP面向连接、数据确认与重传的机制将会影响聊天的效率。

步骤:

1、新建一个工程,选择“Win32 Console Application”应用程序,工程名为“NetSrv”,建立一个空的工程即可。如图:


2、新建一个源文件,文件名也为“NetSrv

3、以下分为两部分来编写该应用程序:

(1)首先编写基于UDP的服务器端的应用程序

(2)接着再编写基于UDP的客户端的应用程序

第一部分:服务器端代码:

#include<Winsock2.h>
#include<stdio.h>
#include<windows.h>
void main()
{
//加载套接字库
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 1, 1 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
return;
}
if ( LOBYTE( wsaData.wVersion ) != 1 ||
        HIBYTE( wsaData.wVersion ) != 1 ) {
WSACleanup( );
return; 
}
//创建套接字,因为是基于UDP的,所以用SOCK_DGRAM.
SOCKET sockSrv=socket(AF_INET,SOCK_DGRAM,0);
//对于服务器端,接着应该进行绑定
SOCKADDR_IN addrSrv;//定义一个地址结构体的变量
addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
addrSrv.sin_family=AF_INET;//地址族
addrSrv.sin_port=htons(6000);//端口号
bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));
char recvBuf[100];//字符数组,用来接收信息
char sendBuf[100];//用来发送信息
char tempBuf[200];//用来存放中间数据
SOCKADDR_IN addrClient;//定义一个地址结构体的变量,在通讯的时候,我们需要获取和我们通讯的这一方的地址信息,这一获取是我们通过调用recvfrom来获得的,但是我们需要提供一个地址结构体的变量
int len =sizeof(SOCKADDR);
//while循环,保证通讯过程能够不断的循环下去
while(1)
{
//接收数据
recvfrom(sockSrv,recvBuf,100,0,(SOCKADDR*)&addrClient,&len);
//判断是否结束对话,q表示结束
if('q'==recvBuf[0])
{
sendto(sockSrv,"q",strlen("q")+1,0,(SOCKADDR*)&addrClient,len);
printf("Char end!\n");
break;
}
//将数据格式化到tempBuf中
sprintf(tempBuf,"%s say:%s",inet_ntoa(addrClient.sin_addr),recvBuf);//addrClient.sin_addr表示对方的IP地址,inet_ntoa将IP转换为点分十进制表示的形式,如172.0.0.1
//将输出信息设置成绿色
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY | FOREGROUND_GREEN);
printf("%s\n",tempBuf);//将数据打印输出
//将字体颜色选回默认
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
printf("Please input data:\n");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY | FOREGROUND_GREEN);
gets(sendBuf);//从键盘输入数据
sendto(sockSrv,sendBuf,strlen(sendBuf)+1,0,(SOCKADDR*)&addrClient,len);//发送数据
}
//当循环结束的时候,关闭套接字
closesocket(sockSrv);
//终止对套接字的使用
WSACleanup();
}


注意,这里需要为程序添加一个”ws2_32.lib”的连接库文件,具体操作“project-settings-link”,然后在“Object/library modules”里添加就行了,如下图:


第二部分:客户端代码的编写:

点击“资源视图(FileView)”,增加一个新的工程到工作区,同样选择“win32 Console Application,工程名为“NetClient”,同样选择“An empty project”。如图:


然后在工程“NetClient”下新建一个源文件,文件名为“NetClient”,,同样也要为该文件加入“ws2_32.lib”链接库文件,操作同上。(这里不要选错工程名)

写入如下代码:

#include<Winsock2.h>
#include<stdio.h>
void main()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 1, 1 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
return;
}
if ( LOBYTE( wsaData.wVersion ) != 1 ||
        HIBYTE( wsaData.wVersion ) != 1 ) {
WSACleanup( );
return; 
}
//创建套接字
SOCKET sockClient=socket(AF_INET,SOCK_DGRAM,0);
//基于UDP的客户端来说,它不需要去绑定,但是要设置信息将要发送到对方机器的地址信息,也就是服务器端的地址信息
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(6000);//接收端口号
   
char recvBuf[100];//接收数据
char sendBuf[100];//发送数据
char tempBuf[200];//临时数据存储
int len=sizeof(SOCKADDR);//用于返回接收数据的地址结构的长度,必须先经过初始化
while(1)
{
printf("please input data:\n");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY | FOREGROUND_RED |FOREGROUND_GREEN);
gets(sendBuf);
sendto(sockClient,sendBuf,strlen(sendBuf)+1,0,
(SOCKADDR*)&addrSrv,len);//发送数据
        recvfrom(sockClient,recvBuf,100,0,
(SOCKADDR*)&addrSrv,&len);//接收数据
//判断是否结束对话
if('q'==recvBuf[0])
{
sendto(sockClient,"q",strlen("q")+1,0,
(SOCKADDR*)&addrSrv,len);
printf("Chat end!\n");
break;
}
//将接收到的数据格式化到tempBuf中
sprintf(tempBuf,"%s say:%s",inet_ntoa(addrSrv.sin_addr),recvBuf);
//将字体设置为黄色
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY | FOREGROUND_RED |FOREGROUND_GREEN);
printf("%s\n",tempBuf);
//将字体选回默认
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
}
//关闭套接字
closesocket(sockClient);
//终止对套接字库的使用
WSACleanup();
}


运行结果:

服务器端:(服务器端必须先运行)


客户端:

相关函数详见在线msdnhttp://msdn.microsoft.com/en-us

基于UDP的简单字符界面聊天程序源码下载:http://download.csdn.net/detail/chaoyuan899/5297109

基于UDP的简单可视化界面聊天程序源代码下载:http://download.csdn.net/detail/chaoyuan899/5307517

  • 3
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值