Linux的shell聊天室

serv.c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <pthread.h>
#include <time.h>
int serverfd;//服务器socket
int clientfd[100];//客户端的socketfd,100个元素,clientfd[0]~clientfd[99]
int size =50;//用来控制进入聊天室的人数为50以内
char* IP = "127.0.0.1";//主机ip地址
short PORT = 6666;//端口号
typedef struct sockaddr meng;
time_t nowtime;

void init(){
 serverfd = socket(PF_INET,SOCK_STREAM,0);
 if (serverfd == -1){
 	perror("创建socket失败");
	exit(-1);}

//为套接字设置ip协议 设置端口号  并自动获取本机ip转化为网络ip
	struct sockaddr_in addr;//存储套接字的信息
	addr.sin_family = PF_INET;//地址族
	addr.sin_port = htons(PORT);//设置server端端口号,你可以随便设置,当sin_port = 0时,系统随机选择一个未被使用的端口号
	addr.sin_addr.s_addr = inet_addr(IP);//把127.0.0.1改为自己的server端的ip地址,当sin_addr = INADDR_ANY时,表示从本机的任一网卡接收数据
//绑定套接字
 if (bind(serverfd,(meng*)&addr,sizeof(addr)) == -1){
	perror("绑定失败");
	exit(-1);
	}
 if (listen(serverfd,100) == -1){//监听最大连接数
	perror("设置监听失败");
	exit(-1);   }
}

void SendAll(char* msg){
 int i;
 for (i = 0;i < size;i++){
	if (clientfd[i] != 0){
	printf("发送给%d\n",clientfd[i]);
	printf("发送的信息是: %s\n",msg);
//写入文件
char buf[1024];
FILE *logs = fopen("log.txt", "a+");
if(logs== NULL)
{	printf("open file erroe: \n"); }
else{ time(&nowtime);
sprintf(buf, "进入时间:%s\tIP地址:%s\n",ctime(&nowtime),IP);
fputs(buf,logs);
sprintf(buf, "所发信息:%s\n",msg);
fputs(buf,logs);
fclose(logs);	}
send(clientfd[i],msg,strlen(msg),0); }
}
}

void* server_thread(void* p){
 int fd = *(int*)p;
 int i,ll;
char buf[100] = {};
 printf("pthread = %d\n",fd);
 while(1){
	if ((ll=recv(fd,buf,sizeof(buf),0))<= 0){
	   for (i = 0;i < size;i++){
		if (fd == clientfd[i]){
		clientfd[i] = 0;
		break;   }    }
	printf("退出:fd = %d 退出了。\n",fd);
char buf[1024];
FILE *logs = fopen("log.txt", "a");
if(logs== NULL)
   {	printf("open file erroe: \n");   }
else{        time(&nowtime);
		sprintf(buf, "退出时间:%s\tIP地址:%s\n",ctime(&nowtime),IP);
		fputs(buf,logs);
		  }
	pthread_exit(0);
 }
 	//把服务器接受到的信息发给所有的客户端
buf[ll]=0;	
SendAll(buf);
	}
}

void server(){
	printf("服务器启动\n");
	while(1){
	struct sockaddr_in fromaddr;
	socklen_t len = sizeof(fromaddr);
	int fd = accept(serverfd,(meng*)&fromaddr,&len);
//调用accept进入堵塞状态,等待客户端的连接
	if (fd == -1){
	 printf("客户端连接出错...\n");
	 continue;  }
	int i = 0;
 	for (i = 0;i < size;i++){
	  if (clientfd[i] == 0){
	//记录客户端的socket
		clientfd[i] = fd;
		printf("线程号= %d\n",fd);//
 	//有客户端连接之后,启动线程给此客户服务
		pthread_t tid;
		pthread_create(&tid,0,server_thread,&fd);
		break;  }
	if (size == i){
	//发送给客户端说聊天室满了
	char* str = "对不起,聊天室已经满了!";
	send(fd,str,strlen(str),0);
	close(fd);	}
  }
  }
}

int main(){
	init();
	server();
}

sem_thr2.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <fcntl.h>
#include <string.h>
#include <sys/ipc.h>
#include <semaphore.h>
#define SEM "prt"
#define CLEAR() printf("\033[2J")  
#define MOVETO(x,y) printf("\033[%d;%dH", (x), (y))  
int lock_var,xid=1,val;
time_t end_time;
sem_t *sem;
void *pthread1(int *x);
void print();

