实现简单的通讯系统

一、项目要求

系统能实现注册登录功能

然后能实现用户间相互通讯

 

二、项目思路

注册的账号保存在数据库中,这里需要搭建数据库

登录账号后选择需要聊天的对象并与其聊天,这里客户端需要用到线程,能同时读写;在线客户需要引用一个链表保存起来,每当有新客户登录时将客户与其文件描述符存储在链表中,而退出时将其从链表里剔除

三、代码

1.  .c文件

1)server.c

#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
#include <assert.h>
#include <sys/epoll.h>
#include <string.h>
#include "mysql.h"
#include "list.h"
#include "pack.h"

struct word
{
    int fd; //客户端的文件描述符
    int objfd; //客户端选择的对象客户的文件描述符
    struct word *next;
};
//成功返回监听套接字, 失败返回NULL 
int sock_init()
{
    int sockfd;
    int ret;

    sockfd = socket(AF_INET, SOCK_STREAM, 0); //创建监听套接字
    if(sockfd<0)
    {   
        perror("socket");
        return -1; 
    }   

    //设置套接字端口复用
    int opt = 1;
    setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    //设置地址族
    struct sockaddr_in  seraddr;
    int addrlen = sizeof(struct sockaddr_in);
    seraddr.sin_family = AF_INET;
    seraddr.sin_port = htons(8001);
    inet_pton(AF_INET, "127.0.0.1", &seraddr.sin_addr.s_addr);
    ret = bind(sockfd, (struct sockaddr*)&seraddr, addrlen);  //绑定地址和端口号
    if(ret<0)
    {   
        perror("bind");
        return -1; 
    }   


    ret = listen(sockfd, 10);  //通知内核监听套接字
    if(ret<0)
    {   
        perror("bind");
        return -1; 
    }   
    return sockfd;
}

//处理显示在线人数请求
int deal_show_request(int cfd,struct node *head)
{
    int ret;
    int num=0;
    struct node *p=head->next;
    struct pack pk; 
    pk.ver=1;
    pk.type=SHOW;//设置type
    pk.len=len_list(head);//求出在线人数
    ret=write(cfd,&pk,sizeof(struct pack));
    if(ret<0)
    {   
        close(cfd);
        return -1; 
    }   
    while(p!=NULL)
    {   
        ret=write(cfd,p,sizeof(struct node));//发送在线人数的链表给客户端
    if(ret<0)
        {
            close(cfd);
            return -1; 
        }
        p=p->next;
    }   
    return 0;
}
//处理通信请求
int deal_communicate_request(int sockfd,int cfd,int efd,struct node *head)
{
    int ret;
    char buff[1024];
    //读客户端发来的信息
    ret = read(sockfd,buff,1024);
    if(ret<0)
    {
        perror("read");
        //1、关闭文件描述符
        close(sockfd);
        //2、从集合中移除
        epoll_ctl(efd, EPOLL_CTL_DEL, sockfd, NULL);
        return -1;
    }
    else if(ret == 0)
    {
        //1、关闭文件描述符
        close(sockfd);
        //2、从集合中移除
        epoll_ctl(efd, EPOLL_CTL_DEL, sockfd, NULL);
        del_list(head,sockfd);
        return -1;
    }
    buff[ret] = '\0';

    //将信息写给目标客户端
    ret =  write(cfd,buff,strlen(buff));
    if(ret<0)
    {
        close(cfd);
        return -1;
    }
}

