• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
金色洋光
学习是最好的投资
博客园    首页    新随笔    联系   管理     

linuxC网络聊天室简单代码,CSDN博客迁移

学习总结:因为前一段对LINUX –C的学习也对网络编程有一点的认识,通过这一次聊天室的制作,更增加对学习新知识的兴趣。写聊天室时主要遇到的

问题是

1.服务器实现并发功能(接受和发送)

2.实现多客户端连接服务器。

3.怎样识别客户端之间的差别与联系

4.实现多客户端之间的接受和发送。

问题解决方案

1.实现并发服务,我主要用了线程进行接收,通过接收的信息在识别创建发送线程。在服务器主函数中主要管理客户端的连接。

2.在主函数中连接客户端主要是用数组贮存接收成功后(accept函数)的标识符,这样每个客户端都可连接,并且客户端可区分。

3.我用接收成功后的标识符和客户端的用户名进行客户端识别。

4.服务器通过客户端发送过来的字符串进行识别,发送的是个人还是群聊。

这次写的比较简单,代码还可以进行完善和功能添加。

服务器:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <memory.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <error.h> 
#include <netinet/in.h>
#include <arpa/inet.h>
#include<termios.h>

#define MAX_LINE 1024
#define MAX_CLIENT 15

char recvbuf[MAX_LINE]={0};    //传送内容缓冲区
int num=0;              //客户端连接标记
char sendbuf[MAX_LINE]={0};
int client[MAX_CLIENT];
//FD_SETSIZE,1024是tcp最大连接数,client[FD_SETSIZE] 存放有数据请求的客户端;
char name[15][1024]={0};

int FLACE=0;

int findname(char *name1)
{
 int i = 0;
 for(i=0;i<5;i++)
 {
 printf("name[%d]=%s\n",i,name[i]);
 }
 printf("find_name:%s",name1);
 for (i = 0; i < MAX_CLIENT; i++)
 {
    if (client[i]!=-1&&(strcmp((name[i]), name1))==0)     
        return i;
 } 
 return -1;
}
void sendto_one(int *client_num)
{
        char buf[1024]={0};
        char recvname[20] = { 0 };
        char *p = strtok(sendbuf + 3, "\r\n");//TO:3个字符后取出\r\n前的名字
        printf("(p)=%sa\n",p);
        strcpy(recvname, p);
        int sock= findname(recvname);
        if(sock==0)
        {
        memset(buf, 0,MAX_LINE);
        sprintf(buf,"此人没上线\n");
        send(client[*client_num],buf,strlen(buf),0);
        }
        printf("(sock=)%d\n",sock);
        while(1)
        {
           if(sock!=-1&&num==1)
         {
           memset(buf, 0,MAX_LINE);
           sprintf(buf,"FPOM:%s\r\n%s",name[*client_num],sendbuf+4+strlen(p)+2);
           send(client[sock],buf,strlen(buf),0);
           printf("send success\n");
           num=0;
         }
        }
}
void sendto_all(int *client_num)
{ 
 int i,j;
 char buf[1024] = { 0 };
 printf("send.buf=%s\n",sendbuf);
 memset(buf, 0,MAX_LINE);
 sprintf(buf, "FPOM:%s\n%s",name[*client_num],sendbuf);
        j=0;
 printf("sendto_all11.buf=%s\n",buf);
 for(i=0;i<15;i++)
 {
   printf("client[%d]=%d\n",i,client[i]);
 }
 while(1)
 {
  while(j<10)
  {
    if(client[j]!=-1&&num==1) 
    {
      printf("name[j]%s",name[j]);
      send(client[j],buf,MAX_LINE,0);
    }
    printf("send to kehu\n");
    j++;  
  }
  num=0;
 } 
}
void recvwhole(int* client_num)
{
 int n;
 pthread_t tid2,tid3;
 while(1)
 {
    memset(recvbuf, 0,MAX_LINE);//初始化数组
    n=0;
    n=recv(client[*client_num],recvbuf,MAX_LINE,0);
    if(n>0)
    {
      printf("(recv.buf=)%s\n",recvbuf);
      memset(sendbuf, 0,MAX_LINE);//初始化数组
      strcpy(sendbuf,recvbuf);
      num=1;
      printf("(num=)%d,\n(sendbuf:)\n%s\n",num,sendbuf);
    }
    if (!strncmp(sendbuf, "TO:",3))
     {
            printf("发送个人\n");
            pthread_create(&tid2,NULL,(void*)sendto_one,(void*)client_num);
            pthread_detach(tid2);           
     }
     if (!strncmp(sendbuf, "ALL\r\n", 5))
     {
            printf("发送群体\n");
            pthread_create(&tid3,NULL,(void*)sendto_all,(void*)client_num);
            pthread_detach(tid3);
     }
 }
}

