Linux socket聊天室

这篇具有很好参考价值的文章主要介绍了Linux socket聊天室。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

一、运行效果

1、分别编译客户端和服务端代码

2、运行

3、使用效果

 二、代码

chat.h

服务端代码 

客户端代码


一、运行效果

1、分别编译客户端和服务端代码

gcc client.c -o C -lpthread

gcc server.c -o S -lpthread

2、运行

先运行服务器端,8888为端口号

./S 8888

linux基于socket的聊天程序,# LINUX系统编程,linux,服务器,c语言,ubuntu,网络

 再运行客户端,这里创建两个客户端,端口号要和服务端的一样

./C 127.0.0.1 8888

linux基于socket的聊天程序,# LINUX系统编程,linux,服务器,c语言,ubuntu,网络

         可以看到,左下的窗口运之后,就会进入注册界面;而服务器也会提示有客户端的ip连接进来,这个时候再用右边的窗口运行客户端

linux基于socket的聊天程序,# LINUX系统编程,linux,服务器,c语言,ubuntu,网络

  进入两个主页之后,服务器就会有不同的port对应不同的客户端

3、使用效果

注册

linux基于socket的聊天程序,# LINUX系统编程,linux,服务器,c语言,ubuntu,网络

         上图可以看到,左下进行了一个注册之后就会提示注册成功,服务器上面也会有记录,下面进行登录

linux基于socket的聊天程序,# LINUX系统编程,linux,服务器,c语言,ubuntu,网络

         上图左下登录之后会提示登录成功,服务器也会有记录,而左下的窗口只要再按下回车就能进入到功能主页。下面再用左下的窗口注册一个用户2

linux基于socket的聊天程序,# LINUX系统编程,linux,服务器,c语言,ubuntu,网络

         上图可以看到,用户2注册成功登录之后,进入功能主页的左下用户也会有提示说右下用户上线了,服务器也会记录。下面左下用户进行“公聊”,只要是在线的用户都会收到信息

linux基于socket的聊天程序,# LINUX系统编程,linux,服务器,c语言,ubuntu,网络

         上图坐下用户输入数字3,选择功能之后,就会提示输入,输入之后按回车,右下用户就出现了信息(蓝色字体),如下 

linux基于socket的聊天程序,# LINUX系统编程,linux,服务器,c语言,ubuntu,网络

         上图可以看到右下用户出现了“公聊信息”蓝色字体,下面用右边的用户对左边用户进行“私聊”

linux基于socket的聊天程序,# LINUX系统编程,linux,服务器,c语言,ubuntu,网络

         输入4选择功能之后,会询问对谁发信息,接着就输入用户的名字,在输入发送的消息,按下回车就可以发送,如下

linux基于socket的聊天程序,# LINUX系统编程,linux,服务器,c语言,ubuntu,网络

        可以看到坐下的用户已经收到私聊的信息,这样就不会像公聊那样谁都能看到,输入5可以查看有谁在线,下面先把右下的用户退出

linux基于socket的聊天程序,# LINUX系统编程,linux,服务器,c语言,ubuntu,网络

上图可以看到只查询到自己用户1的名字在线,下面用第二个用户查询

linux基于socket的聊天程序,# LINUX系统编程,linux,服务器,c语言,ubuntu,网络

linux基于socket的聊天程序,# LINUX系统编程,linux,服务器,c语言,ubuntu,网络 上图可以看到,用户2上线之后,查到两个用户在线

 二、代码

chat.h

#ifndef __CHAT_H
#define __CHAT_H

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>

#define SERVER_PORT 8888
#define SIZE 32
/*最大的用户数量*/
#define MAX_USER_NUM 64
/*在线用户*/
struct ONLINE{
    int fd;                     /*描述符,-1:该用户下线   >0:该用户已经登录,对应的套接字*/
    int flage;                  /*注册标志,-1 该条目没有用户信息  1:该条目有用户注册信息*/
    char name[SIZE];            /*姓名*/
    char password[SIZE];        /*密码*/
};
/*C/S通信的结构体*/
struct protocol{
    int cmd;                    /*命令*/
    int state;                  /*存储命令返回信息*/
    char name[SIZE];            /*用户姓名*/
    char data[MAX_USER_NUM];    /*数据*/
};
/*cmd(命令类型)*/
#define BROADCAST       0X00000001          /*广播数据*/
#define PRIVATE         0X00000002          /*私聊*/
#define REGISTE         0X00000004          /*注册*/
#define LOGIN           0X00000008          /*登录*/
#define ONLINEUSER      0X00000010          /*显示在线用户*/
#define LOGOUT          0X00000020          /*退出*/

