C语言利用UDP实现群聊聊天室的示例代码

目录
  • 1.UDP群聊的功能
  • 2.写项目的流程
  • 3.流程图
  • 4.代码实现
    • 4.1头文件
    • 4.2函数
    • 4.3服务器
    • 4.4客户端

1.UDP群聊的功能

有新用户登录,其他在线的用户可以收到登录信息

有用户群聊,其他在线的用户可以收到群聊信息

有用户退出,其他在线的用户可以收到退出信息

服务器可以发送系统信息

2.写项目的流程

画流程图

根据流程图写框架

一个功能一个功能实现

3.流程图

4.代码实现

4.1头文件

#ifndef __MYHEAD_H__
#define __MYHEAD_H__

#include <head.h>
#define N 512
//聊天操作用的结构体
typedef struct _MSG{
    char ch;//用来'l'聊天,'q'退出,'登录d'
    char name[128];//存名字
    char text[N];//存聊天内容
}msg_t;
//用来保存每个用户信息的结构体
typedef struct _Jilu{
    struct sockaddr_in addr;
    struct _Jilu *next;
}jilu_t;

int create_head(jilu_t **head);
int input_addr(jilu_t *head,msg_t msg,int sockfd,struct sockaddr_in clientaddr,socklen_t clientaddr_len);
int wx_addr(jilu_t *head,msg_t msg,int sockfd,struct sockaddr_in clientaddr,socklen_t clientaddr_len);
int tuichu_addr(jilu_t *head,msg_t msg,int sockfd,struct sockaddr_in clientaddr,socklen_t clientaddr_len);
#endif

4.2函数

#include "myhead.h"

//创建一个单链表头
int create_head(jilu_t **head)
{
    if(head==NULL){
        printf("传送错误,请检查\n");
        return -1;
    }

    (*head)=(jilu_t *)malloc(sizeof(jilu_t));
    (*head)->next=NULL;

    return 0;

}

//记录登录的用户的信息
int input_addr(jilu_t *head,msg_t msg,int sockfd,struct sockaddr_in clientaddr,socklen_t clientaddr_len)
{
    if(head==NULL){
        printf("传送错误,请检查\n");
        return -1;
    }

    //将这个用户登录的信息发送给所有人
    snprintf(msg.text,sizeof(msg.text),"[%s]%s",msg.name,"登录了");
    //这个用来记录头的地址
    jilu_t *jilu_head=head;

    while(jilu_head->next!=NULL){
        jilu_head=jilu_head->next;
        if(sendto(sockfd,&msg,sizeof(msg),0,(struct sockaddr*)&jilu_head->addr,clientaddr_len)==-1){
            ERRLOG("将用户登录信息发给所有人失败");
        }
    }
    //创建一个新的节点,并且把新的用户信息放入新得单列表
    jilu_t *temp=NULL;
    create_head(&temp);
    temp->addr=clientaddr;

    //用头插法将用户信息插入链表
    temp->next=head->next;
    head->next=temp;

    return 0;
}

int wx_addr(jilu_t *head,msg_t msg,int sockfd,struct sockaddr_in clientaddr,socklen_t clientaddr_len)
{

    if(head==NULL){
        printf("传送错误,请检查\n");
        return -1;
    }

    //将接受到的消息发给除了自己以外的所有人
    jilu_t *jilu_head=head;
    while(jilu_head->next!=NULL){
        jilu_head=jilu_head->next;
        if(0!=memcmp(&(jilu_head->addr),&clientaddr,sizeof(clientaddr))){
            if(sendto(sockfd,&msg,sizeof(msg),0,(struct sockaddr*)&jilu_head->addr,clientaddr_len)==-1){
                ERRLOG("将聊天内容发给所有人失败");
            }
        }
    }

    return 0;
}
int tuichu_addr(jilu_t *head,msg_t msg,int sockfd,struct sockaddr_in clientaddr,socklen_t clientaddr_len)
{
    if(head==NULL){
        printf("传送错误,请检查\n");
        return -1;
    }

    snprintf(msg.text,sizeof(msg.text),"%s%s",msg.name,"退出登录");

    jilu_t *jilu_head=head;
    jilu_t *pdel=NULL;

    while(jilu_head->next!=NULL){

        if(0==memcmp(&(jilu_head->next->addr),&clientaddr,sizeof(clientaddr))){
            pdel=jilu_head->next;
            jilu_head->next=pdel->next;
            free(pdel);
            pdel=NULL;
        }else{
            jilu_head=jilu_head->next;
            if(sendto(sockfd,&msg,sizeof(msg),0,(struct sockaddr*)&jilu_head->addr,clientaddr_len)==-1){
                ERRLOG("将这个退出的信息告诉所有人失败");
            }
        }
    }

    return 0;
}

