Linux C 即时通信中继服务器(类似QQ)

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <pthread.h>
#include <semaphore.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <errno.h>
#include <string.h>

#define  SERVER_PORT 8888
#define  MAX_BUF_SIZE  4096
#define  SUCCESS 0
#define  FAILURE -1

#pragma pack(push)  /* 保存默认的对齐方式 */
#pragma pack(1)    /* 设置当前对齐方式为n字节对齐 */


// 报文1    来自客户端的请求
// 报文2    服务器对用户回复


// 报文3    服务器对客户端的回复(在线用户信息)
typedef struct st_Manage_Info
{
    char cUserStatus;
	char cUserName[10];
	char cUserAddr[32];
	struct st_Manage_Info *next;
}ST_MANAGE_INFO;

typedef struct 
{
    char cMessageType; 
	char cUserName[10];
	char acId[10];              //user1  user2
	char acMessage[128];
	unsigned short  iUserNum;
	ST_MANAGE_INFO UserArray[10];
	char acToUser[10];
}ST_LOGIN_INFO;




#pragma pack(pop)


 ST_MANAGE_INFO *UserOnlineHead = NULL;
 ST_MANAGE_INFO *UserOnlineTail = NULL;
unsigned short g_UserNum = 0;

void AdduserTolist(char cUserName[10],char cUserIpaddr[32])
{

	if( UserOnlineHead == NULL)
	{
		ST_MANAGE_INFO *p=(ST_MANAGE_INFO *)malloc(sizeof(ST_MANAGE_INFO));
		p -> cUserStatus = 'Y';
		strcpy(p->cUserName,cUserName);
		strcpy(p->cUserAddr,cUserIpaddr);
		UserOnlineTail = p;
		UserOnlineHead = UserOnlineTail ;
		UserOnlineTail->next = NULL;
		g_UserNum ++ ;
    }
    else
    {
    	ST_MANAGE_INFO *p = (ST_MANAGE_INFO *)malloc( sizeof(ST_MANAGE_INFO));
	    p->cUserStatus='Y';
		strcpy(p->cUserName,cUserName);
		strcpy(p->cUserAddr,cUserIpaddr);
		UserOnlineTail->next = p;
        UserOnlineTail = p;
	    UserOnlineTail->next = NULL;
	    g_UserNum ++ ;
    }
}


char *ListUser(char cUserOnline[1024], ST_MANAGE_INFO *head)
{
	 ST_MANAGE_INFO *pst = head;

	 ST_LOGIN_INFO *UserOnline;
	
	int i = 0;	
	
	
    UserOnline = (ST_LOGIN_INFO *)cUserOnline;
	
	while(NULL != pst)
	{
	    UserOnline->cMessageType = '3';	    
	    strcpy(UserOnline->UserArray[i].cUserName,pst->cUserName);
	    UserOnline->UserArray[i].cUserStatus = pst->cUserStatus;
		printf("%s   %s   %c\n", pst->cUserName,pst->cUserAddr,pst->cUserStatus);		
		pst=pst->next;
		i++ ;
	}
	UserOnline->iUserNum = g_UserNum ;
	
	
}

int RecvFromServer(int iClientSockFd);

int main(int argc, char **argv)
{
    int iServerSockFd;
    int iClientSockFd;
    struct sockaddr_in stServerAddr;
    int iServerLen;
    int iOpt =1;
    int iReturn;

    printf("UDPQQ Server is running \n");

    // create server socket
    iServerSockFd = socket(AF_INET, SOCK_DGRAM, 0);
    if (iServerSockFd < 0 )
    {
        printf("socket create failed in CommManageServerRecvThread.\n");
		return FAILURE;
    }

    stServerAddr.sin_family = AF_INET;
    stServerAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    stServerAddr.sin_port = htons(SERVER_PORT);
    iServerLen = sizeof(stServerAddr);

    iReturn = bind(iServerSockFd, (const struct sockaddr *)&stServerAddr, sizeof(stServerAddr));
    if(iReturn != SUCCESS)
    {
        printf("Bind failed.\n");
        close(iServerSockFd);
        return FAILURE;
    }
    
    iReturn = RecvData(iServerSockFd);
    
    if(iReturn != SUCCESS)
    {
        printf("read from server failed.\n");
        close(iServerSockFd);
        return FAILURE;
    }

    close(iServerSockFd);

    return SUCCESS;
}