/*return code(服务器处理结果返回值)*/
#define OP_OK               0X80000000      /*操作成功*/
#define ONLINEUSER_OK       0X80000001      /*显示在线用户,未结束*/
#define ONLINEUSER_OVER     0X88888888      /*显示在线用户,已经发送完毕*/
#define NAME_EXIST          0X80000003      /*注册信息,用户名已经存在*/
#define NAME_PWD_NMATCH     0X80000004      /*登录时,输入的用户名密码不对 */
#define USER_LOGED          0X80000005      /*登录时,提示该用户已经在线*/
#define USER_NOT_REGIST     0X80000006      /*登录时,提示用户没有注册*/

#endif


服务端代码 

#include "chat.h"
#include <stdio.h>
#include <unistd.h>

struct ONLINE online[MAX_USER_NUM];
/*将用户注册信息存储到在线用户列表中*/
int add_user(int socket_fd, struct protocol *msg) {
  int i, index = -1;
  char buf[128] = {0};
  /*历在线用户列表数组,从第一个开始找没有被占用的位置,将用户的注册信息存储到该位置*/
  for (i = 0; i < MAX_USER_NUM; i++) { /*判断当前位置是否已经被占用*/
    if (online[i].flage == -1) {       /* 标记该位置为已占用*/
      online[i].flage = 1;
      strcpy(online[i].name, msg->name);
      strcpy(online[i].password, msg->data);
      printf("regist %s to %d \n", msg->name, i);
      index = i;
      return index; /* 返回存储用户信息的位置*/
    }
  }
  return index;
}
/*从在线列表中删除
 *在聊天室程序中将在线用户列表中指定位置的客户端信息删除,
 *并向所有在线客户端发送某用户下线通知
 */
