Home Article Linux 系统编程 TCP 多人聊天室V1.1

Linux 系统编程 TCP 多人聊天室V1.1

Release time:2020-07-24 20:32:38 Author:admin Reading volume:74

/* tcp 网络聊天 程序 v2.1
 * 功能:1.多个客户端的登录,服务器转发客户端的消息
 *   2.客户端查看当前登录的所有客户端
 *   3.按登录名点对点发消息
 *   4.群发消息
 *   5.登出客户端
 * 已解决问题:1.基本实现所有功能
 *     2.解决服务器终止重新启动时ip地址已经被使用的问题
 *     3.第一个登陆的客户端先点对点发送消息时再群发失灵
 *           4.输入消息类型错误时会不断接受乱码
 *  待解决问题: 服务器先终止时所有客户端不断接收到消息
 *
 * 时间: 2020年4月29日
 */

server.c

#include
#include
#include
#include
#include
#include
#include <sys/socket.h>
#include <arpa/inet.h>
#include "chatroom.h"
#include "link.h"

#define PORT 1234
#define IP "127.0.0.1"

Msg msg;
LinkList fl = {0,NULL,NULL};

void showMsg(Msg* msgp)
{
 printf("type: %d,from:%s, to:%s,data : %s ",msgp->type,msgp->from,msgp->to,msgp->data);
}

void *process(void  *arg)
{
 int c_sockfd = *(int *)arg;
 printf("c_sockfd:%d ",c_sockfd);
 while(1)
 {
  memset(&msg,0,sizeof(Msg));
  read(c_sockfd,&msg,sizeof(Msg));
  if(msg.type == 0)
  {
   break;
  }
  showMsg(&msg);
  //forward
  switch(msg.type)
  {
   case 1:
    addFirst(&fl, msg.from, c_sockfd);
    travel(&fl);
    strcpy(msg.data,"login success!");
          write(c_sockfd,&msg,sizeof(Msg));
    break;
   case 2:
    travel(&fl);
    count = fl.len;
    while(count--)
    {
     strcpy(msg.data,tra[count]);
     write(c_sockfd,&msg,sizeof(Msg));
    }

    break;
   case 3:
    {
    int sockfd = get(&fl,msg.to);
    write(sockfd,&msg,sizeof(Msg));
    break;
    } // 必须重新定义 不然会出错
   case 4:
   {
   Node* ptr = fl.head;
   while(ptr)
   {
    if(strcmp(msg.from,ptr->to) != 0)
    {
     write(ptr->sockfd,&msg,sizeof(Msg));
    }
    ptr = ptr->next;
   }
    break;
   } 
   case 5:
    delete(&fl,msg.from);
    
    break;
  }
 }
 shutdown(c_sockfd,SHUT_RDWR);
}

int main()
{
 int s_sockfd = socket(AF_INET,SOCK_STREAM,0);
 if (s_sockfd == -1)
 {
  perror("socket error!");
  exit(1);
 }

 struct sockaddr_in s_addr;
 s_addr.sin_family = AF_INET;
 s_addr.sin_port = htons(PORT);
 s_addr.sin_addr.s_addr = inet_addr(IP);

 socklen_t addrlen = sizeof(struct sockaddr);

// reuse ip address port
 int opt = 1;
 setsockopt(s_sockfd,SOL_SOCKET,SO_REUSEADDR,&opt ,sizeof(opt));
 if (bind(s_sockfd,(struct sockaddr*)(&s_addr),addrlen) == -1)
 {
  perror("bind error!");
  exit(1);
 }
 printf("bind successful! ");

 if(listen(s_sockfd,10) == -1)
 {
  perror("listen error!");
  exit(1);
 }

 struct sockaddr_in c_addr;
 while(1)
 {
  int c_sockfd = accept(s_sockfd,(struct sockaddr*)(&c_addr),&addrlen);
  if (c_sockfd == -1)
  {
   perror("accept error!");
   exit(1);
  }
  pthread_t pid;
  if (pthread_create(&pid,NULL,process,&c_sockfd) == -1)
  {
   perror("pthread_create error!");
   exit(1);
  }
 }
 close(s_sockfd);
 pthread_exit(0);
}

link.c

#include
#include "link.h"
#include
#include

Node* createNode(char to[],int sockfd)
{
 Node *ptr;
 ptr = malloc(sizeof(Node));
 if(ptr == NULL)  exit(1);
 strcpy(ptr->to,to);
 ptr->sockfd = sockfd;
 ptr->prev = NULL;
 ptr->next = NULL;
 return ptr;
}

void addFirst(LinkList * listListPtr,char to[],int sockfd)
{
 Node *ptr =createNode(to,sockfd);
 if (listListPtr->len)
 {
  ptr->next = listListPtr->head;
  listListPtr->head->prev =ptr;
  listListPtr->head = ptr;
 }
 else
 {
  listListPtr->head = ptr;
  listListPtr->tail = ptr;
 }
 listListPtr->len++;
}
int get(LinkList *flp,char to[])
{
 Node *ptr = flp->head;
 while(ptr)
 {
  if (strcmp(to,ptr->to)==0)
  {
   return ptr->sockfd;
  }
  ptr=ptr->next;
 }
 return -1;
}

void delete(LinkList * flp,char to[])
{
 Node *ptr = flp->head,*prevPtr = NULL,*nextPtr=NULL;
 while(ptr)
 {
  if (strcmp(to,ptr->to)==0)
  {
   prevPtr = ptr->prev;
   nextPtr = ptr->next;
   if(prevPtr == NULL)
   {
    flp->head = nextPtr;
   }
   else if(nextPtr == NULL)
   {
    flp->tail = prevPtr;
   }
   else{
    prevPtr->next = nextPtr;
    nextPtr->prev = prevPtr;
   }
   free(ptr);
   flp->len--;
  }
  ptr = ptr->next;
 }
}