//处理注册请求
//成功:0
//失败:-1
int deal_reg_request(int  cfd,  int efd,struct node *head)
{
    int ret;
    struct  reg  r1;
    ret = read(cfd, &r1, sizeof(struct reg));
    if(ret<0)
    {
        perror("read");
        //1、关闭文件描述符
        close(cfd);
        //2、从集合中移除
        epoll_ctl(efd, EPOLL_CTL_DEL, cfd, NULL);
        return -1;
    }
    else if(ret == 0)
    {
        //1、关闭文件描述符
        close(cfd);
        //2、从集合中移除
        epoll_ctl(efd, EPOLL_CTL_DEL, cfd, NULL);
        del_list(head,cfd);
        return -1;
    }

    //去数据库中查询该用户是否存在
    //  select  *  from  user_info  where   name = ''
    char  sql[1024];
    int  rows = 0;
    MYSQL_RES  *result = NULL;
    sprintf(sql, "select *  from  user_info  where  name='%s'", r1.name);
    my_go(sql, &result);
    rows = mysql_num_rows(result);

    struct pack pk;
    pk.ver = 1;
    pk.type = REG_FAIL;
    pk.len = 0;
    if(rows == 0)//用户不存在
    {
        //在数据库中注册
        sprintf(sql, "insert  into  user_info values ('%s', '%s')", r1.name, r1.passwd);
        my_go(sql, NULL);
        //修改包头类型中的数据
        pk.type = REG_OK;
    }

    ret = write(cfd, &pk, sizeof(struct pack));
    if(ret<0)
    {
        //1、关闭文件描述符
        close(cfd);
        //2、从集合中移除
        epoll_ctl(efd, EPOLL_CTL_DEL, cfd, NULL);
    }
    return 0;
}

//处理登录请求
//成功返回0
//失败返回-1
int deal_login_request(int cfd, int efd,struct node *head)
{
    int ret;
    struct reg r2;
    struct node *p=head->next;
    ret=read(cfd,&r2,sizeof(struct reg));
    if(ret<0)
    {
        perror("read");
        close(cfd);
        epoll_ctl(efd,EPOLL_CTL_DEL,cfd,NULL);
        return -1;
    }
    else if(ret == 0)
    {
        close(cfd);
        epoll_ctl(efd,EPOLL_CTL_DEL,cfd,NULL);
        del_list(head,cfd);
        return -1;
    }
    struct pack pk;
    pk.ver = 1;
    pk.type = LOG_OK;
    pk.len = 0;
    char sql[1024];
    int rows = 0;
    MYSQL_RES *result = NULL;
    sprintf(sql,"select * from user_info where name='%s'",r2.name);
    my_go(sql,&result);
    rows = mysql_num_rows(result);
    if(rows == 0)
    {
        pk.type=LOG_FAIL_NONAME;
    }
    else
    {
        MYSQL_ROW row = NULL;
        for(int i=1;i<=rows;i++)
        {
            row = mysql_fetch_row(result);
            if(strcmp(r2.name,row[0]) == 0)
            {
                if(strcmp(r2.passwd,row[1]) == 0)
                {
                    pk.type = LOG_OK;
                    struct node *pnew = NULL;
                    //每当有客户端登录成功,添加进在线客户端链表中
                    pnew = create_node();
                    pnew->fd = cfd;
                    strcpy(pnew->name,r2.name);

                    pnew->next = head->next;
                    head->next = pnew;
                }
                else
                {
                    pk.type = LOG_FAIL_WRONGPSWD;
                }
            }
        }
    }
    ret = write(cfd,&pk,sizeof(struct pack));
    if(ret<0)
    {
        close(cfd);
        epoll_ctl(efd,EPOLL_CTL_DEL,cfd,NULL);
    }
    return 0;
}