void del_user_online(int index) {
  int i;
  char buf[128] = {0};
  /*通过比较传入的 index 变量与 0 的大小,来判断传入参数是否合法
   *如果 index 小于 0,代表传入参数无效,直接返回
   */
  if (index < 0)
    return;
  /*删除在线用户列表中相应位置的客户端信息
   *将在线用户列表中指定位置的客户端信息的 fd 字段设置为 -1,表示该客户端已下线
   */
  online[index].fd = -1;
  /*通知所有客户端,某个用户下线了
   *遍历在线用户列表中的每个客户端,fd 不为 -1
   *的客户端,向其发送某用户下线的通知消息buf
   */
  sprintf(buf, "%s offline\n", online[index].name);
  for (i = 0; i < MAX_USER_NUM; i++) {
    if (online[i].fd == -1) {
      continue;
    }
    write(online[i].fd, buf, strlen(buf));
  }
  return;
}
/*向所有在线用户广播消息*/
void broadcast(int index, struct protocol *msg) {
  int i;
  char buf[128] = {0};
  sprintf(buf, "\033[0;34m\t%s say:%s\33[0m\n", online[index].name, msg->data);
  for (i = 0; i < MAX_USER_NUM; i++) {
    if ((online[i].fd == -1) || (i == index)) /*跳过不在线的和自己*/
    {
      continue;
    }
    write(online[i].fd, buf, strlen(buf));
  }
}
/*用于判断准备登录的用户是否已经登录,并返回其在列表中的索引*/
int find_dest_user_online(int socket_fd, int *index, struct protocol *msg) {
  int i;
  /*遍历在线用户列表数组*/
  for (i = 0; i < MAX_USER_NUM; i++) {
    if (online[i].flage == -1) {
      continue;
    }
    /*如果用户名和密码都匹配*/
    if ((strcmp(msg->name, online[i].name) == 0) &&
        (strcmp(msg->data, online[i].password) == 0)) 
    {/*不在线的先建立服务器连接*/
      if (online[i].fd == -1) {
        online[i].fd = socket_fd;
        *index = i;
        return OP_OK;
      } else {/*在线的打印已经登陆在线*/
        printf("%s had login\n", online[i].name);
        return USER_LOGED;/*用户已经登陆*/
      }
    }
  }/*遍历完所有在线用户仍然没有找到匹配的用户*/
  return NAME_PWD_NMATCH;
}
/*查找在线用户列表 online 中指定用户名*/
int find_dest_user(char *name) {
  int i;
  for (i = 0; i < MAX_USER_NUM; i++) {
    if (online[i].flage == -1) {
      continue;
    }
    if (strcmp(name, online[i].name) == 0) {
      return i;
    }
  }
  return -1;
}
/*私聊功能*/
void private(int index, struct protocol *msg) {
  int dest_index;
  char buf[128];
  /*查找目标用户在在线用户列表 online 中的索引*/
  dest_index = find_dest_user(msg->name);
  if (dest_index == -1) {
    /*向发送私聊请求的用户发送一条提示消息,告诉其该用户不在线*/
    sprintf(buf, "there is no  user :%s \n", msg->name);
    write(online[index].fd, buf, strlen(buf));
    return;
  } else {
    sprintf(buf, "\033[0;34m\t%s say to %s:%s\33[0m\n", online[index].name,
                                                online[dest_index].name,
                                                msg->data);
    write(online[dest_index].fd, buf, strlen(buf));
    return;
  }
}
/*列出在线用户*/
void list_online_user(int index) {
  int i;
  struct protocol msg;
  for (i = 0; i < MAX_USER_NUM; i++) {
    /*如果该套接字已经关闭,则继续下一个循环*/
    if (online[i].fd == -1) {
      continue;
    }
    memset(&msg, 0, sizeof(msg));
    msg.cmd = ONLINEUSER;
    msg.state = ONLINEUSER_OK;
    strcpy(msg.name, online[i].name);
    printf("list online[%d].name =%s \n",i, msg.name);
     /*向客户端发送在线用户结构体的数据*/
    write(online[index].fd, &msg, sizeof(msg));
    sleep(1);
  }
  /*表示在线用户列表已经全部发送完毕*/
  msg.cmd = ONLINEUSER;
  msg.state = ONLINEUSER_OVER;
  /*用于通知客户端当前任务已完成,并结束本次传输*/
  write(online[index].fd, &msg, sizeof(msg));
}
/*注册*/
void registe(int socket_fd, int *index, struct protocol *msg) {
  int dest_index;
  char buf[128];
  struct protocol msg_back;
  msg_back.cmd = REGISTE;
  /*查找该用户名是否已经被其他用户注册*/
  dest_index = find_dest_user(msg->name);
  if (dest_index == -1) {
    *index = add_user(socket_fd, msg);
    online[*index].flage = 1;
    msg_back.state =  OP_OK;
    printf("user %s regist success!\n", msg->name);
    write(socket_fd, &msg_back, sizeof(msg_back));
    return;
  } else {/*用户名已存在*/
    msg_back.state = NAME_EXIST;
    printf("user %s exist!\n", msg->name);
    write(socket_fd, &msg_back, sizeof(msg_back));
    return;
  }
}
/*登录*/
void login(int socket_fd, int *index, struct protocol *msg) {
  int i, ret;
  char buf[128];
  struct protocol msg_back;
  msg_back.cmd = LOGIN;
  /*查找该用户名是否已经在线*/
  ret = find_dest_user_online(socket_fd, index, msg);
  if (ret != OP_OK) {/*不等于表示该用户名不存在或者该用户未登录*/
    msg_back.state = ret;
    strcpy(buf, " no this user\n");
    printf("user %s login fail!\n", msg->name);
    write(socket_fd, &msg_back, sizeof(msg_back));
    return;
  } else {/*登录成功*/
    msg_back.state = OP_OK;
    strcpy(msg_back.data, "login success\n");
    printf("user %s login success!index =%d \n", msg->name, *index);
    write(online[*index].fd, &msg_back, sizeof(msg_back));
  }
  // 通知所有客户端,某个用户上线了
  sprintf(buf, "%s online\n", online[*index].name);
  for (i = 0; i < MAX_USER_NUM; i++) {
    if (online[i].fd != -1) {
      write(online[i].fd, buf, strlen(buf));
    }
  }
}
void *func(void *arg) {
  int socket_fd = *((int *)arg);
  char buf[64];
  int len;
  int index = -1;
  struct protocol msg;
  free(arg);
  /*进入聊天*/
  while (1) {
    /*read()函数和recv()函数都可以用于从套接字中读取数据,都会阻塞
     *小于等于0说明未能成功读取任何数据或连接已关闭,因此用户被视为离线
     */
    if ((len = read(socket_fd, &msg, sizeof(msg))) <= 0) {
      printf("%s offline\n", online[index].name);
      del_user_online(index);
      close(socket_fd);
      return;
    }

    switch (msg.cmd) {
    case REGISTE:
      registe(socket_fd, &index, &msg);
      break;
    case LOGIN:
      login(socket_fd, &index, &msg);
      break;
    case BROADCAST:
      broadcast(index, &msg);
      break;
    case PRIVATE:
      private(index, &msg);
      break;
    case ONLINEUSER:
      list_online_user(index);
      break;
    default:
      break;
    }
  }
}
int main(int argc, char *argv[]) {
  int ls_fd, new_fd;
  int addr_len, clientaddr_len;
  struct sockaddr_in my_addr;
  struct sockaddr_in client_addr;
  char buf[64] = {0};
  pthread_t pid;
  int *arg, i, port_number, ret;
  /*判断输入命令行参数数量是否正确*/
  if (argc != 2) {
    fprintf(stderr, "Usage: %s [port_number]>5000\a\n", argv[0]);
    exit(-1);
  }
  /*将第二个参数转换为整数类型并赋值给变量,然后判断输入的端口参数是否小于0*/
  if ((port_number = atoi(argv[1])) < 5000) {
    fprintf(stderr, "Usage: %s [port_number]>5000\a\n", argv[0]);
    exit(-1);
  }
  /*原型:int socket(int domain, int type, int protocol);
   *创建一个网络通信端点(打开一个网络通信),成功则返回一个网络文件描述符;调用失败,则会返回-1
   *domain:AF_INET,协议族名字,代表IPv4互联网协议;如果用IPV6在后面加个6即可
   *type:SOCK_STREAM,这是用于 TCP 协议
   *protocol:0,表示为给定的通信域和套接字类型选择默认协议
   */
  if ((ls_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
    perror("socket() fail\n");
    return;
  }
  /*将 server_addr 结构体变量所占用的内存区域全部清零。*/
  memset(&my_addr, 0, sizeof(struct sockaddr_in));
  /*指定套接字服务器的地址信息*/
  /*表示使用 IPv4 地址*/
  my_addr.sin_family = AF_INET;
  /*端口号设置并将主机字节顺序转换为网络字节顺序*/
  my_addr.sin_port = htons(port_number);
  /*使用了宏 INADDR_ANY
   * 来指定监听所有可用的网络接口,从而使得服务器能够接受到所有网络接口上的连接请求*/
  my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  addr_len = sizeof(struct sockaddr_in);
  /*int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
   *将参数 sockfd 指定的套接字与一个地址 addr 进行绑定,成功返回
   *0,失败情况下返回-1 sockfd:网络文件描述符 addr:服务器结构体地址
   *addrlen:addr参数所指向的结构体对应的字节长度
   */
  if (bind(ls_fd, (struct sockaddr *)(&my_addr), addr_len) == -1) {
    perror("bind() fail\n");
    exit(-1);
  }
  /*int listen(int sockfd, int backlog);
   *让服务器进程进入监听状态,监听sockfd描述符并创建一个等待连接队列,若执行成功则返回0,否则返回-1
   *sockfd:要设置为监听状态的套接字描述符
   *backlog:5,指定允许的连接数为
   *5。如果有更多的客户端连接请求到达,它们将被服务器拒绝或忽略。
   */
  if (listen(ls_fd, 5) == -1) {
    fprintf(stderr, "listen error:%s\n\a", strerror(errno));
    return;
  }
  clientaddr_len = sizeof(struct sockaddr_in);
  /*初始化online结构体*/
  for (i = 0; i < 64; i++) {
    online[i].fd = -1;
    online[i].flage = -1;
  }
  while (1) {
    /*int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
     *调用成功返回一个新的
     *socket_fd描述符,用于与客户端通信的。如果发生错误或者连接被中断,则函数返回
     *-1 函数成功返回时,addr 所指的缓冲区将被填充上客户端的地址信息,而 addrlen
     *则会被更新为实际的地址信息长度
     *调用时没有客户端请求连接(等待连接队列中也没有等待连接的请求),
     *accept()会进入阻塞状态,直到客户程序建立连接
     */
    if ((new_fd = accept(ls_fd, (struct sockaddr *)(&client_addr),
                         &clientaddr_len)) == -1) {
      fprintf(stderr, "Accept error:%s\n\a", strerror(errno));
      return;
    }
    /*char *inet_ntoa(struct in_addr in);
     *将32位IP地址转换为点分十进制形式的字符串表示
     */
    printf("Client-ip: %s\tport: %d\t\n", inet_ntoa(client_addr.sin_addr),
           client_addr.sin_port);
    /*用堆空间单独存放new_fd,防止高并发状态覆盖原栈空间的new_fd*/
    arg = malloc(sizeof(int));
    *arg = new_fd;
    /*pthread_create(pthread_t *thread,
                        const pthread_attr_t *attr,
                        void *(*start_routine) (void *),
                        void *arg);
     *创建一个新的线程,返回 0
     表示成功,否则返回一个非零的错误码,表示创建线程失败 *thread:线程标识符pid
     *attr:指定线程的属性,如果传递了 NULL,则表示使用默认属性
     *start_routine:是一个函数指针,用于指定线程启动时要执行的函数
     *arg:传递给该函数的参数
     */
    if ((ret = pthread_create(&pid, NULL, func, (void *)arg)) != 0) {
      perror("pthread_create err");
      return;
    }
  }
  close(new_fd);
  close(ls_fd);
  exit(0);
}

客户端代码

#include "chat.h"
#include <bits/types/timer_t.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>

int socket_fd, addrlen;
struct sockaddr_in server_addr;

pthread_t pid;

int login_f = -1;

void *func(void *arg) {
  int len;
  char buf[128] = {0};
  struct protocol *msg;
  while (1) {
    if (login_f != 1) {
      continue;
    }
    memset(buf, 0, sizeof(buf));
    if ((len = read(socket_fd, buf, sizeof(buf))) <= 0) {
      close(socket_fd);
      return;
    }
    msg = (struct protocol *)buf;
    /*显示在线用户*/
    if ((msg->state == ONLINEUSER_OK) && (msg->cmd == ONLINEUSER)) {
      printf("%s\t", msg->name);
      continue;
    }
    if ((msg->state == ONLINEUSER_OVER) && (msg->cmd == ONLINEUSER)) {
      printf("\n");
      continue;
    }
    buf[len] = '\0';
    printf("%s\n", buf);
  }
}
/*广播信息*/
void broadcast(int fd) {
  struct protocol msg;
  msg.cmd = BROADCAST;
  printf("say:\n#");
  scanf("%s", msg.data);
  write(fd, &msg, sizeof(msg));
}
/*私聊信息*/
void private(int fd) {
  struct protocol msg, msgback;
  msg.cmd = PRIVATE;
  printf("input name you want to talk:\n\t#");
  scanf("%s", msg.name);
  printf("\n#say:\n");
  scanf("%s", msg.data);
  write(fd, &msg, sizeof(msg));
}
/*显示在线人数*/
void list_online_user(int socket_fd) {
  struct protocol msg;
  msg.cmd = ONLINEUSER;
  write(socket_fd, &msg, sizeof(msg));
  while (1) {
    read(socket_fd, &msg, sizeof(msg));
    if (msg.state != ONLINEUSER_OK) {
      getchar();
      getchar();
      break;
    } else
      printf("%s\r\n", msg.name);
  }
}
/*注册*/
int registe(int fd) {
  struct protocol msg, msgback;
  msg.cmd = REGISTE;
  printf("input your name\n");
  scanf("%s", msg.name);
  printf("input your passwd\n");
  scanf("%s", msg.data);
  write(socket_fd, &msg, sizeof(msg));
  read(socket_fd, &msgback, sizeof(msgback));
  if (msgback.state != OP_OK) {
    printf("\033[0;31m\tName had exist,try again!\n");
    getchar();
    getchar();
    return -1;
  } else {
    printf("\033[0;31m\tRegist success!\n");
    getchar();
    getchar();
    return 0;
  }
}
/*登陆*/
int login(int fd) {
  struct protocol msg, msgback;
  msg.cmd = LOGIN;

  printf("input your name\n");
  scanf("%s", msg.name);
  printf("input your passwd\n");
  scanf("%s", msg.data);
  write(socket_fd, &msg, sizeof(msg));
  read(socket_fd, &msgback, sizeof(msgback));
  if (msgback.state != OP_OK) {
    printf("\033[0;31m\tName had exist,maybe the password is wrong,try "
           "again!\33[0m\n");
    getchar();
    getchar();
    login_f = -1;
    return NAME_PWD_NMATCH;
  } else {
    printf("\033[0;31m\tLogin success!\33[0m\n");
    getchar();
    getchar();
    login_f = 1;
    return OP_OK;
  }
}
/*退出*/
int logout(int fd) {
  close(fd);
  login_f = -1;
}
int main(int argc, char *argv[]) {
  int sel, ret;
  int port_number;
  int min_sel, max_sel;
  struct protocol msg;
  /* 检测参数个数*/
  if (argc != 3) {
    fprintf(stderr, "Usage:%s hostname portnumber\a\n", argv[0]);
    exit(-1);
  }
  /*argv2 存放的是端口号 ,读取该端口,转换成整型变量*/
  if ((port_number = atoi(argv[2])) < 5000) {
    fprintf(stderr, "Usage:%s hostname [portnumber]>5000\a\n", argv[0]);
    exit(-1);
  }
  /*创建一个 套接字*/
  if ((socket_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
    fprintf(stderr, "Socket Error:%s\a\n", strerror(errno));
    return;
  }
  /*填充结构体,ip和port必须是服务器的*/
  memset(&server_addr, 0, sizeof(server_addr));
  server_addr.sin_family = AF_INET;
  /*转换为网络字节序*/
  server_addr.sin_port = htons(port_number);
  /*点分十进制表示的字符串形式转换成二进制 Ipv4 或 Ipv6 地址*/
  server_addr.sin_addr.s_addr = inet_addr(argv[1]);
  addrlen = sizeof(struct sockaddr_in);
  if (connect(socket_fd, (struct sockaddr *)(&server_addr), addrlen) == -1) {
    fprintf(stderr, "Connect Error:%s\a\n", strerror(errno));
    return;
  }
  /*创建线程*/
  if ((ret = pthread_create(&pid, NULL, func, NULL)) != 0) {
    perror("pthread_create err");
    return;
  }
  while (1) {
    system("clear");
    if (login_f == -1) {
      printf(
          "\033[0;33m+---------------------------------------------+\033[0m\n");
      printf("\33[0;31m\t 1、 注册 \n\33[0m");
      printf("\33[0;31m\t 2、 登录 \33[0m\n");
    } else if (login_f == 1) {
      printf(
          "\033[0;33m+---------------------------------------------+\033[0m\n");
      printf("\33[0;31m\t 3、 公聊\33[0m\n");
      printf("\33[0;31m\t 4、 私聊\33[0m\n");
      printf("\33[0;31m\t 5、 在线用户\33[0m\n");
    }
    printf("\33[0;31m\t 0、 退出\033[0m\n");
    printf(
        "\033[0;33m+---------------------------------------------+\033[0m\n");
    fflush(stdin);
    scanf("%d", &sel);
    if (sel == 0) {
      break;
    }
    if (login_f == 1) {
      min_sel = 3;
      max_sel = 5;
    } else if (login_f == -1) {
      min_sel = 1;
      max_sel = 2;
    }
    if (sel < min_sel || sel > max_sel) {
      printf("输入的数字不在范围内,请重新输入\n");
      continue;
    }
    switch (sel) {
    case 1:
      registe(socket_fd);
      break;
    case 2:
      login(socket_fd);
      break;
    case 3:
      broadcast(socket_fd);
      break;
    case 4:
      private
      (socket_fd);
      break;
    case 5:
      list_online_user(socket_fd);
      break;
    case 0:
      logout(socket_fd);
      break;
    default:
      break;
    }
    if (sel == 0) {
      exit(0);
    }
  }
}

本项目学习于从0实现基于Linux socket聊天室-多线程服务器模型-1_一口Linux的博客-CSDN博客

从0实现基于Linux socket聊天室-多线程服务器一个很隐晦的错误-2_一口Linux的博客-CSDN博客从0实现基于Linux socket聊天室-多线程服务器一个很隐晦的错误-2_一口Linux的博客-CSDN博客
 从0实现基于Linux socket聊天室-实现聊天室的公聊、私聊功能-4_一口Linux的博客-CSDN博客
 

一口Linux博主实力强悍、经验丰富、知识领域广,笔下文章内容丰富,大家可以点点关注文章来源地址https://www.toymoban.com/news/detail-816014.html

到了这里,关于Linux socket聊天室的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 使用Linux系统IO多路复用中eopll创建基于TCP通信协议的多人聊天室

    一.1.搭建好TCP的通信模型 2.创建红黑树根节点 3.将套接字事件添加到红黑树中,使其被监听 4.当套接字事件发生,表示有客户端连接,将连接事件加入到红黑树节点当中 5.每当连接事件发生时,表示客户端发送信息到服务器 6.每当有事件准备就绪时,将对应的红黑树节点信息

    2024年02月13日
    浏览(45)
  • UDP套接字的通信(实现英汉互译/程序替换/多线程聊天室/Windows与Linux通信)

    我们在客户端发英文,服务端做翻译工作,让翻译好的中文再次发给我们的客户端,然后打印出来。 翻译的操作 创建一个txt文件里面包含英汉互译的数据 dict.txt 对txt中的数据进行操作 分割函数 将英汉通过冒号分开。 将文件数据插入map里面 重新加载文件 通过捕捉2号(ctrl

    2024年02月11日
    浏览(38)
  • Linux 基本语句_16_Udp网络聊天室

    服务端代码: 客户端代码: 总体效果是客户上线状态、退出状态、发送的消息都能通过广播,将信息发送给所有在线客户端,服务端能接收并显示所有客户端发送的消息,且也具备广播能力 服务端: 服务端创建了一个链表,这个链表中的每个节点是专用于储存客户端的ip地

    2024年02月04日
    浏览(41)
  • Python多人聊天室-基于socket UDP协议

    使用Python编写的基于socket UDP通信的多功能即时聊天室,包含Tkinter编写的图形化聊天界面,功能包括有账号注册和登录,登录成功后可以查看在线用户,并和聊天室内的其他在线用户聊天,包含私聊和群发,能发送文字、表情包,以及文件等。 登录和注册 显示在线用户 群聊

    2024年02月11日
    浏览(58)
  • 多人聊天室(带私聊功能)Linux网络编程基础

    在和同学一起努力下终于完成了期末作业哈哈哈哈 文章目录 目录 前言 一、需求分析 二、功能设计 1.服务器端: 2.客户端: 三、流程图: 编程流程图: 服务器流程图: 客户端流程图: 四、运行效果: 项目源码: 服务器源码 客户端源码: 总结: Linux网络编程是我们这学

    2024年02月09日
    浏览(59)
  • 基于Java Socket写一个多线程的聊天室(附源码)

    Socket编程是在TCP/IP上的网络编程,但是Socket在上述模型的什么位置呢。这个位置被一个天才的理论家或者是抽象的计算机大神提出并且安排出来 ​ 我们可以发现Socket就在应用程序的传输层和应用层之间,设计了一个Socket抽象层,传输层的底一层的服务提供给Socket抽象层,S

    2024年02月10日
    浏览(54)
  • .NET编程——利用C#实现基于Socket类的聊天室(WinForm)

    在学习C#和MySQL实现注册登录和TCP协议的Socket通信后,本文将介绍如何利用Socket类中的异步通信函数来实现本地聊天室功能, Socket通信限制了客户端与客户端之间的通信,客户端只能接收来自服务器的消息而不能接收到客户端发送的消息,因此服务器最佳的选择是起到一个中

    2023年04月21日
    浏览(90)
  • 【一】【socket聊天室】-多线程,socket编程

    本文主要实现基于socket编程的聊天室,主要分为下面三个步骤: (1)多用户聊天:一个服务器多个客户端,客户端信息显示在公共的服务端窗口,利用 多线程 实现;          ——客户端双线程:一个接受线程一个发送线程(主线程);          ——服务器单线程:接收

    2024年02月08日
    浏览(45)
  • 【Java socket编程】多人聊天室

    课程设计大作业 功能: 1.具有 点对点通信 功能,任意客户端之间能够发送消息。 2.具有 群组通信 功能: 客户端可以 自主建立群组 ,添加或删除组成员; 客户端能够向组内成员同时发送消息,其他组成员不能收到。 3.具有 广播 功能 客户端能够向所有其他成员 广播消息

    2024年02月04日
    浏览(40)
  • C语言Socket编程TCP简单聊天室

    这是一个使用C语言进行套接字编程实现的简单聊天室, 使用Pthread库进行多线程执行 服务端: svr.c 客户端: cli.c Makefile: Makefile 执行编译 启动服务器 启动客户端 聊天 退出

    2024年02月03日
    浏览(54)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包