聊天小项目(三)转发消息到其他客户端

客户端A发送消息,服务端转发消息给其他客户端。

服务端;

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
#include <pthread.h>
#include <fcntl.h>

#define LISTENQ 2       //最大监听队列
#define PORT 5000        //监听端口
#define MAXFD 2          //最大的在线用户数量

static int maxi = 0;       //maxi表示当前client数组中最大的用户的i值

typedef struct sockNode SOCKNODE;
struct sockNode
{
    int fd;
    struct sockNode *pNext;  
};

SOCKNODE sockList; // 全局的套接字链表

void initList(SOCKNODE *sockList)
{
    sockList = (SOCKNODE *)malloc(sizeof(SOCKNODE));
    sockList->pNext = NULL;
    sockList->fd = 0;
}

void insertList(SOCKNODE *sockList, SOCKNODE *newSock) //头部插入链表
{
    SOCKNODE *p = sockList;
    while(p->pNext != NULL)
    {
        p = p->pNext;
    }
    p->pNext = newSock;
}

void transmit(int fd, char *buffer)
{
    SOCKNODE *sock = &sockList;
	sock = sock->pNext; // 第一个节点
	while(sock->fd != fd || sock->pNext != NULL) //相邻
	{
	    if(sock->fd == fd && sock->pNext != NULL) // 满足while第一个条件,跳过,第二条件,执行
	         sock = sock->pNext;
	    strcat(buffer, "from othgers!");
	    send(sock->fd, buffer, strlen(buffer),0);
	    if(sock->pNext == NULL)// 到达末尾
	        break;
	    else
	        sock = sock->pNext;

    }
}

void recvandsend(void)           //监听转发线程入口函数
{
    int index=0;
    int nbytes=0;
 
    char buffer[1024];
    int  len;
    int  outindex=0;
    printf("receive socket and return message!\n");
	while(1)
    {
        SOCKNODE *sock = &sockList;
        while(sock->pNext != NULL)
        {
            sock = sock->pNext;
            memset(buffer, 0, sizeof(buffer));
	        nbytes = 0;            
	        nbytes = recv(sock->fd, buffer, sizeof(buffer),0);
	        if(nbytes > 0) // 在某个套接字有消息进来
	        {
	            buffer[nbytes] = '\0';
	            printf("%s\n", buffer);
	            transmit(sock->fd, buffer);
	        }
	    }
    }
    pthread_exit(NULL);
    exit(1);
}

int  closeConnection(int sockfd)
{
    char buffer[1024];
    memset(buffer, 0 ,sizeof(buffer));
    strncpy(buffer, "close", sizeof("close"));
    if(write(sockfd, buffer, sizeof(buffer)) == -1)
        return 1;
    else
        return 0;
}

int  connectSucceeddMess(int sockfd)
{
    
    char buffer[1024];
    memset(buffer, 0 ,sizeof(buffer));
    strncpy(buffer, "SERVER : welecome to this chat room!", sizeof("SERVER : welecome to this chat room!"));
    if(write(sockfd, buffer, sizeof(buffer)) == -1)
        return 1;
    else
        return 0;
}

