国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

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系統(tǒng)編程,linux,服務器,c語言,ubuntu,網(wǎng)絡

?再運行客戶端,這里創(chuàng)建兩個客戶端,端口號要和服務端的一樣

./C 127.0.0.1 8888

linux基于socket的聊天程序,# LINUX系統(tǒng)編程,linux,服務器,c語言,ubuntu,網(wǎng)絡

?????????可以看到,左下的窗口運之后,就會進入注冊界面;而服務器也會提示有客戶端的ip連接進來,這個時候再用右邊的窗口運行客戶端

linux基于socket的聊天程序,# LINUX系統(tǒng)編程,linux,服務器,c語言,ubuntu,網(wǎng)絡

??進入兩個主頁之后,服務器就會有不同的port對應不同的客戶端

3、使用效果

注冊

linux基于socket的聊天程序,# LINUX系統(tǒng)編程,linux,服務器,c語言,ubuntu,網(wǎng)絡

?????????上圖可以看到,左下進行了一個注冊之后就會提示注冊成功,服務器上面也會有記錄,下面進行登錄

linux基于socket的聊天程序,# LINUX系統(tǒng)編程,linux,服務器,c語言,ubuntu,網(wǎng)絡

?????????上圖左下登錄之后會提示登錄成功,服務器也會有記錄,而左下的窗口只要再按下回車就能進入到功能主頁。下面再用左下的窗口注冊一個用戶2

linux基于socket的聊天程序,# LINUX系統(tǒng)編程,linux,服務器,c語言,ubuntu,網(wǎng)絡

?????????上圖可以看到,用戶2注冊成功登錄之后,進入功能主頁的左下用戶也會有提示說右下用戶上線了,服務器也會記錄。下面左下用戶進行“公聊”,只要是在線的用戶都會收到信息

linux基于socket的聊天程序,# LINUX系統(tǒng)編程,linux,服務器,c語言,ubuntu,網(wǎng)絡

?? ? ? ? 上圖坐下用戶輸入數(shù)字3,選擇功能之后,就會提示輸入,輸入之后按回車,右下用戶就出現(xiàn)了信息(藍色字體),如下?

linux基于socket的聊天程序,# LINUX系統(tǒng)編程,linux,服務器,c語言,ubuntu,網(wǎng)絡

? ? ? ? ?上圖可以看到右下用戶出現(xiàn)了“公聊信息”藍色字體,下面用右邊的用戶對左邊用戶進行“私聊”

linux基于socket的聊天程序,# LINUX系統(tǒng)編程,linux,服務器,c語言,ubuntu,網(wǎng)絡

? ? ? ? ?輸入4選擇功能之后,會詢問對誰發(fā)信息,接著就輸入用戶的名字,在輸入發(fā)送的消息,按下回車就可以發(fā)送,如下

linux基于socket的聊天程序,# LINUX系統(tǒng)編程,linux,服務器,c語言,ubuntu,網(wǎng)絡

? ? ? ? 可以看到坐下的用戶已經(jīng)收到私聊的信息,這樣就不會像公聊那樣誰都能看到,輸入5可以查看有誰在線,下面先把右下的用戶退出

linux基于socket的聊天程序,# LINUX系統(tǒng)編程,linux,服務器,c語言,ubuntu,網(wǎng)絡

上圖可以看到只查詢到自己用戶1的名字在線,下面用第二個用戶查詢

linux基于socket的聊天程序,# LINUX系統(tǒng)編程,linux,服務器,c語言,ubuntu,網(wǎng)絡

linux基于socket的聊天程序,# LINUX系統(tǒng)編程,linux,服務器,c語言,ubuntu,網(wǎng)絡?上圖可以看到,用戶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
/*最大的用戶數(shù)量*/
#define MAX_USER_NUM 64
/*在線用戶*/
struct ONLINE{
    int fd;                     /*描述符,-1:該用戶下線   >0:該用戶已經(jīng)登錄,對應的套接字*/
    int flage;                  /*注冊標志,-1 該條目沒有用戶信息  1:該條目有用戶注冊信息*/
    char name[SIZE];            /*姓名*/
    char password[SIZE];        /*密碼*/
};
/*C/S通信的結(jié)構(gòu)體*/
struct protocol{
    int cmd;                    /*命令*/
    int state;                  /*存儲命令返回信息*/
    char name[SIZE];            /*用戶姓名*/
    char data[MAX_USER_NUM];    /*數(shù)據(jù)*/
};
/*cmd(命令類型)*/
#define BROADCAST       0X00000001          /*廣播數(shù)據(jù)*/
#define PRIVATE         0X00000002          /*私聊*/
#define REGISTE         0X00000004          /*注冊*/
#define LOGIN           0X00000008          /*登錄*/
#define ONLINEUSER      0X00000010          /*顯示在線用戶*/
#define LOGOUT          0X00000020          /*退出*/

