欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易網(wǎng)絡(luò)聊天室

 更新時(shí)間:2021年06月30日 17:23:30   作者:菠蘿小馬哥  
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易網(wǎng)絡(luò)聊天室,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

本文實(shí)例為大家分享了C語(yǔ)言實(shí)現(xiàn)網(wǎng)絡(luò)聊天室的具體代碼,供大家參考,具體內(nèi)容如下

業(yè)務(wù)邏輯:

1、客戶端注冊(cè)名字
2、告訴所有在線的客戶端,XXX進(jìn)入聊天室
3、新建一個(gè)線程為該客戶端服務(wù),隨時(shí)接收客戶端發(fā)送來(lái)的消息
4、當(dāng)接收到一個(gè)客戶端的消息時(shí),向每一個(gè)客戶端轉(zhuǎn)發(fā)一份(群聊)
5、同時(shí)在線人數(shù)最多50人

任何客戶端可以隨意隨時(shí)進(jìn)入或退出客戶端

服務(wù)端代碼server.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <pthread.h>
#include <semaphore.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#ifndef DEBUG
 #define debug(format,...) {}
#else
 #define debug(format,...) \
 {\
  fprintf(stdout,"%s:%d:%s ",__func__,__LINE__,__TIME__);\
  fprintf(stdout,format,##__VA_ARGS__);\
  fprintf(stdout,"\n");\
 }
#endif//DEBUG

#define error(format,...)\
{\
 fprintf(stdout,"%s:%d:%s ",__func__,__LINE__,__TIME__);\
 fprintf(stdout,format,##__VA_ARGS__);\
 fprintf(stdout,":%m\n");\
 exit(EXIT_FAILURE);\
}

// 客戶端最大連接數(shù)
#define CLIENT_MAX 50

// 服務(wù)器端口號(hào)
#define PORT 5566

// 緩沖區(qū)大小
#define BUF_SIZE 4096

// 重定義socket地址類型
typedef struct sockaddr* SP;

// 客戶端結(jié)構(gòu)體
typedef struct Client
{
 int sock;//socket 標(biāo)識(shí)符
 pthread_t tid; //線程ID
 char name[20];
 struct sockaddr_in addr;
}Client;

// 定義50個(gè)存儲(chǔ)客戶端的結(jié)構(gòu)變量
Client clients[50];

// 定義信號(hào)量用于限制客戶端的數(shù)量
sem_t sem;

// 信號(hào)處理函數(shù)
void sigint(int num)
{
 for(int i=0; i<10; i++)
 {
  if(clients[i].sock)
  {
   pthread_cancel(clients[i].tid);//銷毀線程
  }
 }
 debug("服務(wù)器退出!");
 exit(EXIT_SUCCESS);
}

void client_eixt(Client* client)
{
 sem_post(&sem);
 close(client->sock);
 client->sock = 0;
}

void client_send(Client* client,char* buf)
{
 size_t len = strlen(buf)+1;
 for(int i=0; i<CLIENT_MAX; i++)
 {
  if(clients[i].sock && clients[i].sock != client->sock)
  {
    send(clients[i].sock,buf,len,0);
  }
 }
}

void* run(void* arg)
{
 Client* client = arg;
 char buf[BUF_SIZE] = {};

 // 接收昵稱
 int ret_size = recv(client->sock,client->name,20,0);
 if(0 >= ret_size)
 {
  client_eixt(client);
  return NULL;
 }

 // 通知其它客戶端新人上線
 sprintf(buf,"!!!歡迎%s進(jìn)入聊天室!!!",client->name);
 client_send(client,buf);
 for(;;)
 { 
  // 接收消息
  ret_size = recv(client->sock,buf,BUF_SIZE,0);
  if(0 >= ret_size || 0 == strcmp("quit",buf))
  {
   // 通知其它客戶端退出
   sprintf(buf,"!!!%s退出聊天室!!!",client->name);
   client_send(client,buf);
   client_eixt(client);
   return NULL;
  }
  strcat(buf,":");
  strcat(buf,client->name);
  client_send(client,buf);
  debug(buf);
 }
}

int main(int argc,const char* argv[])
{
 signal(SIGINT,sigint);
 debug("注冊(cè)信號(hào)處理函數(shù)成功!");

 sem_init(&sem,0,CLIENT_MAX);
 debug("初始化信號(hào)量成功!");

 int svr_sock = socket(AF_INET,SOCK_STREAM,0);
 if(0 > svr_sock)
 {
  error("socket");
 }
 debug("創(chuàng)建socket對(duì)象成功!");

 struct sockaddr_in svr_addr = {};
 svr_addr.sin_family = AF_INET;
 svr_addr.sin_port = htons(PORT);
 svr_addr.sin_addr.s_addr = INADDR_ANY;
 socklen_t addrlen = sizeof(svr_addr);
 debug("準(zhǔn)備通信地址成功!");

 if(bind(svr_sock,(SP)&svr_addr,addrlen))
 {
  error("bind");
 }
 debug("綁定socket對(duì)象和通信地址成功!");


 if(listen(svr_sock,10))
 {
  error("listen");
 }
 debug("設(shè)置監(jiān)聽socket監(jiān)聽成功!");

 for(;;)
 {
  debug("等待客戶端連接...");

  sem_wait(&sem);
  int index = 0;
  while(clients[index].sock)
  {
   index++;
  }

  clients[index].sock = accept(svr_sock,(SP)&clients[index].addr,&addrlen);
  if(0 > clients[index].sock)
  {
   kill(getpid(),SIGINT);
  }

  debug("有新的客戶端連接,from ip:%s",inet_ntoa(clients[index].addr.sin_addr));
  pthread_create(&clients[index].tid,NULL,run,&clients[index]);
 }
}

客戶端代碼client.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <pthread.h>
#include <semaphore.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#ifndef DEBUG
 #define debug(format,...) {}
#else
 #define debug(format,...) \
 {\
  fprintf(stdout,"%s:%d:%s ",__func__,__LINE__,__TIME__);\
  fprintf(stdout,format,##__VA_ARGS__);\
  fprintf(stdout,"\n");\
 }
#endif//DEBUG

#define error(format,...)\
{\
 fprintf(stdout,"%s:%d:%s ",__func__,__LINE__,__TIME__);\
 fprintf(stdout,format,##__VA_ARGS__);\
 fprintf(stdout,":%m\n");\
 exit(EXIT_FAILURE);\
}

#define BUF_SIZE  4096
#define SERVER_PORT 5566
#define SERVER_IP  "192.168.0.125"
typedef struct sockaddr* SP;

void* run(void* arg)
{
 int cli_sock = *(int*)arg;
 char buf[BUF_SIZE] = {};
 for(;;)
 {
  int ret_size = recv(cli_sock,buf,BUF_SIZE,0);
  if(0 >= ret_size)
  {
   printf("服務(wù)器正在升級(jí),請(qǐng)稍候登錄!\n");
   exit(EXIT_SUCCESS);
  }
  printf("\r%30s\n>>>",buf);
  fflush(stdout);
 }
}


int main(int argc,const char* argv[])
{
 int cli_sock = socket(AF_INET,SOCK_STREAM,0);
 if(0 > cli_sock)
 {
  error("socket");
 }

 struct sockaddr_in cli_addr = {};
 cli_addr.sin_family = AF_INET;
 cli_addr.sin_port = htons(SERVER_PORT);
 cli_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
 socklen_t addrlen = sizeof(cli_addr);

 if(connect(cli_sock,(SP)&cli_addr,addrlen))
 {
  printf("服務(wù)器正在升級(jí),請(qǐng)稍候登錄!\n");
  return EXIT_SUCCESS;
 }

 char buf[BUF_SIZE] = {};
 printf("請(qǐng)輸入你的眤稱:");
 gets(buf);
 send(cli_sock,buf,strlen(buf)+1,0);

 pthread_t tid;
 pthread_create(&tid,NULL,run,&cli_sock);

 for(;;)
 {
  printf(">>>");
  gets(buf);
  send(cli_sock,buf,strlen(buf)+1,0);
  if(0 == strcmp("quit",buf))
  {
   printf("退出聊天室!\n");
   return EXIT_SUCCESS;
  }
 }
}

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Qt串口通信開發(fā)之QSerialPort模塊簡(jiǎn)單使用方法與實(shí)例

    Qt串口通信開發(fā)之QSerialPort模塊簡(jiǎn)單使用方法與實(shí)例

    這篇文章主要介紹了Qt串口通信開發(fā)之QSerialPort模塊簡(jiǎn)單使用方法與實(shí)例,需要的朋友可以參考下
    2020-03-03
  • 使用pybind11封裝C++結(jié)構(gòu)體作為參數(shù)的函數(shù)實(shí)現(xiàn)步驟

    使用pybind11封裝C++結(jié)構(gòu)體作為參數(shù)的函數(shù)實(shí)現(xiàn)步驟

    這篇文章主要介紹了用pybind11封裝C++結(jié)構(gòu)體作為參數(shù)的函數(shù)實(shí)現(xiàn)步驟,本文分步驟通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-02-02
  • C語(yǔ)言打印某一年的日歷

    C語(yǔ)言打印某一年的日歷

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言打印某一年的日歷,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-06-06
  • C++11新特性之智能指針(shared_ptr/unique_ptr/weak_ptr)

    C++11新特性之智能指針(shared_ptr/unique_ptr/weak_ptr)

    這篇文章主要介紹了C++11新特性之智能指針,包括shared_ptr, unique_ptr和weak_ptr的基本使用,感興趣的小伙伴們可以參考一下
    2016-08-08
  • C語(yǔ)言實(shí)現(xiàn)漢諾塔游戲

    C語(yǔ)言實(shí)現(xiàn)漢諾塔游戲

    個(gè)人覺得漢諾塔這個(gè)遞歸算法比電子老鼠的難了一些,不過(guò)一旦理解了也還是可以的,其實(shí)網(wǎng)上也有很多代碼,可以直接參考。記得大一開始時(shí)就做過(guò)漢諾塔的習(xí)題,但是那時(shí)代碼寫得很長(zhǎng)很長(zhǎng),也是不理解遞歸的結(jié)果。今天重新來(lái)實(shí)現(xiàn)一下
    2015-03-03
  • 淺談C++模板元編程

    淺談C++模板元編程

    本篇文章主要介紹了淺談C++模板元編程,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-12-12
  • c語(yǔ)言中形參與實(shí)參的關(guān)系解讀

    c語(yǔ)言中形參與實(shí)參的關(guān)系解讀

    這篇文章主要介紹了c語(yǔ)言中形參與實(shí)參的關(guān)系,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • C++中hashmap的一些使用建議

    C++中hashmap的一些使用建議

    由于hashmap不是c++ stl中標(biāo)準(zhǔn)實(shí)現(xiàn),這樣在跨平臺(tái)使用時(shí)就可能會(huì)出現(xiàn)問(wèn)題,下面這篇文章主要給大家介紹了關(guān)于C++中hashmap的一些使用建議,需要的朋友可以參考下
    2023-03-03
  • C/C++?Qt?數(shù)據(jù)庫(kù)與TreeView組件綁定詳解

    C/C++?Qt?數(shù)據(jù)庫(kù)與TreeView組件綁定詳解

    本篇文章主要介紹了QT數(shù)據(jù)庫(kù)與View組件的綁定,通過(guò)數(shù)據(jù)庫(kù)與組件關(guān)聯(lián)可實(shí)現(xiàn)動(dòng)態(tài)展示數(shù)據(jù)庫(kù)中的表記錄。感興趣的小伙伴可以了解一下
    2021-12-12
  • C語(yǔ)言實(shí)現(xiàn)第一次防死版掃雷游戲

    C語(yǔ)言實(shí)現(xiàn)第一次防死版掃雷游戲

    大家好,本篇文章主要講的是C語(yǔ)言實(shí)現(xiàn)第一次防死版掃雷游戲,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下
    2022-01-01

最新評(píng)論