int main(int argc, char *argv[])
{
    struct sockaddr_in server_addr;
    struct sockaddr_in client_addr;
    int        sin_size;
    int        sockfd, new_fd;
    int        thr_id;         /* thread ID for the newly createdthread */
    pthread_t  p_thread;       /* thread's structure                     */
    SOCKNODE *sockNew;
    char buffer[1024];
    int nbytes=0;
    int flags;
    initList(&sockList); // 初始化套接字链表
     
    if(argc != 1)
    {
        fprintf(stderr,"Usage:%sportnumber\a\n",argv[0]);
        exit(1);
    }
 
    /* 服务器端开始建立 socket 描述符 */
    if((sockfd = socket(AF_INET,SOCK_STREAM,0))==-1)
    {
        fprintf(stderr,"Socketerror:%s\n\a",strerror(errno));
        exit(1);
    }
 
    /* 服务器端填充 sockaddr 结构 */
    bzero(&server_addr,sizeof(struct sockaddr_in));
    server_addr.sin_family=AF_INET;
    server_addr.sin_addr.s_addr=htonl(INADDR_ANY);
 
    server_addr.sin_port=htons(PORT);
    /* 捆绑 sockfd 描述符 */
    if(bind(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1)
    {
        fprintf(stderr,"Binderror:%s\n\a",strerror(errno));
        exit(1);
    }
    printf("Server Port : %d ... ...\n",PORT);

    /* 监听 sockfd 描述符 */
    if(listen(sockfd,LISTENQ)==-1)
    {
        fprintf(stderr,"Listenerror:%s\n\a",strerror(errno));
        exit(1);
    }
    
   thr_id = pthread_create(&p_thread, NULL, recvandsend, NULL); 
    
    while(1)
    {
        // 服务器阻塞,直到客户程序建立连接
        sin_size = sizeof(struct sockaddr_in);
        new_fd = accept(sockfd,(struct sockaddr *)(&client_addr),&sin_size);
        if(maxi >= MAXFD)
        {
            printf("will colse socket %d!\n",new_fd);
            if((new_fd != -1) && (closeConnection(new_fd) == 0))
		    {
		        close(new_fd);
		        printf("close %d connection success\n",new_fd);
		    }
        }
        else
        {
            if(new_fd == -1)
	        {
	            printf("socket Error!\n");
	            exit(1);
	        }
	        else
	        {
	            if(!connectSucceeddMess(new_fd))
	            {
	                // 设置非阻塞方式
	            	flags = fcntl(new_fd, F_GETFL, 0);
	                fcntl(new_fd, F_SETFL, flags | O_NONBLOCK); 
	                
	                sockNew = (SOCKNODE *)malloc(sizeof(SOCKNODE));
	                sockNew->fd = new_fd;
	                sockNew->pNext = NULL;
	                insertList(&sockList, sockNew); // 新套接字插入到链表中
	                printf("client %d to Chat Room!\n", new_fd);
		            maxi = maxi + 1;
		        }
	        }
	    }
	   
    }
    close(sockfd);
    exit(0);
}

客户端:

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
#include <pthread.h>
 
#define TRUE 1
#define PORT 5000
 
static int sockfd;
static int closeFlag = 1;

void closeClient()
{
    char mes[1024];
    int nbytes=0;
    int re;
    nbytes = read(sockfd, mes, sizeof(mes));
    re = strncmp(mes, "close", sizeof("close"));
	printf("mes is [%s]\n", mes); 
    if(re == 0)
    {
        printf("will colse socke, and exit client!\n");
        exit(1);
    }
}
void* recvfromserver()        //接受服务器消息线程入口函数
{
    char mes[1024];
    int nbytes=0;
    int re;
    while(1)
    {
	    memset(mes, 0, sizeof(mes));
        nbytes = read(sockfd, mes, sizeof(mes));
        if(nbytes > 0)
	    {
		    mes[nbytes] = '\0';
			printf("%s\n", mes);
	    }
	    re = strncmp(mes, "close", sizeof("close"));
	    
        if(re == 0)
        {
            printf("will colse socke, and exit client!\n");
            closeFlag = 0;
        }
   	    
    }
    pthread_exit(NULL);
	return NULL;
}

void logOut(int sockfd)
{
    char mes[1024];
    memset(mes, 0, sizeof(mes));
    strncpy(mes, "client %d will close!", sizeof("client %d will close!"));
    if(write(sockfd, mes, sizeof(mes)) == -1)
        printf("close client %d succeed!\n", sockfd);
    else
        printf("close client %d failed!\n", sockfd);
    
}
 
int main(int argc, char *argv[])
{
   char   buffer[1024];
   struct sockaddr_in server_addr;
   struct hostent *host;
   int    portnumber,nbytes;
   char   strhost[16];
   char   mes[1024];
   int    thr_id;         /* thread ID for the newly createdthread */
   pthread_t  p_thread;       /* thread's structure                     */
   if(argc!=1)
   {
		fprintf(stderr,"Usage:%s\a\n",argv[0]);
		exit(1);
   }
   printf("Please input the ip address : ");
   scanf("%s",strhost);
   if((host = gethostbyname(strhost)) == NULL)
   {
		fprintf(stderr,"Gethostnameerror\n");
		exit(1);
   }
 
   /* 客户程序开始建立 sockfd 描述符 */
   printf("Connection ... ...\n");
   if((sockfd = socket(AF_INET,SOCK_STREAM,0)) == -1)
   {
		fprintf(stderr,"SocketError:%s\a\n",strerror(errno));
		exit(1);
   }
   /* 客户程序填充服务端的资料 */
   bzero(&server_addr,sizeof(server_addr));
   server_addr.sin_family=AF_INET;
   server_addr.sin_port=htons(PORT);
   server_addr.sin_addr=*((struct in_addr *)host->h_addr);
   printf("Create Connection succeed ... ...\n");
   
   /* 客户程序发起连接请求 */
   if(connect(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1)
   {
		  fprintf(stderr,"ConnectError:%s\a\n",strerror(errno));
		  exit(1);
   }
 
   /* 连接成功了 */
   printf("connected the server succed,  ... ...\n");
   thr_id = pthread_create(&p_thread, NULL, recvfromserver, NULL);   
   closeClient();

   printf("\nPress Quit or q or Q disconnect server!\n");
   
   
   while(1)
   {
	    memset(buffer, 0, sizeof(buffer));
	    memset(mes, 0, sizeof(mes));
 
	    gets(buffer);    
	    
 	    strcat(mes, ":");
		strcat(mes,  buffer);

        printf("mes: [ %s ]\n", mes);
        
		if((write(sockfd,mes,sizeof(mes)))== -1)
		{
			fprintf(stderr,"WriteError:%s\n",strerror(errno));
			exit(1);
		}
 
		if(strcmp(buffer,"Quit")==0 || strcmp(buffer,"q")==0 || strcmp(buffer,"Q")==0)
		{
		    logOut(sockfd);
			break;
		}
	}
 
    close(sockfd);
    exit(0);
}
发布了91 篇原创文章 · 获赞 75 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/fengxianghui01/article/details/104421244