int main()
{
    struct node *head=NULL;
    head=create_node();
    struct word *head1=NULL;
    char buff[1024];
    int sockfd;
    int ret, count;
    int cfd, efd;
    struct sockaddr_in cliaddr;
    int addrlen=sizeof(struct sockaddr_in);
    int port;
    char ip[64];
    // 连接数据库
    ret = my_init();
    if(ret<0)
    {
        return -1;
    }


    efd = epoll_create(100); //创建集合空间
    if(efd<0)
    {
        perror("epoll_create");
        return -1;
    }

    sockfd = sock_init();
    if(sockfd < 0)
    {
        return -1;
    }

    struct  epoll_event  ev;
    struct  epoll_event  evs[10];
    ev.events = EPOLLIN;
    ev.data.fd = sockfd;
    epoll_ctl(efd, EPOLL_CTL_ADD, sockfd, &ev); //管理集合空间中的描述符

    while(1)
    {
        printf("服务器等待响应...\n");
        count = epoll_wait(efd, evs, 10, -1);  //监听集合中的文件描述符
        if(count < 0)
        {
            perror("epoll_wait");
            break;
        }

        for(int i=0; i<count; i++)
        {
            int  temp =  evs[i].data.fd;
            if(temp == sockfd)// 有客户端请求连接
            {
                //1、接收客户端
                cfd = accept(sockfd, (struct sockaddr*)&cliaddr, &addrlen);
                port=ntohs(cliaddr.sin_port);
                inet_ntop(AF_INET,&cliaddr.sin_addr.s_addr,ip,64);
                printf("客户端[%s:%d]连接成功!\n",ip,port);
                if(cfd<0)
                {
                    perror("accept");
                    continue;
                }
                //2、cfd 加入efd关联的集合中
                ev.data.fd = cfd;
                epoll_ctl(efd, EPOLL_CTL_ADD, cfd, &ev);
            }
            else   //已经连接过来的客户端发来数据
            {
                struct pack  pk;
                ret = read(temp, &pk, sizeof(struct pack));
                if(ret<0)
                {
                    perror("read");
                    //1、关闭文件描述符
                    close(temp);
                    //2、从集合中移除
                    epoll_ctl(efd, EPOLL_CTL_DEL, temp, NULL);
                    continue;
                }
                else if(ret == 0)
                {
                    printf("客户端断开连接!\n");
                    //1、关闭文件描述符
                    close(temp);
                    //2、从集合中移除
                    epoll_ctl(efd, EPOLL_CTL_DEL, temp, NULL);
                    //3、从在线链表中移除退出登录的客户端
                    if(head->next==NULL)
                    {
                        break;
                    }
                    else
                    {
                        del_list(head,temp);
                        break;
                    }
                }

                if(pk.type  == REG)//注册请求
                {
                    deal_reg_request(temp,  efd,head);
                }
                else if (pk.type == LOG)  //登录请求
                {
                    deal_login_request(temp, efd,head);
                }
                else if (pk.type == SHOW)  //显示在线客户端的请求
                {
                    deal_show_request(temp,head);
                }
                else if (pk.type == COM) //读取目标客户
                {
                    char objuser[32];
                    int cfd;
                    ret=read(temp,objuser,32); //读取目标客户的用户名
                    objuser[ret]='\0';
                    //printf("%s\n",objuser);
                    if(ret<0)
                    {
                        perror("read");
                        close(temp);
                        epoll_ctl(efd, EPOLL_CTL_DEL, temp, NULL);
                        continue;
                    }
                    struct node *t=head->next;
                    struct word *pnew=NULL;
                    while(t!=NULL)
                    {
                        if(strcmp(t->name,objuser)==0) //判断是否有目标客户
                        {
                            cfd=t->fd;

                            //将请求方和目标客户存储在word链表中
                            pnew=create_node();
                            pnew->fd=temp;
                            pnew->objfd=cfd;
                            pnew->next=head1;
                            head1=pnew;
                            break;
                        }
                        t=t->next;
                    }
                }
                else if (pk.type == CATE) //发送消息请求
                {
                    struct word *d=head1;
                    while(d!=NULL)
                    {
                        if(d->fd == temp)
                        {
                            deal_communicate_request(temp,d->objfd,efd,head);
                            break;
                        }
                        d=d->next;
                    }
                }
            }
        }
    }
    //数据库断开连接
    my_close();
    close(cfd);
    close(sockfd);
    head=free_list(head);
    return 0;
}

2)client.c

#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <stdlib.h>
#include <assert.h>
#include <pthread.h>
#include "pack.h"
#include "list.h"

struct pk
{
    int sockfd;
    char objuser[32];
};
void hangle(int sig)
{
    printf("rev  sig: %d\n", sig);
}