4.3服务器

#include "myhead.h"

int main(int argc, char const *argv[])
{
    int sockfd=0;
    pid_t pid=0;
    msg_t msg;//用来进行各种操作
    msg_t faso;//用来发系统消息

    if((sockfd=socket(AF_INET,SOCK_DGRAM,0))==-1){
        ERRLOG("创建服务器套接字失败");
    }

    //将网络信息结构体放入服务器中
    struct sockaddr_in serveraddr;
    memset(&serveraddr,0,sizeof(serveraddr));
    serveraddr.sin_family=AF_INET;
    serveraddr.sin_port=htons(atoi(argv[2]));
    serveraddr.sin_addr.s_addr=inet_addr(argv[1]);
    socklen_t serveraddr_len=sizeof(serveraddr);

    //将套接字与网络信息结构体绑定
    if(bind(sockfd,(struct sockaddr*)&serveraddr,serveraddr_len)==-1){
        ERRLOG("将套接字与网络信息结构体绑定失败");
    }

    //创建一个新的网络信息结构体来存客户端的信息
    struct sockaddr_in clientaddr;
    clientaddr.sin_family=AF_INET;
    socklen_t clientaddr_len=sizeof(clientaddr);

    //创建进程
    pid=fork();
    if(pid==-1){
        ERRLOG("服务器创建进程失败");
    }else if(pid==0){
        //创建一个单列表保存网络信息结构体
        jilu_t *head;
        create_head(&head);
        memset(&msg,0,sizeof(msg));
        while(1){
            if(recvfrom(sockfd,&msg,sizeof(msg),0,(struct sockaddr*)&clientaddr,&clientaddr_len)==-1){
                ERRLOG("接受客户端传来的信息失败");
            }
             switch(msg.ch){
                case 'd'://登录信息
                    input_addr(head,msg,sockfd,clientaddr,clientaddr_len);
                    //head->next=NULL; //这个用来测试用的
                    break;
                case 'l'://聊天信息
                    wx_addr(head,msg,sockfd,clientaddr,clientaddr_len);
                    break;
                case 'q'://退出信息
                    tuichu_addr(head,msg,sockfd,clientaddr,clientaddr_len);
                    break;
            }
        }
    }else{
        while(1){
            //发系统消息
            memset(&faso,0,sizeof(faso));
            fgets(faso.text,sizeof(faso.text),stdin);
            faso.text[strlen(faso.text)-1]='\0';
            faso.ch='l';
            sprintf(faso.name,"%s","系统消息");

            if(sendto(sockfd,&faso,sizeof(faso),0,(struct sockaddr*)&serveraddr,serveraddr_len)==-1){
                ERRLOG("发送系统消息失败");
            }
        }
    }
    return 0;
}

4.4客户端

#include "myhead.h"

