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;
}