//注册请求
void  reg_request(int sockfd)
{
    int  ret;
    struct reg   r1; 
    printf("请输入用户名:");
    scanf("%s", r1.name);
    while(getchar()!='\n');
    printf("请输入密码:");
    scanf("%s", r1.passwd);
    while(getchar()!='\n');

    struct pack  *p = NULL;
    p = (struct pack*)malloc(sizeof(struct pack)+sizeof(struct reg));
    assert(p!=NULL);

    p->ver = 1;
    p->type = REG; //这只type
    p->len = sizeof(struct reg);
    memcpy(p->data, &r1, sizeof(struct reg));

    ret = write(sockfd, p, sizeof(struct pack)+sizeof(struct reg)); //将包发送给服务端
    if(ret<0)
    {   
        perror("write");
        close(sockfd);
        exit(-1);
    }   

    ret = read(sockfd, p, sizeof(struct pack)); //读取服务端发来的type
    if(ret<0)
    {   
        perror("read");
        close(sockfd);
        exit(-1);
    }   
    else if(ret == 0)
    {   
        printf("服务器断开连接!\n");
        close(sockfd);
        exit(-1);
    }   
    if(p->type == REG_OK)
    {   
        printf("注册成功!\n");
    }   
    else if(p->type == REG_FAIL)
    {   
        printf("注册失败,用户名已经存在!\n");
    }   
    else
    {   
        printf("数据异常!\n");
    }   
    free(p);
    return ;
}

//登录请求
int login_request(int sockfd)
{
    char name[32];
    char passwd[32];
    struct reg  r2; 
    int ret;
    printf("用户名:\n");
    scanf("%s",r2.name);
    while(getchar()!='\n');
    printf("密 码:\n");
    scanf("%s",r2.passwd);
    while(getchar()!='\n');

    struct pack *p=NULL;
    p=(struct pack *)malloc(sizeof(struct pack)+sizeof(struct reg));
    assert(p!=NULL);
    p->ver=1;
    p->type=LOG; //设置type
    p->len=sizeof(struct reg);
    memcpy(p->data,&r2,sizeof(struct reg));

    ret = write(sockfd, p, sizeof(struct pack)+sizeof(struct reg));
    if(ret<0)
    {
        perror("write");
        close(sockfd);
        exit(-1);
    }

    ret = read(sockfd, p, sizeof(struct pack));
    if(ret<0)
    {
        perror("read");
        close(sockfd);
        exit(-1);
    }
    else if(ret == 0)
    {
        printf("服务器断开连接!\n");
        close(sockfd);
        exit(-1);
    }
    if(p->type == LOG_OK)
    {
        printf("登录成功!\n");
        return 1;
    }
    else if(p->type == LOG_FAIL_NONAME)
    {
        printf("登录失败,用户名不存在!\n");
    }
    else if(p->type == LOG_FAIL_WRONGPSWD)
    {
        printf("登录失败,密码错误!\n");
    }
    else
    {
        printf("数据异常!\n");
    }
    free(p);
    return 0;
}

