#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;
}