/*return code(服務器處理結(jié)果返回值)*/
#define OP_OK               0X80000000      /*操作成功*/
#define ONLINEUSER_OK       0X80000001      /*顯示在線用戶,未結(jié)束*/
#define ONLINEUSER_OVER     0X88888888      /*顯示在線用戶,已經(jīng)發(fā)送完畢*/
#define NAME_EXIST          0X80000003      /*注冊信息,用戶名已經(jīng)存在*/
#define NAME_PWD_NMATCH     0X80000004      /*登錄時,輸入的用戶名密碼不對 */
#define USER_LOGED          0X80000005      /*登錄時,提示該用戶已經(jīng)在線*/
#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};
  /*歷在線用戶列表數(shù)組,從第一個開始找沒有被占用的位置,將用戶的注冊信息存儲到該位置*/
  for (i = 0; i < MAX_USER_NUM; i++) { /*判斷當前位置是否已經(jīng)被占用*/
    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;
}
/*從在線列表中刪除
 *在聊天室程序中將在線用戶列表中指定位置的客戶端信息刪除,
 *并向所有在線客戶端發(fā)送某用戶下線通知
 */
void del_user_online(int index) {
  int i;
  char buf[128] = {0};
  /*通過比較傳入的 index 變量與 0 的大小,來判斷傳入?yún)?shù)是否合法
   *如果 index 小于 0,代表傳入?yún)?shù)無效,直接返回
   */
  if (index < 0)
    return;
  /*刪除在線用戶列表中相應位置的客戶端信息
   *將在線用戶列表中指定位置的客戶端信息的 fd 字段設置為 -1,表示該客戶端已下線
   */
  online[index].fd = -1;
  /*通知所有客戶端,某個用戶下線了
   *遍歷在線用戶列表中的每個客戶端,fd 不為 -1
   *的客戶端,向其發(fā)送某用戶下線的通知消息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));
  }
}
/*用于判斷準備登錄的用戶是否已經(jīng)登錄,并返回其在列表中的索引*/
int find_dest_user_online(int socket_fd, int *index, struct protocol *msg) {
  int i;
  /*遍歷在線用戶列表數(shù)組*/
  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 {/*在線的打印已經(jīng)登陸在線*/
        printf("%s had login\n", online[i].name);
        return USER_LOGED;/*用戶已經(jīng)登陸*/
      }
    }
  }/*遍歷完所有在線用戶仍然沒有找到匹配的用戶*/
  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) {
    /*向發(fā)送私聊請求的用戶發(fā)送一條提示消息,告訴其該用戶不在線*/
    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++) {
    /*如果該套接字已經(jīng)關閉,則繼續(xù)下一個循環(huán)*/
    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);
     /*向客戶端發(fā)送在線用戶結(jié)構(gòu)體的數(shù)據(jù)*/
    write(online[index].fd, &msg, sizeof(msg));
    sleep(1);
  }
  /*表示在線用戶列表已經(jīng)全部發(fā)送完畢*/
  msg.cmd = ONLINEUSER;
  msg.state = ONLINEUSER_OVER;
  /*用于通知客戶端當前任務已完成,并結(jié)束本次傳輸*/
  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;
  /*查找該用戶名是否已經(jīng)被其他用戶注冊*/
  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;
  /*查找該用戶名是否已經(jīng)在線*/
  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()函數(shù)和recv()函數(shù)都可以用于從套接字中讀取數(shù)據(jù),都會阻塞
     *小于等于0說明未能成功讀取任何數(shù)據(jù)或連接已關閉,因此用戶被視為離線
     */
    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;
  /*判斷輸入命令行參數(shù)數(shù)量是否正確*/
  if (argc != 2) {
    fprintf(stderr, "Usage: %s [port_number]>5000\a\n", argv[0]);
    exit(-1);
  }
  /*將第二個參數(shù)轉(zhuǎn)換為整數(shù)類型并賦值給變量,然后判斷輸入的端口參數(shù)是否小于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);
   *創(chuàng)建一個網(wǎng)絡通信端點(打開一個網(wǎng)絡通信),成功則返回一個網(wǎng)絡文件描述符;調(diào)用失敗,則會返回-1
   *domain:AF_INET,協(xié)議族名字,代表IPv4互聯(lián)網(wǎng)協(xié)議;如果用IPV6在后面加個6即可
   *type:SOCK_STREAM,這是用于 TCP 協(xié)議
   *protocol:0,表示為給定的通信域和套接字類型選擇默認協(xié)議
   */
  if ((ls_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
    perror("socket() fail\n");
    return;
  }
  /*將 server_addr 結(jié)構(gòu)體變量所占用的內(nèi)存區(qū)域全部清零。*/
  memset(&my_addr, 0, sizeof(struct sockaddr_in));
  /*指定套接字服務器的地址信息*/
  /*表示使用 IPv4 地址*/
  my_addr.sin_family = AF_INET;
  /*端口號設置并將主機字節(jié)順序轉(zhuǎn)換為網(wǎng)絡字節(jié)順序*/
  my_addr.sin_port = htons(port_number);
  /*使用了宏 INADDR_ANY
   * 來指定監(jiān)聽所有可用的網(wǎng)絡接口,從而使得服務器能夠接受到所有網(wǎng)絡接口上的連接請求*/
  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);
   *將參數(shù) sockfd 指定的套接字與一個地址 addr 進行綁定,成功返回
   *0,失敗情況下返回-1 sockfd:網(wǎng)絡文件描述符 addr:服務器結(jié)構(gòu)體地址
   *addrlen:addr參數(shù)所指向的結(jié)構(gòu)體對應的字節(jié)長度
   */
  if (bind(ls_fd, (struct sockaddr *)(&my_addr), addr_len) == -1) {
    perror("bind() fail\n");
    exit(-1);
  }
  /*int listen(int sockfd, int backlog);
   *讓服務器進程進入監(jiān)聽狀態(tài),監(jiān)聽sockfd描述符并創(chuàng)建一個等待連接隊列,若執(zhí)行成功則返回0,否則返回-1
   *sockfd:要設置為監(jiān)聽狀態(tài)的套接字描述符
   *backlog:5,指定允許的連接數(shù)為
   *5。如果有更多的客戶端連接請求到達,它們將被服務器拒絕或忽略。
   */
  if (listen(ls_fd, 5) == -1) {
    fprintf(stderr, "listen error:%s\n\a", strerror(errno));
    return;
  }
  clientaddr_len = sizeof(struct sockaddr_in);
  /*初始化online結(jié)構(gòu)體*/
  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);
     *調(diào)用成功返回一個新的
     *socket_fd描述符,用于與客戶端通信的。如果發(fā)生錯誤或者連接被中斷,則函數(shù)返回
     *-1 函數(shù)成功返回時,addr 所指的緩沖區(qū)將被填充上客戶端的地址信息,而 addrlen
     *則會被更新為實際的地址信息長度
     *調(diào)用時沒有客戶端請求連接(等待連接隊列中也沒有等待連接的請求),
     *accept()會進入阻塞狀態(tài),直到客戶程序建立連接
     */
    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地址轉(zhuǎn)換為點分十進制形式的字符串表示
     */
    printf("Client-ip: %s\tport: %d\t\n", inet_ntoa(client_addr.sin_addr),
           client_addr.sin_port);
    /*用堆空間單獨存放new_fd,防止高并發(fā)狀態(tài)覆蓋原??臻g的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);
     *創(chuàng)建一個新的線程,返回 0
     表示成功,否則返回一個非零的錯誤碼,表示創(chuàng)建線程失敗 *thread:線程標識符pid
     *attr:指定線程的屬性,如果傳遞了 NULL,則表示使用默認屬性
     *start_routine:是一個函數(shù)指針,用于指定線程啟動時要執(zhí)行的函數(shù)
     *arg:傳遞給該函數(shù)的參數(shù)
     */
    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));
}
/*顯示在線人數(shù)*/
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;
  /* 檢測參數(shù)個數(shù)*/
  if (argc != 3) {
    fprintf(stderr, "Usage:%s hostname portnumber\a\n", argv[0]);
    exit(-1);
  }
  /*argv2 存放的是端口號 ,讀取該端口,轉(zhuǎn)換成整型變量*/
  if ((port_number = atoi(argv[2])) < 5000) {
    fprintf(stderr, "Usage:%s hostname [portnumber]>5000\a\n", argv[0]);
    exit(-1);
  }
  /*創(chuàng)建一個 套接字*/
  if ((socket_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
    fprintf(stderr, "Socket Error:%s\a\n", strerror(errno));
    return;
  }
  /*填充結(jié)構(gòu)體,ip和port必須是服務器的*/
  memset(&server_addr, 0, sizeof(server_addr));
  server_addr.sin_family = AF_INET;
  /*轉(zhuǎn)換為網(wǎng)絡字節(jié)序*/
  server_addr.sin_port = htons(port_number);
  /*點分十進制表示的字符串形式轉(zhuǎn)換成二進制 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;
  }
  /*創(chuàng)建線程*/
  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("輸入的數(shù)字不在范圍內(nèi),請重新輸入\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實現(xiàn)基于Linux socket聊天室-多線程服務器模型-1_一口Linux的博客-CSDN博客

從0實現(xiàn)基于Linux socket聊天室-多線程服務器一個很隱晦的錯誤-2_一口Linux的博客-CSDN博客從0實現(xiàn)基于Linux socket聊天室-多線程服務器一個很隱晦的錯誤-2_一口Linux的博客-CSDN博客
?從0實現(xiàn)基于Linux socket聊天室-實現(xiàn)聊天室的公聊、私聊功能-4_一口Linux的博客-CSDN博客
?

一口Linux博主實力強悍、經(jīng)驗豐富、知識領域廣,筆下文章內(nèi)容豐富,大家可以點點關注文章來源地址http://www.zghlxwxcb.cn/news/detail-816014.html

到了這里,關于Linux socket聊天室的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • 使用Linux系統(tǒng)IO多路復用中eopll創(chuàng)建基于TCP通信協(xié)議的多人聊天室

    一.1.搭建好TCP的通信模型 2.創(chuàng)建紅黑樹根節(jié)點?3.將套接字事件添加到紅黑樹中,使其被監(jiān)聽 4.當套接字事件發(fā)生,表示有客戶端連接,將連接事件加入到紅黑樹節(jié)點當中 5.每當連接事件發(fā)生時,表示客戶端發(fā)送信息到服務器 6.每當有事件準備就緒時,將對應的紅黑樹節(jié)點信息

    2024年02月13日
    瀏覽(19)
  • UDP套接字的通信(實現(xiàn)英漢互譯/程序替換/多線程聊天室/Windows與Linux通信)

    UDP套接字的通信(實現(xiàn)英漢互譯/程序替換/多線程聊天室/Windows與Linux通信)

    我們在客戶端發(fā)英文,服務端做翻譯工作,讓翻譯好的中文再次發(fā)給我們的客戶端,然后打印出來。 翻譯的操作 創(chuàng)建一個txt文件里面包含英漢互譯的數(shù)據(jù) dict.txt 對txt中的數(shù)據(jù)進行操作 分割函數(shù) 將英漢通過冒號分開。 將文件數(shù)據(jù)插入map里面 重新加載文件 通過捕捉2號(ctrl

    2024年02月11日
    瀏覽(18)
  • Linux 基本語句_16_Udp網(wǎng)絡聊天室

    Linux 基本語句_16_Udp網(wǎng)絡聊天室

    服務端代碼: 客戶端代碼: 總體效果是客戶上線狀態(tài)、退出狀態(tài)、發(fā)送的消息都能通過廣播,將信息發(fā)送給所有在線客戶端,服務端能接收并顯示所有客戶端發(fā)送的消息,且也具備廣播能力 服務端: 服務端創(chuàng)建了一個鏈表,這個鏈表中的每個節(jié)點是專用于儲存客戶端的ip地

    2024年02月04日
    瀏覽(18)
  • Python多人聊天室-基于socket UDP協(xié)議

    Python多人聊天室-基于socket UDP協(xié)議

    使用Python編寫的基于socket UDP通信的多功能即時聊天室,包含Tkinter編寫的圖形化聊天界面,功能包括有賬號注冊和登錄,登錄成功后可以查看在線用戶,并和聊天室內(nèi)的其他在線用戶聊天,包含私聊和群發(fā),能發(fā)送文字、表情包,以及文件等。 登錄和注冊 顯示在線用戶 群聊

    2024年02月11日
    瀏覽(20)
  • 多人聊天室(帶私聊功能)Linux網(wǎng)絡編程基礎

    多人聊天室(帶私聊功能)Linux網(wǎng)絡編程基礎

    在和同學一起努力下終于完成了期末作業(yè)哈哈哈哈 文章目錄 目錄 前言 一、需求分析 二、功能設計 1.服務器端: 2.客戶端: 三、流程圖: 編程流程圖: 服務器流程圖: 客戶端流程圖: 四、運行效果: 項目源碼: 服務器源碼 客戶端源碼: 總結(jié): Linux網(wǎng)絡編程是我們這學

    2024年02月09日
    瀏覽(27)
  • 基于Java Socket寫一個多線程的聊天室(附源碼)

    基于Java Socket寫一個多線程的聊天室(附源碼)

    Socket編程是在TCP/IP上的網(wǎng)絡編程,但是Socket在上述模型的什么位置呢。這個位置被一個天才的理論家或者是抽象的計算機大神提出并且安排出來 ? 我們可以發(fā)現(xiàn)Socket就在應用程序的傳輸層和應用層之間,設計了一個Socket抽象層,傳輸層的底一層的服務提供給Socket抽象層,S

    2024年02月10日
    瀏覽(31)
  • .NET編程——利用C#實現(xiàn)基于Socket類的聊天室(WinForm)

    .NET編程——利用C#實現(xiàn)基于Socket類的聊天室(WinForm)

    在學習C#和MySQL實現(xiàn)注冊登錄和TCP協(xié)議的Socket通信后,本文將介紹如何利用Socket類中的異步通信函數(shù)來實現(xiàn)本地聊天室功能, Socket通信限制了客戶端與客戶端之間的通信,客戶端只能接收來自服務器的消息而不能接收到客戶端發(fā)送的消息,因此服務器最佳的選擇是起到一個中

    2023年04月21日
    瀏覽(34)
  • 【一】【socket聊天室】-多線程,socket編程

    【一】【socket聊天室】-多線程,socket編程

    本文主要實現(xiàn)基于socket編程的聊天室,主要分為下面三個步驟: (1)多用戶聊天:一個服務器多個客戶端,客戶端信息顯示在公共的服務端窗口,利用 多線程 實現(xiàn); ? ? ? ? ?——客戶端雙線程:一個接受線程一個發(fā)送線程(主線程); ? ? ? ? ?——服務器單線程:接收

    2024年02月08日
    瀏覽(18)
  • 【Java socket編程】多人聊天室

    【Java socket編程】多人聊天室

    課程設計大作業(yè) 功能: 1.具有 點對點通信 功能,任意客戶端之間能夠發(fā)送消息。 2.具有 群組通信 功能: 客戶端可以 自主建立群組 ,添加或刪除組成員; 客戶端能夠向組內(nèi)成員同時發(fā)送消息,其他組成員不能收到。 3.具有 廣播 功能 客戶端能夠向所有其他成員 廣播消息

    2024年02月04日
    瀏覽(35)
  • C語言Socket編程TCP簡單聊天室

    C語言Socket編程TCP簡單聊天室

    這是一個使用C語言進行套接字編程實現(xiàn)的簡單聊天室, 使用Pthread庫進行多線程執(zhí)行 服務端: svr.c 客戶端: cli.c Makefile: Makefile 執(zhí)行編譯 啟動服務器 啟動客戶端 聊天 退出

    2024年02月03日
    瀏覽(29)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包