//显示在线客户请求
void show_request(int sockfd)
{
    int ret;
    int num;
    struct node *head = NULL;
    struct pack pk,pk1;
    pk.ver = 1;
    pk.type = SHOW;
    pk.len = 0;
    ret = write(sockfd,&pk,sizeof(struct pack));
    if(ret<0)
    {
        exit(-1);
    }
    ret = read(sockfd,&pk1,sizeof(struct pack)); //读取服务器发送的含有在线人数的包
    if(ret<0)
    {
        close(sockfd);
        exit(-1);
    }
    for(int i=0;i<pk1.len;i++)
    {
        struct node *pnew = NULL;
        pnew=create_node();
        ret = read(sockfd,pnew,sizeof(struct node)); //读取在线客户链表
        if(ret<0)
        {
            perror("read");
            close(sockfd);
            exit(-1);
        }
        else if(ret == 0)
        {
            printf("服务器断开连接!\n");
            close(sockfd);
            exit(-1);
        }
        pnew->next = head;
        head = pnew;
    }
    struct node *p = head;
    printf("当前在线用户:\n");
    while(p!=NULL)
    {
        printf("%s\n",p->name);
        p=p->next;
    }
    return;
}
//线程1:写信息
void *pthread1(void *argv)
{
    int sockfd = *((int *)argv);
    char buff[1024];
    int ret;
    while(1)
    {
        int ret;
        struct pack pk;
        scanf("%s",buff);
        pk.ver = 1;
        pk.type = CATE;
        pk.len = 0;
        ret = write(sockfd,&pk,sizeof(struct pack));
        if(ret<0)
        {
            exit(-1);
        }
        while(getchar()!='\n');
        ret = write(sockfd,buff,strlen(buff));
        if(ret<0)
        {
            perror("write");
            exit(-1);
        }
    }
}

//线程2:读信息
void *pthread2(void *argv)
{
    int ret;
    struct pk temp = *((struct pk *)argv);
    char buff[1024];
    while(1)
    {
        int ret;
        ret = read(temp.sockfd,buff,1024);
        if(ret<0)
        {
            perror("read");
            close(temp.sockfd);
            exit(-1);
        }
        else if(ret == 0)
        {
            printf("服务器断开连接!\n");
            close(temp.sockfd);
            exit(-1);
        }
        buff[ret] = '\0';
        printf("[%s]:%s\n",temp.objuser,buff);
    }
}
//将选择的目标客户发送给服务器
void communicate_request(int sockfd,char objuser[])
{
    int ret;
    int cfd;
    struct pack pk;
    pk.ver = 1;
    pk.type = COM;
    pk.len = 0;
    ret = write(sockfd,&pk,sizeof(struct pack));
    if(ret<0)
    {
        exit(-1);
    }


    ret = write(sockfd,objuser,strlen(objuser));
    if(ret<0)
    {
        exit(-1);
    }
    sleep(1);

    return;
}
//将聊天信息发送给服务器
void communicate(int sockfd,char objuser[])
{
    struct pk pp;
    pp.sockfd=sockfd;
    strcpy(pp.objuser,objuser);
    pthread_t pth1,pth2;
    printf("输入聊天信息:\n");
    //加入线程,能够边读边写
    if(0!=pthread_create(&pth1,NULL,pthread1,&sockfd))
    {
        perror("pthread_create");
        exit(-1);
    }
    if(0!=pthread_create(&pth2,NULL,pthread2,&pp))
    {
        perror("pthread_create");
        exit(-1);
    }
    pthread_join(pth1,NULL);
    pthread_join(pth2,NULL);
}

int main()
{
    signal(SIGPIPE, hangle); //遇到SIGPIPE信号执行hangle函数
    int sockfd;
    int ret;
    char objuser[32];

    sockfd = socket(AF_INET, SOCK_STREAM, 0); //创建监听套接字
    if(sockfd<0)
    {
        perror("socket");
        return -1;
    }


    //设置地址族
    struct sockaddr_in  seraddr;
    int addrlen = sizeof(struct sockaddr_in);
    seraddr.sin_family = AF_INET;
    seraddr.sin_port = htons(8001);
    inet_pton(AF_INET, "127.0.0.1", &seraddr.sin_addr.s_addr);
    ret = connect(sockfd, (struct sockaddr*)&seraddr, addrlen);  //请求连接
    if(ret<0)
    {
        perror("connect");
        return -1;
    }

    int flag=1,sel;
    int flag1=1,sel1;
    while(flag)
    {
        printf("1、注册\n");
        printf("2、登录\n");
        printf("0、退出\n");
        printf("请输入你的选择:");
        scanf("%d", &sel);
        while(getchar()!='\n');

        switch(sel)
        {
            case 1://注册
                reg_request(sockfd);
                break;
            case 2://登录
                ret=login_request(sockfd);
                if(ret == 1)
                {
                    while(flag1)
                    {
                        printf("1、显示在线用户\n");
                        printf("2、选择在线用户聊天\n");
                        printf("0、返回上一层\n");
                        printf("请输入你的选择:");
                        scanf("%d",&sel1);
                        while(getchar()!='\n');
                        switch(sel1)
                        {
                            case 1: //显示在线用户
                                show_request(sockfd);
                                break;
                            case 2: //选择在线用户连天
                                printf("请输入选择聊天的对象名称:");
                                scanf("%s",objuser);
                                while(getchar()!='\n');
                                communicate_request(sockfd,objuser);
                                sleep(2);
                                communicate(sockfd,objuser);
                                break;
                            case 0:
                                flag1=0;
                                break;
                            default:
                                printf("输入有误,请重新选择!\n");
                                break;
                        }
                    }
                }
                break;
            case  0:
                flag = 0;
                break;
            default:
                printf("输入有误,请重新选择!\n");
                break;
        }
    }
    close(sockfd);

    return 0;
}