int input_name(int *n)
{
 int a,b;
 memset(sendbuf, 0,MAX_LINE);
 //sprintf(sendbuf,"请输入你的姓名:");
 //a=send(client[*n],sendbuf,MAX_LINE,0);
 b=recv(client[*n],name[*n],MAX_LINE,0);
 printf("(name[%d]=)%s\n",*n,name[*n]);
 if(b>0)
 {return 0;}
 else
 {
   input_name(n);
 }  
}


void *pthread_fun(int * client_num)
{
 if(input_name(client_num))
 {
   perror("input name fail");exit(-1);
 }
 char *p;
 pthread_t tid1,tid2,tid3;
 pthread_create(&tid1,NULL,(void*)recvwhole,/);
 pthread_detach(tid1);              
}





int main(int argc,char *argv[])
{
 struct sockaddr_in addr;//保存客户端地址
 socklen_t len;         //保存客户端地址长度
 struct sockaddr_in add2;
 
 int port=8800;
 char addr_p[INET_ADDRSTRLEN];
 int i=0,ii;
 int lfd,cfd;               //套接字
 int a[15];
 
 pthread_t tid1,tid2; //创建线程变量
 
 bzero(&addr,sizeof(addr));//清空地址结构
 addr.sin_family=AF_INET;//使用IP4
 addr.sin_port=htons(port);//端口号
 addr.sin_addr.s_addr=INADDR_ANY;//服务器可以接受任意地址
 
  
 for(i=0;i<MAX_CLIENT;i++)
   {   client[i]=-1;}
 
//1
 if((lfd=socket(AF_INET,SOCK_STREAM,0))==-1)
 {
   perror("fail to socket");exit(1);
 }
 printf("创建套接字成功\n");
 
 //设置端口可重用
 int opt = 1;
 setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));  //将套接字绑定到服务器的网络地址上
 
 
 //2
 if(bind(lfd,(struct sockaddr*)&addr,sizeof(addr))==-1)
 {
 perror("fial to bind");exit(1);
 }
 printf("绑定地址套接字成功\n");