int main(int argc, char *argv[])
{
	pthread_t id[6];
	pthread_t mon_th_id;
	int ret=0,num;
	end_time = time(NULL)+48;
        puts("Plaese input NUM:");
	scanf("%d",&num);

	sem=sem_init(SEM,0,1);
   // system("clear");
	CLEAR();
	while(ret<num){
	if(pthread_create(&id[ret],NULL,pthread1, &ret)!=0)
		{	perror("pthread_create"); sleep(1); exit(1);}
 	ret++;	sleep(1);}
	//pthread_join(id[5],NULL);
	MOVETO(1,16);

	printf("现在系统时间:");

	while(end_time>time(NULL))
	{   print(); sleep(1);
	}
	MOVETO(28,16);
	puts("---Main线程--END---\n");
 	
//	pthread_join(id2,NULL);

	exit(0);
}

void *pthread1(int *x)
{
	int i,n,v;
	char disp[120];
        memset(disp,0,120);
	n=*x;
	//	while(time(NULL) < end_time){
		MOVETO(n*4,4);
                printf("线程ID号=%u, 第 %d 号线程开始运行!。。。\n",pthread_self(),*x);
		for(i=0;i<20-n;i++){
			sem_wait(sem); 
			//print(n,i); 
		MOVETO(n*4+2,4);  sem_getvalue(sem,&v);
		printf("===>>第 %d 号线程%d次进入临界区操作,信号量值=%d \n", n,i,v);
		if(n%2==1) 
		 	{ strcat(disp,"###");MOVETO(n*4+1,4); puts(disp); }
		else
			{ strcat(disp,"**");MOVETO(n*4+1,4); puts(disp);}	
		//close(stdout); 
		sem_post(sem);	
		if(n%2==1) sleep(1);
		else sleep(2); 
		}
		// printf("pthread1:lock_var=%d\n",lock_var);
		MOVETO(n*4+2,4); printf("===>>线程ID号=%u, 第 %d 号线程已正常结束!。。。\n",pthread_self(), n);
		//sleep(1);
	}

 
void print()
{	time_t tmp;  
//    	struct tm *tmp_ptr = NULL;  
//          time(&tmpcal_ptr);  
	time(tmp);   两种取值方法均可以  
    // printf("tmpcal_ptr=%d\n", tmpcal_ptr);  
	sem_wait(sem); 
	MOVETO(1,32);  
 //   	tmp_ptr = gmtime(&tmpcal_ptr);  
	printf(" %s \n",ctime(&tmp)); 
	sem_post(sem);
}

client.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <time.h>
int clientfd2;		//客户端socket
char* IP = "127.0.0.1";	//服务器的IP
short PORT = 6666;	//服务器服务端口
typedef struct sockaddr meng;
char name[30];		//设置支持的用户名长度
time_t nowtime;
void* recv_thread(void*);
void init(){
clientfd2 = socket(PF_INET,SOCK_STREAM,0);//创建套接字
struct sockaddr_in addr;	//将套接字存在sockaddr_in结构体中
addr.sin_family = PF_INET;	//地址族
addr.sin_port = htons(PORT);//端口号 可随意设置,不过不可超过规定的范围
addr.sin_addr.s_addr = inet_addr(IP);//inet_addr()函数将点分十进制的字符串转换为32位的网络字节顺序的ip信息
//发起连接
if (connect(clientfd2,(meng*)&addr,sizeof(addr)) == -1){
	perror("无法连接到服务器");
	exit(-1);	}
	printf("客户端启动成功\n");
}

void start(){
pthread_t id;
//创建一个线程用于数据的接收,一个用于数据的发送
pthread_create(&id,0,recv_thread,0);
char buf2[100] = {};
sprintf(buf2,"%s进入了群聊",name);
time(&nowtime);
printf("进入的时间是: %s\n",ctime(&nowtime));
send(clientfd2,buf2,strlen(buf2),0);
char buf[100] = {};
char msg[100] = {};
while(1){
	gets(buf);
	sprintf(msg,"%s发送的信息是:%s",name,buf);
	send(clientfd2,msg,strlen(msg),0);
	if (strcmp(buf,"quit") == 0){
	memset(buf2,0,sizeof(buf2));//初始化
	sprintf(buf2,"%s退出了群聊",name);
	send(clientfd2,buf2,strlen(buf2),0);
	break;
	}
	}
	close(clientfd2);
}

void* recv_thread(void* p){
int ll;
char buf[100] = {};
	while(1){
	if ((ll=recv(clientfd2,buf,sizeof(buf),0)) <= 0)
	break;
	buf[ll]=0;
	printf("%s\n",buf);
	}
exit(1);
}

int main(){
 init();
 printf("请输入用户名:");
 scanf("%s",name);
 printf("\n\n*****************************\n");
 printf("欢迎%s 进入群聊\n",name);
 printf("  输入quit 退出\n");
 printf("\n*****************************\n\n");
 start();
 return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值