3)list.c

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "list.h"

//创建结点
struct node *create_node()
{
    struct node *pnew = NULL;
    pnew=(struct node *)malloc(sizeof(struct node));
    assert(pnew!=NULL);
    pnew->next = NULL;
    return pnew;
}

static struct node *search_list(struct node *head,int sockfd)
{
    struct node *p = head->next;
    while(p!=NULL)
    {   
        if(p->fd == sockfd)
        {
            return p;
        }
        p = p->next;
    }   
}
//求链表长度
int len_list(struct node *head)
{
    int len=0;
    struct node *p=head->next;
    while(p!=NULL)
    {   
        len++;
        p=p->next;
    }   
    return len;
}
//删除结点
void del_list(struct node *head,int sockfd)
{
    struct node *pdel = search_list(head,sockfd);
    struct node *p = head;
    while(p->next!=pdel)
    {   
        p=p->next;
    }   
    p->next=pdel->next;
    free(pdel);
}
//释放链表
struct node *free_list(struct node *head)
{
    struct node *pdel=NULL;
    while(head!=NULL)
    {   
        pdel=head;
        head=head->next;
        free(pdel);
    }   
    return head;
}

4)mysql.c

#include "./mysql.h"
#include <stdio.h>


#define  HOST  "localhost"
#define  USER  "halfgod"
#define  PASSWD  "1"
#define  DB      "userinfo"



static  MYSQL  mysql;




//成功返回0, 失败返回-1
int my_init()
{
    //初始化句柄
    if(NULL == mysql_init(&mysql))
    {   
        printf("%s\n", mysql_error(&mysql));
        return -1; 
    }   

    //连接数据库
    if(NULL == mysql_real_connect(&mysql, HOST, USER, PASSWD, DB, 0, NULL, 0)) 
    {   
        printf("%s\n", mysql_error(&mysql));
        return -1; 
    }   
    mysql_set_character_set(&mysql, "utf8");
    return 0;
}


int my_go(char *sql, MYSQL_RES **pres)
{
    if(0!= mysql_query(&mysql, sql))
    {   
        printf("%s\n", mysql_error(&mysql));
        return -1; 
    }   

    MYSQL_RES  *result = NULL;
    result = mysql_store_result(&mysql);
    if(result != NULL)
    {   
        if(pres != NULL)
        {
            *pres = result;
        }
    }   
    return 0;
}


void my_close()
{
    mysql_close(&mysql);
}

2.  .h文件

1)pack.h

#pragma  once


//表示包头信息
struct   pack
{
    unsigned  char  ver;
    unsigned  char  type;
    unsigned  int   len;
    char data[0];
};


//表示用户注册基本信息
struct  reg 
{
    char name[32];
    char passwd[32];
};


#define  REG        11
#define  REG_OK     12
#define  REG_FAIL   13
#define  LOG        1
#define  LOG_OK     2
#define  LOG_FAIL_NONAME   3
#define  LOG_FAIL_WRONGPSWD   4
#define  SHOW       5
#define  COM        6
#define  CATE       7

