UCsocket 编程,简单聊天室实现

/*
   TCP聊天室 客户端
   */
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<string.h>
#include<signal.h>
#include<netinet/in.h>
//一些准备工作
char* IP = "172.30.11.104";//127.0.0.1 本机地址,回送地址,用于网络软件测试 或本机通信
short PORT = 10222; // 端口
typedef struct sockaddr SA; //用做类型转换
int sockfd= 0;
char name[20] = {};
//1 启动客户端,连接服务器
void init()
{
 printf("聊天室客户端开始启动。。\n");
 sockfd = socket(PF_INET,SOCK_STREAM,0);
 struct sockaddr_in addr;
 addr.sin_family = PF_INET;
 addr.sin_port = htons(PORT);
 addr.sin_family.s_addr = inet_addr(IP);
 //连接
 if(connect(sockfd,(SA*)&addr,sizeof(addr)) ==-1)
 {
  perror("无法连接服务器");
  printf("客户端启动失败\n");
  exit(-1);
 }
 printf("客户端启动成功\n");
}
//2 开始通信
void start()
{
 //主要是用来发送消息
 //发消息之前,启动一个线程 用来接收消息
 pthread_t pid;
 void* recv_thread(void* );
 pthread_create(&pid,0,recv_thread,0);
 while(1)
 {
  char buf[100] = {};
  scanf("%s",buf);//读取客户的输入
  char msg[200] = {};
  sprintf(msg,"%s 说:%s",name,buf);
  send(sockfd,msg,strlen(msg),0);
 }
}
//线程函数 ,用来接收消息
void* recv_thread(void* p)
{
 char buf[200] = {};
 if(recv(sockfd,buf,sizeof(buf),0)<=0)
 {
  return ; //结束线程
 }
 printf("%s\n",buf);
}
void sig_close(int signo)
{//关闭客户端socket
 close(sockfd);
 exit(0);
}
int main()
{
 signal(SIGINT,sig_close);
 printf("请输入昵称:\n");
 scanf("%s",name);
 init(); //启动客户端 连接到服务器
 send(sockfd,name,strlen(name),0);
 start();


}

 

/*
   TCP聊天室服务器
   */
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<string.h>
#include<signal.h>
#include<netinet/in.h>
//一些准备工作
char* IP = "172.30.11.104";//127.0.0.1 本机地址,回送地址,用于网络软件测试 或本机通信
short PORT = 10222; // 端口
typedef struct sockaddr SA; //用做类型转换
struct client
{
 char name[20];//记录客户端的昵称
 int fds; //客户端的socket描述符
};
struct client c[100] =  {0};//记录客户端的结构体数组 最多记录了100个
int size = 0; //记录客户端的个数,也可以用来遍历客户端结构体
int sockfd = 0; //服务器的sockt
//1 初始化服务器的网络,创建socket
void init()
{
 printf("聊天室服务器开始启动……\n");
 sockfd = socket(PF_INET,SOCK_STREAM,0);
 if(sockfd == -1) perror("socket创建失败,服务器启动失败"),exit(-1);
 struct sockaddr_in addr;
 addr.sin_family = PF_INET;
 addr.sin_port = htons(PORT);
 addr.sin_addr.s_addr = inet_addr(IP);
 if(bind(sockfd,(SA*)&addr,sizeof(addr))==-1)
 {
  perror("绑定失败");
  printf("服务器启动失败\n");
  exit(-1);
 }
 printf("绑定成功\n");
 if(listen(sockfd,100) == -1)
 {
  perror("设置监听失败");
  printf("服务器启动失败\n");
  exit(-1);
 }
 printf("设置监听成功\n");
 //等待客户端连接到另一个函数中
 printf("初始化服务器成功\n");
}
/*
  辅助函数,用来分发消息
 */
void sendMsgToAll(char* msg)
{
 int i = 0;
 for( i = 0;i<size;i++)
 {
  printf("sendto %d\n",c[i].fds);
  send(c[i].fds,msg,strlen(msg),0);
 }
}

//线程函数,用来接收客户端发来的消息,并且把消息发送给所有客户端
void* service_thread(void* p)
{
 int fd = *(int*)p; //拿到客户端的socket描述符
 printf("pthread = %d",fd); //线程对应客户端
 //保留客户端的信息
 c[size].fds = fd;
 char name[20] = {};
 if(recv(fd,name,sizeof(name),0)>0) //接收昵称
 {
  strcpy(c[size].name,name);
 }
 size++;
 //先群发一条消息,表示欢迎 也可以通知其他客户端有人连接了 进入聊天室
 char tishi[100];
 sprintf(tishi,"热烈欢迎%s登陆聊天室。。",name);
 //群发消息
 sendMsgToAll(tishi);
 //通信部分,收发消息
 while(1)
 {
  char buf[200] = {};
  if(recv(fd,buf,sizeof(buf),0) == 0)
  {
   printf("fd = %d quit\n",fd);
   //有客户端断开
   int i;
   char name[20] = {};
   for(i= 0;i<size;i++)
   {
    if(c[i].fds == fd)
    {
     strcpy(name,c[i].name);
     c[i].fds = c[size-1].fds;
     strcpy(c[i].name,c[size-1].name);
    }
   }
   size--;
   printf("quit->fd=%d\n",fd);
   char msg[100] = {};
   sprintf(msg,"欢送 %s 离开聊天室,再见\n",name);
   sendMsgToAll(msg);
   close(fd);
   return ; //客户端退出  结束线程
  }
  sendMsgToAll(buf); //成功接收到消息,就直接所有的客户端
 }
}

//等待客户端连接,启动服务器服务
void service()
{
 printf("服务器开始服务\n");
 while(1)
 {
  struct sockaddr_in fromaddr; //存储客户端的通信地址
  socklen_t len = sizeof(fromaddr);
  int fd = accept(sockfd,(SA*)&fromaddr,&len);
  if(fd == -1)
  {
   printf("客户端连接出错\n");
   continue;
  }
  //如果客户成功连接
  //开启线程,为该客户端进行服务
  printf("fd =%d\n",fd);
  pthread_t pid;
  pthread_create(&pid,0,service_thread,&fd);
 }
}
void sig_close(int signo)
{ //关闭socket
 int i = 0;
 for(;i<size;i++)
 {
  if(c[i].fds!=0)
   close(c[i].fds);
 }
 close(sockfd);//服务器的socket;
 printf("服务器已经关闭\n");
 exit(0);

}
int main()
{
 signal(SIGINT,sig_close);//做好善后工作
 init();
 service();
 return 0;
}

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值