int RecvData(int iSockFd)
{
    char acBuf[MAX_BUF_SIZE];
    char acSend[MAX_BUF_SIZE];
    
    char acUserOnline[1024];
    int iReadNum;
    
  
    int i;
    unsigned int puiBufLen; 
    
    char cMessageType; 
	char cUserName[10];
	char acId[10];
	char acMessage[128];
	char acTouser[10];
	struct sockaddr_in stClientAddr;
   

    memset(acBuf, 0, sizeof(acBuf));
   
    while(1)
    {
    	int len = sizeof(stClientAddr);
    	
    	memset(acMessage,0,128);
    	memset(acTouser,0,10);
    	
        iReadNum = recvfrom(iSockFd, acBuf,MAX_BUF_SIZE, 0, (struct sockaddr *)&stClientAddr, &len );
        
       
        if(iReadNum < 0) 
        {
            printf("read failed.\n");
            return FAILURE;
        }
              

        Decode(acBuf,&cMessageType,cUserName,acId,acMessage,acTouser);
        
        printf("%c %s %s %s %s\n",cMessageType,cUserName,acId,acMessage,inet_ntoa(stClientAddr.sin_addr));
        printf("acTouser is  %s\n",acTouser);
        if (cMessageType == '1')
        
        {
        char cIpaddr[32];
        
        strcpy(cIpaddr,inet_ntoa(stClientAddr.sin_addr));
        
        AdduserTolist(cUserName,cIpaddr);
        
        ListUser(acUserOnline,UserOnlineHead);
        
        LoginEncode(acSend);

        sendto(iSockFd, acSend, MAX_BUF_SIZE, 0, (const struct sockaddr*)&stClientAddr, len);
        
        sendto(iSockFd, acUserOnline , MAX_BUF_SIZE, 0, (const struct sockaddr*)&stClientAddr, len);
        
        }
        
        else if (cMessageType == '4')
        {
        	 ST_MANAGE_INFO *pst = UserOnlineHead;
        	 struct sockaddr_in SendAddr;
        	 int iAddr;
        	 
        	 memset(&SendAddr, 0, sizeof(SendAddr));
 
    
    
             printf("4444444444444444444\n");
             
             while(pst->next != NULL)
             {
               if( !(strcmp(acTouser,  pst -> cUserName)) )
               {
                  
    
                  inet_pton(AF_INET, pst->cUserAddr, &iAddr);
                  
                  printf("%s    %d  \n", pst->cUserAddr,iAddr);
                         	 
        	    SendAddr.sin_family = AF_INET;
                SendAddr.sin_addr.s_addr = (iAddr);
                SendAddr.sin_port = htons(8888);
                
                TransterEncode(acSend,cUserName,acMessage);
                
                int ire = sendto(iSockFd,acSend, MAX_BUF_SIZE, 0, (const struct sockadddr*)&SendAddr, sizeof(SendAddr));
                
                perror("send:");
                
                printf("sendto rer  is  %d\n",ire);
         
               }
                 pst = pst ->next;
             }
            
        }
}

    return SUCCESS;

}

int Decode(char *acBuf,char *cMessageType,char *cUserName,char *acId, char *cMessage, char *acTouser)
{   
     ST_LOGIN_INFO  *pstInfo;

     pstInfo = (ST_LOGIN_INFO *)acBuf;

     *cMessageType = pstInfo -> cMessageType;
     
     strcpy(cUserName,pstInfo ->cUserName );
     
     strcpy(acId,pstInfo -> acId );
     
     strcpy(cMessage,pstInfo ->acMessage );  
     
     strcpy(acTouser, pstInfo -> acToUser);

     return SUCCESS;
}

int LoginEncode(char *pcBuf)
{
    ST_LOGIN_INFO  *pstInfo;
  
    pstInfo = (ST_LOGIN_INFO *)pcBuf;
   
    pstInfo->cMessageType = '2';
   
    strcpy(pstInfo->acMessage, "Login success!");
   
    return SUCCESS;
} 


int TransterEncode(char *pcBuf,char *acToUser, char *acMessage)
{
    ST_LOGIN_INFO  *pstInfo;
  
    pstInfo = (ST_LOGIN_INFO *)pcBuf;
   
    pstInfo->cMessageType = '5'
    
    strcpy(pstInfo ->acToUser,acToUser);
   
    strcpy(pstInfo->acMessage, acMessage);
   
    return SUCCESS;
}

 

转载于:https://my.oschina.net/sharelinux/blog/127403

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值