2)其他 .h文件

3.Makefile文件

target: ser  cli 

serobj = mysql.o  server.o  list.o

cliobj = client.o  list.o

ser:$(serobj)
    gcc $^  -o  $@  -lmysqlclient


cli:$(cliobj)
    gcc  $^  -o   $@  -lpthread


%.o : %.c 
    gcc  $^ -o $@  -c

clean:
    rm  -rf  *.o   cli  ser

【原 书 名】 Communication Systems Fourth Edition 【原出版社】 John Wiley 【作  者】(加)Simon Haykin [同作者作品] [作译者介绍] 【译  者】 宋铁成[同译者作品] 徐平平 徐志勇 等 【丛 书 名】 国外电子与通信教材系列 【出 版 社】 电子工业出版社 【书 号】 7505382543 【出版日期】 2003 年10月 【开 本】 16开 【页 码】 719 【版 次】1-1 【内容简介】本书对通信系统的基础理论和关键环节进行了深入分析,力图让学生在讨论中领会通信的精髓。全书首先给出通信系统的梗概及需要研究的关键技术,接着分章详细讨论了随机过程、连续波调制、脉冲调制、基带脉冲传输、信号空间分析、带通数据传输、扩频调制、多用户无线通信、信息论基础以及差错控制编码等。各章都附有大量习题,便于学生实践掌握。书中还给出了很有价值的附录,包括概率论、信号和系统描述、贝叶斯函数、超几何分布函数汇总、密码学方面的介绍以及一些有用的表格等。全书强调通信理论的统计基础,并给出了用MATLAB模拟的8个计算机实验,这些实验几乎覆盖了各章节的主要内容,形成了独特的通信理论“软件实验室”。 【编辑推荐】随着微电子技术、计算机技术、激光技术、卫星与光纤等相关信息技术的发展,特别是计算机与通信的有机结合,现代通信正经历着一场变革。在这场变革中,各种新技术、新手段、新业务、新系统层出不穷,现代通信的内容也日趋丰富。在通信新技术不断产生,新需求逐步扩展的背景下,建立在多网互连互通、多个系统集成、多种技术综合应用基础上的一体化通信、全球个人通信迅速发展,这就要求通信技术工作者和通信工程等专业的学生不仅深入学习本专业的典型通信系统,还要全面学习和了解目前广泛应用的各种现代通信系统,以全面、系统地了解现代通信的目的。本书正是为了实现这一目的而编写的。 作者介绍:Simon Haykin是国际电子电气工程界的著名学者,加拿大皇家学会院士,IEEE会士,于1953年获得英国伯明翰大学博士学位,现任加拿大麦克马斯特大学教授,在该校创办了通信研究实验室并长期担任主任。他曾经获得IEEE McNaughton奖章,在神经网络、通信、自适应滤波器等领域成果颇丰,著有多种标准教材。 目录 第1章 随机过程 1.1 简介 1.2 随机过程的数字定义 1.3 平稳过程 1.4 均值、相关函数和协方差函数 1.5 遍历过程 1.6 随机过程通过一个线性时不变滤波器 1.7 功率谱密度 1.8 高斯过程 1.9 噪声 1.10 窄带噪声 1.11 基于同相和正交分量的窄带噪声表示法 1.12 基于包络和相位分量的窄带噪声表示法 1.13 正弦信号加窄带噪声 1.14 计算机实验:平衰落信道 1.15 总结与讨论 注释与参考 习题 第2章 连续波调制 第3章 脉冲调制 第4章 基带脉冲传输 第5章 信号空间分析 第6章 通带数据传输 第7章 扩频调制 第8章 多用户无线通信 第9章 信息论基础 第10章 差错控制编码 附录1 概率论 附录2 信号与系统简述 附录3 贝塞尔函数 附录4 汇合型超几何函数 附录5 密码学 附录6 表格 术语表 参考文献 索引
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值