//3
 if (listen(lfd, 10) == -1)
 {  
    perror("fail to listen"); exit(1);
 }
 printf("监听成功\n");
 
 i=0;
 while(i<MAX_CLIENT)  
 {
  ii=i;
  len=sizeof(add2);
  client[i]=accept(lfd,(struct sockaddr*)&add2,&len);
  //printf("\n**%d\n",client[i]);  
  printf("接受成功,i = %d\n",i);
  
  
  printf("create thread\n");
  a[i]=i; 
  if(pthread_create(&tid1,NULL,(void*)pthread_fun,&a[i])!=0)
  {
    perror("create success");exit(-1);
  }
  pthread_detach(tid1);
  i++;  
  if(ii<i)
  {
    inet_ntop(AF_INET,&addr.sin_addr,addr_p,sizeof(addr_p));////将客户端地址转换为字符串
    printf("IP=%s,port=%d\n",addr_p,ntohs(addr.sin_port)); 
  } 
客户端:

#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>

#define MAX_LINE 1024

char buf[MAX_LINE];
int port=8800;
char name[200]={0};
int FLACE=0;

void fun_all(int sockfd)
{
 char sendbuf[1024]={0};
 sprintf(sendbuf,"ALL\r\n",5);
 printf("\n");getchar();
 printf("输入聊天内容:\n");
 fgets(sendbuf+strlen(sendbuf),100,stdin);
 //scanf("%s",sendbuf+5);
 //sprintf(sendbuf+strlen(sendbuf),"\n");
 printf("(all      sendbuf)=%s\n",sendbuf);
 if(send(sockfd,sendbuf,strlen(sendbuf),0)<=0)
 {
 printf("send error\n");close(sockfd);exit(1);
 }
}
void fun_one(int sockfd)
{ 
 char sendbuf[1024] = {0};
 char name3[20] ;
 printf("输入聊天对象:");getchar();
 memset(name3,0,20);
 fgets(name3,20,stdin);
   printf("(name3)\n%s",name3);
   sprintf(sendbuf,"TO:%s\r\n",name3); 
 printf("输入聊天内容:\n");
 fgets(sendbuf+strlen(sendbuf),100,stdin);
 //printf("(sendbuf)=%s\n",sendbuf);
 //sprintf(sendbuf+strlen(sendbuf),"\r"); 
 if(send(sockfd,sendbuf,strlen(sendbuf),0) <= 0)
 {    
 printf("send err\n");  
 close(sockfd);
    exit(1);
 }
 
}  
void menu()
{
 printf("^^^^^^^^^^^^^^^^^^^^\n");
 printf("1.私聊模式(发送to)\n");
 printf("2.群聊模式(发送all)\n");
 printf("~~~~~~~~~~~~~~~~~~~~\n");
}

void *fun(int *sock)
{
 int sockfd=*sock;
 int n;
 char *p,*q;
 char name2[20]={0};
 
 while(1)
 { n=0;
  memset(buf,0,MAX_LINE);//初始化数组
  n=recv(sockfd,buf,MAX_LINE,0);
  if(n>0)
  {
  printf("\n\n接受到:");
  printf("\n*************\n%s******************\n",buf);
  }  
  if(n<=0)
  {   
  printf("recv failed\n");   
  exit(1);
  }
 }

}



int main(int argc,char *argv[])
{
 int l_fd;//套接字
 struct sockaddr_in addr;
 char sendbuf[1024] = {0};
 char str[6] = {0};
 
 int n;
 pthread_t pid1; 
 bzero(&addr,sizeof(addr));
 addr.sin_family=AF_INET;
 inet_pton(AF_INET,"10.25.100.*",&addr.sin_addr);
 addr.sin_port=htons(port);
 
 if((l_fd=socket(AF_INET,SOCK_STREAM,0))==-1)
 {
   perror("fail to creat socket");exit(1);
 }
 printf("创建套接字成功\n");
 if(connect(l_fd,(struct sockaddr *)&addr,sizeof(addr)) == -1)
 {
   perror("fail to connect");exit(1);
 }
 printf("connect success\n");
 
 memset(name,0,20);    
 printf("请输入你的姓名:");    
 scanf("%s",name);
 sprintf(sendbuf,name); //把格式化的数据写入某个字符串,"LOGIN\r\n%s\r\n\r\n"
 send(l_fd,sendbuf,strlen(sendbuf),0);
 //printf("sendbuf=%s\n",sendbuf);
 
 pthread_create(&pid1,NULL,(void*)fun,(void*)&l_fd);
 pthread_detach(pid1);
 
 while(1)
 {
    menu();
    memset(str,0,6);      
    scanf("%s",str);
    if(!strcmp(str,"all"))
    {
        printf("群聊模式\n");       
      fun_all(l_fd);       
      continue;      
    }       
    else if(!strcmp(str,"to"))
    {       
      printf("私聊模式\n");       
      fun_one(l_fd);       
      continue;      
    }  
    else
      printf("请重新输入:");
 
  }
  wait(NULL);
  close(l_fd);
   return 0;
 }
   
 } 
  
 return 0;
}  

 

每一成功的背后都有个人的努力和家人的支持
posted @ 2020-10-18 20:15  金色洋光  阅读(312)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3