int main(int argc, char const *argv[])
{

    //判断输入的对不对
    if(argc!=3){
        printf("输入格式错误,./a.out ip port\n");
        exit(EXIT_SUCCESS);
    }

    int sockfd=0;
    pid_t pid=0;
    msg_t msg;//创建发送用户的信息

    if((sockfd=socket(AF_INET,SOCK_DGRAM,0))==-1){
        ERRLOG("创建客户端套接字失败");
    }

    //将客户端网络信息结构体进行绑定
    struct sockaddr_in clientaddr;
    memset(&clientaddr,0,sizeof(clientaddr));
    clientaddr.sin_family=AF_INET;
    clientaddr.sin_port=htons(atoi(argv[2]));
    clientaddr.sin_addr.s_addr=inet_addr(argv[1]);
    socklen_t clientaddr_len=sizeof(clientaddr);

    //输入用户的姓名进行登录操作
    msg.ch='d';
    printf("请输入你用来登录的姓名");
    fgets(msg.name,sizeof(msg.name),stdin);
    msg.name[strlen(msg.name)-1]='\0';

    //给服务器发送用户已经登录上的操作
    if(sendto(sockfd,&msg,sizeof(msg),0,(struct sockaddr*)&clientaddr,clientaddr_len)==-1){
        ERRLOG("客户端给服务器发送的登录信息失败");
    }

    //创建进程,子进程用来接受,父进程用来发送
    pid=fork();
    if(pid==-1){
        ERRLOG("客户端创建进程失败");
    }else if(pid==0){
        //用来接受服务器发来的消息
        while(1){
            memset(&msg,0,sizeof(msg));
            if(recvfrom(sockfd,&msg,sizeof(msg),0,NULL,NULL)==-1){
                ERRLOG("接受服务器发来的信息错误");
            }

            printf("[%s]>>(%s)\n",msg.name,msg.text);
        }
    }else{
        //写入要判聊天的内容
        while(1){
            memset(msg.text,0,sizeof(msg.text));
            fgets(msg.text,sizeof(msg.text),stdin);
            msg.text[strlen(msg.text)-1]='\0';

            if(strncmp("quit",msg.text,5)==0){
                msg.ch='q';
            }else{
                msg.ch='l';
            }

            //将写好的内容发送给服务器
            if(sendto(sockfd,&msg,sizeof(msg),0,(struct sockaddr*)&clientaddr,clientaddr_len)==-1){
                ERRLOG("将聊天内容发送给服务器失败");
            }

            //当识别到停止的时候,关闭进程
            if(strncmp("quit",msg.text,5)==0){
                kill(pid,SIGKILL);
                close(sockfd);
                exit(EXIT_SUCCESS);
            }
        }
    }   

    return 0;
}

