C語言實現(xiàn)簡易網(wǎng)絡聊天室
更新時間:2021年06月30日 17:23:30 作者:菠蘿小馬哥
這篇文章主要為大家詳細介紹了C語言實現(xiàn)簡易網(wǎng)絡聊天室,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
本文實例為大家分享了C語言實現(xiàn)網(wǎng)絡聊天室的具體代碼,供大家參考,具體內(nèi)容如下
業(yè)務邏輯:
1、客戶端注冊名字
2、告訴所有在線的客戶端,XXX進入聊天室
3、新建一個線程為該客戶端服務,隨時接收客戶端發(fā)送來的消息
4、當接收到一個客戶端的消息時,向每一個客戶端轉(zhuǎn)發(fā)一份(群聊)
5、同時在線人數(shù)最多50人
任何客戶端可以隨意隨時進入或退出客戶端
服務端代碼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
// 服務器端口號
#define PORT 5566
// 緩沖區(qū)大小
#define BUF_SIZE 4096
// 重定義socket地址類型
typedef struct sockaddr* SP;
// 客戶端結(jié)構(gòu)體
typedef struct Client
{
int sock;//socket 標識符
pthread_t tid; //線程ID
char name[20];
struct sockaddr_in addr;
}Client;
// 定義50個存儲客戶端的結(jié)構(gòu)變量
Client clients[50];
// 定義信號量用于限制客戶端的數(shù)量
sem_t sem;
// 信號處理函數(shù)
void sigint(int num)
{
for(int i=0; i<10; i++)
{
if(clients[i].sock)
{
pthread_cancel(clients[i].tid);//銷毀線程
}
}
debug("服務器退出!");
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進入聊天室!!!",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("注冊信號處理函數(shù)成功!");
sem_init(&sem,0,CLIENT_MAX);
debug("初始化信號量成功!");
int svr_sock = socket(AF_INET,SOCK_STREAM,0);
if(0 > svr_sock)
{
error("socket");
}
debug("創(chuàng)建socket對象成功!");
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("準備通信地址成功!");
if(bind(svr_sock,(SP)&svr_addr,addrlen))
{
error("bind");
}
debug("綁定socket對象和通信地址成功!");
if(listen(svr_sock,10))
{
error("listen");
}
debug("設置監(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("服務器正在升級,請稍候登錄!\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("服務器正在升級,請稍候登錄!\n");
return EXIT_SUCCESS;
}
char buf[BUF_SIZE] = {};
printf("請輸入你的眤稱:");
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;
}
}
}
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C語言字符串函數(shù)操作(strlen,strcpy,strcat,strcmp)詳解
大家好,本篇文章主要講的是C語言字符串函數(shù)操作(strlen,strcpy,strcat,strcmp)詳解,感興趣的同學趕快來看一看吧2021-12-12