void travel(LinkList * flp)
{
 int i = flp->len;
 Node *ptr = flp->head;
 printf("------------------ ");
 printf("size=%d ",flp->len);
 while(i--)
 {
  printf("to:%s,sockfd:%d ",ptr->to,ptr->sockfd);
  strcpy(tra[i],ptr->to);
  fd[i]=ptr->sockfd;
  ptr=ptr->next;
 }
 printf("------------------- ");
}
/*  ------ test link-------
void main()
{
 LinkList list1 = {NULL,0,NULL};

 addFirst(&list1,"mayun",1);
 addFirst(&list1,"mahuateng",2);
 addFirst(&list1,"didi",3);
 travel(&list1);

 delete(&list1,"didi");
 travel(&list1);

 delete(&list1,"mayun");
 travel(&list1);
}
-------------------------*/
link.h

#ifndef LINK_H_
#define LINK_H_

typedef struct {
 char to[50];
 int sockfd;
 struct Node *prev;
 struct Node *next;
}Node;

typedef struct{
 int len;
 Node *head;
 Node *tail;
}LinkList;

char tra[100][10];
int  fd[100];
int  count;
#endif

chatroom.h

#include "link.h"
#ifndef CHATROOM_H
#define CHATROOM_H

enum MsgType{
 LOGIN = 1,
 USERLIST = 2,
 SENDMSG = 3,
 BROADCAST = 4,
 LOGOUT = 5
};

typedef struct{
 char type;
 char from[10];
 char to[10];
 char data[1000];

}Msg;

endif
client.c

 #include
  2 #include
  3 #include
  4 #include
  5 #include <sys/socket.h>
  6 #include <arpa/inet.h>
  7 #include "chatroom.h"
  8
  9 #define PORT 1234
 10 #define IP "127.0.0.1"
 11
 12 Msg msg;
 13 char me[10];
 14
 15 void *readMsg(void *arg)
 16 {
 17     int s_sockfd = *(int *)arg;
 18     while(1)
 19     {
 20         read(s_sockfd,&msg,sizeof(Msg));
 21         printf("receieved %s from %s ",msg.data,msg.from);
 22         usleep(1);
 23     }
 24 }
 25
 26 void * sendMsg(void *arg)
 27 {
 28     int s_sockfd = *(int *)arg;
 29     int choose = 0;
 30     while(1)
 31     {
 32         printf("1.login 2.list 3.send 4.broadcast 5.logout ");
 33         scanf("%d",&choose);
 34         if (choose == 0)
 35         {
 36             printf("input invalid! ");
 37             scanf("%s",me);
 38             continue;
 39         }
 40         switch(choose)
 41         {
 42             case 1:
 43                 msg.type = LOGIN;
 44                 printf("input your name: ");
 45                 scanf("%s",msg.from);
46                 strcpy(me,msg.from);
 47                 write(s_sockfd,&msg,sizeof(Msg));
 48                 break;
 49             case 2:
 50                 msg.type = USERLIST;
 51                 write(s_sockfd,&msg,sizeof(Msg));
 52                 break;
 53             case 3:
 54                 msg.type = SENDMSG;
 55                 printf("input the target: ");
 56                 scanf("%s",msg.to);
 57                 printf("input the msg: ");
 58                 scanf("%s",msg.data);
 59                 write(s_sockfd,&msg,sizeof(Msg));
 60                 break;
 61             case 4:
 62                 msg.type = BROADCAST;
 63                 strcpy(msg.from,me);
 64                 printf("input the msg: ");
 65                 scanf("%s",msg.data);
 66                 write(s_sockfd,&msg,sizeof(Msg));
 67                 break;
 68             case 5:
 69                 msg.type = LOGOUT;
 70                 strcpy(msg.from,me);
 71                 write(s_sockfd,&msg,sizeof(Msg));
 72                 exit(0);
 73         }
 74     }
 75 }
 76 int main()
 77 {
 78     int s_sockfd = socket(AF_INET,SOCK_STREAM,0);
 79     if (s_sockfd == -1)
 80     {
 81         perror("socket error!");
 82         exit(1);
 83     }
 84     int addrlen = sizeof(struct sockaddr);
 85     struct sockaddr_in s_addr;
86     memset(&s_addr,0,addrlen);
 87     s_addr.sin_family = AF_INET;
 88     s_addr.sin_port = htons(PORT);
 89     s_addr.sin_addr.s_addr = inet_addr(IP);
 90
 91     if (connect(s_sockfd,(struct sockaddr*)(&s_addr),addrlen) == -1)
 92     {
 93         perror("connect error!");
 94         exit(1);
 95     }
 96
 97     pthread_t pid1,pid2;
 98     if (pthread_create(&pid1,NULL,readMsg,&s_sockfd) == -1)
 99     {
100         perror("pthraed 1 create error!");
101         exit(1);
102     }
103     if (pthread_create(&pid2,NULL,sendMsg,&s_sockfd) == -1)
104     {
105         perror("pthread 2 create error!");
106         exit(1);
107     }
108
109     pthread_join(pid1,NULL);
110     pthread_join(pid2,NULL);
111
112     return 0;
113 }

 

 

 

 

支付宝打赏 微信打赏
  
I want to comment

Search

Leave a message
http://blog.rjxj513.com/
User login
You have not written any reviews yet!
You have commented!
Can only praise once!
You have a collection!