到此这篇关于C语言利用UDP实现群聊聊天室的示例代码的文章就介绍到这了,更多相关C语言 UDP聊天室内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C++实现简易UDP网络聊天室

    本文实例为大家分享了C++实现简易UDP网络聊天室的具体代码,供大家参考,具体内容如下 工程名:NetSrv NetSrv.cpp //服务器端 #include<Winsock2.h> #include<stdio.h> void main() { //加载套接字库 WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD(1,1); err = WSAStartup(wVersi

  • C语言实现UDP通信

    UDP通信 UDP是一种无连接的尽最大努力交付的不可靠连接,通信之前无需先建立连接,自然而然,通信之后也就无需再释放连接. 通信的套接字 UDP所采用的通信接口与前面讲过的TCP通信接口相同,只是没有建立连接这一步. socket()用来创建套接字,使用 udp 协议时,选择数据报服务 SOCK_DGRAM.sendto()用来发送数据,由于 UDP 是无连接的,每次发送数据都需要指定对端的地址(IP 和端口).recvfrom()接收数据,每次都需要传给该方法一个地址结构来存放发送端的地址.

  • C语言详解UDP通信的实现

    UDP通信 UDP服务端创建的socket是直接用来通信的套接字,没有类似TCP一样创建一个监听的socket. UDP相关函数: #include <sys/types.h>#include <sys/socket.h>注意:send和recv用于TCP; sendto和recvfrom用于UDP. ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *d

  • C++基于socket UDP网络编程实现简单聊天室功能

    本文实例为大家分享了C++基于socket UDP实现简单聊天室功能的具体代码,供大家参考,具体内容如下 0.通信步骤流程图 (左:服务器:右:客户端:) 1.服务器代码 1.1服务器类头文件(CServer_UDP.h) #pragma once #include <winsock2.h> class CServer_UDP { public: CServer_UDP(); void SendMsg(const char sendBuf[]); void RecMsg(); ~CServer

  • C语言利用UDP实现群聊聊天室的示例代码

    目录 1.UDP群聊的功能 2.写项目的流程 3.流程图 4.代码实现 4.1头文件 4.2函数 4.3服务器 4.4客户端 1.UDP群聊的功能 有新用户登录,其他在线的用户可以收到登录信息 有用户群聊,其他在线的用户可以收到群聊信息 有用户退出,其他在线的用户可以收到退出信息 服务器可以发送系统信息 2.写项目的流程 画流程图 根据流程图写框架 一个功能一个功能实现 3.流程图 4.代码实现 4.1头文件 #ifndef __MYHEAD_H__ #define __MYHEAD_H__ #

  • Java Socket聊天室编程(二)之利用socket实现单聊聊天室

    在上篇文章Java Socket聊天室编程(一)之利用socket实现聊天之消息推送中我们讲到如何使用socket让服务器和客户端之间传递消息,达到推送消息的目的,接下来我将写出如何让服务器建立客户端与客户端之间的通讯. 其实就是建立一个一对一的聊天通讯. 与上一篇实现消息推送的代码有些不同,在它上面加以修改的. 如果没有提到的方法或者类则和上一篇一模一样. 1,修改实体类(服务器端和客户端的实体类是一样的) 1,UserInfoBean 用户信息表 public class UserInfoB

  • Java实现NIO聊天室的示例代码(群聊+私聊)

    功能介绍 功能:群聊+私发+上线提醒+下线提醒+查询在线用户 文件 Utils 需要用maven导入下面两个包 <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.18</version> </dependency> <dependency> <group

  • Python实现网络聊天室的示例代码(支持多人聊天与私聊)

    实验名称: 网络聊天室 功能: i. 掌握利用Socket进行编程的技术 ii. 掌握多线程技术,保证双方可以同时发送 iii. 建立聊天工具 iv. 可以和单人聊天 v. 可以和多个人同时进行聊天 vi. 使用图形界面,显示双方的语录 vii. 程序可以在一定程度上进行错误识别 概述 实验通过聊天室可以完成单人或多人之间的聊天通信,功能的实现主要是通过Socket通信来实现.本次实验采用客户端/服务器(C/S)架构模式,通过Python语言来编写服务器端与客户端的程序.运用多线程可完成多点对多

  • Python 利用OpenCV给照片换底色的示例代码

    OpenCV的全称是:Open Source Computer Vision Library.OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,可以运行在Linux.Windows和Mac OS操作系统上.它轻量级而且高效--由一系列 C 函数和少量 C++ 类构成,同时提供了Python.Ruby.MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法.相比于PIL库来说OpenCV更加强大, 可以做更多更复杂的应用,比如人脸识别等. 1. 读入并显示图片 im

  • C# 利用Selenium实现浏览器自动化操作的示例代码

    概述 Selenium是一款免费的分布式的自动化测试工具,支持多种开发语言,无论是C. java.ruby.python.或是C# ,你都可以通过selenium完成自动化测试.本文以一个简单的小例子,简述C# 利用Selenium进行浏览器的模拟操作,仅供学习分享使用,如有不足之处,还请指正. 涉及知识点 要实现本例的功能,除了要掌握Html ,JavaScript,CSS等基础知识,还涉及以下知识点: log4net:主要用于日志的记录和存储,本例采用log4net进行日志记录,便于过程跟踪

  • Python基于Socket实现简易多人聊天室的示例代码

    前言 套接字(Sockets)是双向通信信道的端点. 套接字可以在一个进程内,在同一机器上的进程之间,或者在不同主机的进程之间进行通信,主机可以是任何一台有连接互联网的机器. 套接字可以通过多种不同的通道类型实现:Unix域套接字,TCP,UDP等. 套接字库提供了处理公共传输的特定类,以及一个用于处理其余部分的通用接口. socket模块: 要创建套接字,必须使用套接字模块中的socket.socket()函数,该函数具有一般语法 s = socket.socket (socket_famil

  • SpringBoot+Netty实现简单聊天室的示例代码

    目录 一.实现 1.User类 2.SocketSession类 3.SessionGroup 4.WebSocketTextHandler类 5.WebSocketServer类 6.index.html 二.效果 一.实现 1.User类 import java.util.Objects; public class User {     public String id;     public String nickname;     public User(String id, Strin

  • ASP.NET MVC4异步聊天室的示例代码

    本文介绍了ASP.NET MVC4异步聊天室的示例代码,分享给大家,具体如下: 类图: Domain层 IChatRoom.cs using System; using System.Collections.Generic; namespace MvcAsyncChat.Domain { public interface IChatRoom { void AddMessage(string message); void AddParticipant(string name); void GetM

  • 利用js实现前后台传送Json的示例代码

    无论使用什么框架都存在着从controller向Html页面或者jsp页面传递数据的问题,最常用的方式是传递Json字符串.以前对这块知识有些模糊,现在整理一下. [Jquery基本方法] 实现传值常用的是Jquery以及内部封装的ajax.首先看一下jquery的get()和post()语法.get()方法是从服务器获得数据,其主要参数就是获得后台请求地址,以及负责处理的回调函数: $.get(URL,callback); $("button").click(function(){

随机推荐