#ifndef LANCHAT_DEBUG_H
#define LANCHAT_DEBUG_H
//仅客户端使用
#define LANCHAT_CLIENT_DEBUG_ERROR
#define LANCHAT_CLIENT_DEBUG_WARNING
#define LANCHAT_CLIENT_DEBUG_INFO
#ifdef LANCHAT_CLIENT_DEBUG_ERROR
#define PrintClientError printf(“at %s:%d–”,FILE,LINE);printf
#else
#define PrintClientError(…)
#endif
//PrintClientError(…) C99才支持
//用法PrintClientError同printf,注意不可使用在不加{}的条件体和循环体,以下雷同
#ifdef LANCHAT_CLIENT_DEBUG_WARNING
#define PrintClientWarning printf(“at %s:%d–”,FILE,LINE);printf
#else
#define PrintClientWarning(…)
#endif
#ifdef LANCHAT_CLIENT_DEBUG_INFO
#define PrintClientInfo printf(“at %s:%d–”,FILE,LINE);printf
#else
#define PrintClientInfo(…)
#endif
//仅服务器使用
#define LANCHAT_SERVER_DEBUG_ERROR
#define LANCHAT_SERVER_DEBUG_WARNING
#define LANCHAT_SERVER_DEBUG_INFO
#ifdef LANCHAT_SERVER_DEBUG_ERROR
#define PrintServerError printf(“at %s:%d–”,FILE,LINE);printf
#else
#define PrintServerError(…)
#endif
#ifdef LANCHAT_SERVER_DEBUG_WARNING
#define PrintServerWarning printf(“at %s:%d–”,FILE,LINE);printf
#else
#define PrintServerWarning(…)
#endif
#ifdef LANCHAR_SERVER_DEBUG_INFO
#define PrintServerInfo printf(“at %s:%d–”,FILE,LINE);printf
#else
#define PrintServerInfo(…)
#endif
//仅公共库代码使用
#define LANCHAT_PUBLIC_DEBUG_ERROR
#define LANCHAT_PUBLIC_DEBUG_WARNING
#define LANCHAT_PUBLIC_DEBUG_INFO
#ifdef LANCHAT_PUBLIC_DEBUG_ERROR
#define PrintPublicError printf(“at %s:%d–”,FILE,LINE);printf
#else
#define PrintPublicError(…)
#endif
#ifdef LANCHAT_PUBLIC_DEBUG_WARNING
#define PrintPublicWarning printf(“at %s:%d–”,FILE,LINE);printf
#else
#define PrintPublicWarning(…)
#endif
#ifdef LANCHAT_PUBLIC_DEBUG_INFO
#define PrintPublicInfo printf(“at %s:%d–”,FILE,LINE);printf
#else
#define PrintPublicInfo(…)
#endif
#endif
#ifndef LANCHAT_PROTOCOL_H
#define LANCHAT_PROTOCOL_H
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NAME_LEN 24
#define PASS_LEN 24
enum ENUM_LC_PDU_TYPE
{
LC_PDU_TYPE_LOGIN_REQ = 1,
LC_PDU_TYPE_LOGIN_RSP,
LC_PDU_TYPE_USERLIST_REQ,
LC_PDU_TYPE_USERLIST_RSP,
LC_PDU_TYPE_PVCHAT_REQ,
LC_PDU_TYPE_PVCHAT_RSP,
LC_PDU_TYPE_GPCHAT_REQ
};
//size PDU数据总字节数
//type 1.注册请求 2.注册回应 3.用户列表请求 4.用户列表回应 5.私聊PDU 6.私聊回应 7.群聊PDU
//sender 消息发送者用户名 如果是从服务器发出则为"server"
//recver 消息接收者用户名 如果为群聊则为"group" 如果仅是发给服务器而不需转发的则为"server"
//buf 该PDU实际数据,注册请求为20字节的password 用户列表请求无此部分 用户列表请求回应为20字节的整数倍
// 私聊群聊为聊天内容字符串 注册回应与私聊回应为long型数字(0表示成功 其它表示某种错误)
//len buf部分字节数
struct LanChatPDU
{
long size;
long type;
char sender[NAME_LEN];
char recver[NAME_LEN];
long len;
char buf[1];
};
#define LANCHAT_PDU_HEADER_SIZE (sizeof(long) * 3 + NAME_LEN * 2)
struct LanChatPDU *CreateLoginPDU(char *name,char *password);
struct LanChatPDU *CreatePrivateChatPDU(char *sender,char *recver,char *content);
struct LanChatPDU *CreateGroupChatPDU(char *sender,char *content);
struct LanChatPDU *CreateRequestUserListPDU(char *sender);
struct LanChatPDU *CreateReuestUserListRspPDU(char *recver,char *username,long count);
struct LanChatPDU *CreateOtherRspPDU(char *recver,long type, long value);//注册回应 私聊回应
int DestroyLanChatPDU(struct LanChatPDU * pstPDU);//所有Create函数均有动态分配,本函数负责释放
int SendPDU(int fd,struct LanChatPDU *pstPDU);
int LockSendPDU(int fd,struct LanChatPDU *pstPDU,pthread_mutex_t *plock);//多个线程使用同一socket发送数据时用
struct LanChatPDU * RecvPDU(int fd);
#endif
#ifndef LANCHAT_PUBLIC_H
#define LANCHAT_PUBLIC_H
#include “lanchatprotocol.h”
#include “lanchatdebug.h”
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#define MIN(a,b) ((a) > (b) ? (b) : (a))
int MyWrite(int fd, void *pvBuf, size_t n);
int MyRead(int fd, void *pvBuf, size_t n);
char *MyGetString(char *pacBuf,int size);
char *MyReadLineFromTxt(char *pacBuf,int size,FILE *pf);
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include “cprivate.h”
static void InitClientCTL(struct LanChatClientCTL * pstClient);
static void EndClientCTL(struct LanChatClientCTL * pstClient);
static int ConnectServer(struct LanChatClientCTL * pstClient,char *ip,int port);
int main(int argc,char *argv[])
{
struct LanChatClientCTL stClient = {-1};
int ret = 0;
int port = 0;
if(argc < 3)
{
PrintClientError(“The program run arg is invalid\n”);
return 1;
}
sscanf(argv[2],"%d",&port);
if(port < 1024 || port > 9999)
{
PrintClientError(“port is error\n”);
return 2;
}
InitClientCTL(&stClient);
ret = ConnectServer(&stClient,argv[1],port);
if(0 == ret)
{
ret = UserLogin(&stClient);
}
if(0 == ret)
{
ClientMainLoop(&stClient);
}
else
{
PrintClientError(“Can’t into ClientMainLoop Function\n”);
}
EndClientCTL(&stClient);
return ret;
}
static void InitClientCTL(struct LanChatClientCTL * pstClient)
{
memset(pstClient,0,sizeof(struct LanChatClientCTL));
pstClient->stdinfd = 0;
pstClient->sockfd = -1;
ChangeClientUILayer(pstClient,1);//Main UI
pstClient->iNumOfUsers = 0;
pstClient->pcAllUserName = NULL;
}
static void EndClientCTL(struct LanChatClientCTL * pstClient)
{
if(NULL != pstClient->pcAllUserName)
{
free(pstClient->pcAllUserName);
pstClient->pcAllUserName = NULL;
}
if(pstClient->sockfd >= 0)
{
close(pstClient->sockfd);
}
}
static int ConnectServer(struct LanChatClientCTL * pstClient,char *ip,int port)
{
struct sockaddr_in servaddr;
int fdSocket = -1;
int ret = 0;
fdSocket = socket(AF_INET,SOCK_STREAM,0);
if(fdSocket < 0)
{
PrintClientError(“Open Socket Failed!!!\n”);
return -1;
}
memset(&servaddr,0,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(port);
inet_aton(ip,&servaddr.sin_addr);
ret = connect(fdSocket,(struct sockaddr *)&servaddr,sizeof(servaddr));
if(ret < 0)
{
PrintClientError(“Connect Server Failed!!!\n”);
close(fdSocket);
fdSocket = -1;
}
pstClient->sockfd = fdSocket;
return ret;
}
#include “cprivate.h”
void ClientMainLoop(struct LanChatClientCTL *pstClient)
{
int ret = 0;
fd_set rset;
if(NULL == pstClient)
{
PrintClientError(“Invalid Input Parameter!!!\n”);
return;
}
DisplayClientUI(pstClient);
while(1)
{
FD_ZERO(&rset);
FD_SET(pstClient->stdinfd,&rset);
FD_SET(pstClient->sockfd,&rset);
ret = select(pstClient->sockfd + 1,
&rset,
NULL,
NULL,
NULL);
if(ret <= 0)
{
if(errno == EINTR)
{
PrintClientWarning(“select is aborted by SIGNAL\n”);
continue;
}
else
{
PrintClientError(“select is aborted by exception\n”);
break;
}
}//end if(ret <= 0)
if(FD_ISSET(pstClient->stdinfd,&rset))
{
ret = HandleUserInput(pstClient);
if(-1 == ret)
{
PrintClientError("LanChat Client is exiting!!!\n");
break;
}
}
if(FD_ISSET(pstClient->sockfd,&rset))
{
ret = HandleSocketMessage(pstClient);
if(-1 == ret)
{
PrintClientError("Client Socket has been closed!!!\n");
break;
}
}
}//end while(1)
}
int ChangeClientUILayer(struct LanChatClientCTL *pstClient,int uilayer)
{
int ret = 0;
if(NULL == pstClient || uilayer < 1 || uilayer > 3)
{
PrintClientError(“Invalid Input Parameter!!!\n”);
return -1;
}
pstClient->uilayer = uilayer;
return ret;
}
#ifndef _LANCHAT_CLIENT_PRIVATE_H
#define _LANCHAT_CLIENT_PRIVATE_H
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/select.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include “lanchatpublic.h”
//客户端总控用结构体
struct LanChatClientCTL
{
int sockfd;
int stdinfd;//0
int uilayer;//1登录后的主界面 2选择消息接收者的界面 3提示用户输入消息内容的界面
char *pcAllUserName;//服务器已注册用户列表
int iNumOfUsers;//用户列表中包含的用户个数
char acClientUserName[NAME_LEN];//登录后本客户端的用户名,将作为消息发送者
char acReceiverName[NAME_LEN];//为group表示群聊,不为空则为私聊消息接收者
};
//总控子模块接口
void ClientMainLoop(struct LanChatClientCTL *pstClient);
int ChangeClientUILayer(struct LanChatClientCTL *pstClient,int uilayer);
//登录子模块接口
int UserLogin(struct LanChatClientCTL *pstClient);
//用户输入数据处理子模块接口
int HandleUserInput(struct LanChatClientCTL * pstClient);
//socket数据处理子模块接口
int HandleSocketMessage(struct LanChatClientCTL * pstClient);
int SendMessage(struct LanChatClientCTL * pstClient,
char *pcContent,
int iLenOfContent);
//Viewer子模块接口
void DisplayClientUI(struct LanChatClientCTL * pstClient);
void DisplayChatMessage(const char *pcFrom,
const char *pcTo,
const char *pcContent,
int iLenOfContent);
#endif
#include “cprivate.h”
int HandleSocketMessage(struct LanChatClientCTL * pstClient)
{
struct LanChatPDU *pstPDU = NULL;
if(NULL == pstClient)
{
PrintClientError(“Invalid Input Parameter!!!\n”);
return -2;
}
pstPDU = RecvPDU(pstClient->sockfd);
if(NULL == pstPDU)
{
PrintClientError(“RetriveChatPDU Failed!!!\n”);
return -1;
}
switch(pstPDU->type)
{
case LC_PDU_TYPE_PVCHAT_REQ://收到私聊消息
case LC_PDU_TYPE_GPCHAT_REQ://收到群聊消息
DisplayChatMessage(pstPDU->sender,
pstPDU->recver,
pstPDU->buf,
pstPDU->len);
break;
case LC_PDU_TYPE_PVCHAT_RSP:
if(0 != (long )pstPDU->buf)
{
PrintClientInfo(“Some Message sent failed %ld\n”,(long)pstPDU->buf);
}
break;
default:
PrintClientError(“Unknowed LanChat PDU\n”);
break;
}
DestroyLanChatPDU(pstPDU);
return 0;
}
int SendMessage(struct LanChatClientCTL * pstClient,char *pcContent,int iLenOfContent)
{
struct LanChatPDU *pstPDU = NULL;
int ret = 0;
if(NULL == pstClient || NULL == pcContent || iLenOfContent <= 0)
{
PrintClientError(“Invalid Input Parameter!!!\n”);
return -1;
}
if(0 == strcmp(pstClient->acReceiverName,“group”))
{
pstPDU = CreateGroupChatPDU(pstClient->acClientUserName,pcContent);
}
else
{
pstPDU = CreatePrivateChatPDU(pstClient->acClientUserName,pstClient->acReceiverName,pcContent);
}
if(pstPDU != NULL)
{
ret = SendPDU(pstClient->sockfd,pstPDU);
DestroyLanChatPDU(pstPDU);
}
else
{
ret = -1;
}
return ret;
}
#include “cprivate.h”
static int SelectMainUICMD();
static void SelectReceiverName(char *pcName);
static int CheckReceiverName(struct LanChatClientCTL * pstClient,const char *pcName);
static int GetMsgContentFromStdin(char **ppOut);
int HandleUserInput(struct LanChatClientCTL * pstClient)
{
int ret = 0;
int iCMD = 0;
char acName[NAME_LEN] = {0};
char *pcContent = NULL;
int iLenOfContent = 0;
if(NULL == pstClient)
{
PrintClientError(“Invalid Input Parameter!!!\n”);
return -2;
}
switch(pstClient->uilayer)
{
case 1://当前界面为:登录后主界面,读取的内容决定后面的操作
iCMD = SelectMainUICMD();
if(2 == iCMD)
{
return -1;
}
else if(1 == iCMD)
{
ChangeClientUILayer(pstClient,2);
DisplayClientUI(pstClient);
}
else
{
PrintClientError(“Invalid Operation Command!!!\n”);
}
break;
case 2://当前界面为:选择消息接收者的界面,读取的内容决定消息接收者
memset(pstClient->acReceiverName,0,NAME_LEN);
SelectReceiverName(acName);
ret = CheckReceiverName(pstClient,acName);
if(ret == 0)
{
memset(pstClient->acReceiverName,0,NAME_LEN);
strcpy(pstClient->acReceiverName,acName);
ChangeClientUILayer(pstClient,3);
DisplayClientUI(pstClient);
}
else
{
PrintClientError("Your Input User Name is not exist\n");
ChangeClientUILayer(pstClient,1);
DisplayClientUI(pstClient);
ret = 0;
}
break;
case 3://当前界面为:提示用户输入消息内容的界面,读取的内容作为消息内容
iLenOfContent = GetMsgContentFromStdin(&pcContent);
if(0 != strncmp(pcContent,"*back*",strlen("*back*")))
{
ret = SendMessage(pstClient,pcContent,iLenOfContent);
}
ChangeClientUILayer(pstClient,1);//回主界面
DisplayClientUI(pstClient);
memset(pstClient->acReceiverName,0,NAME_LEN);
free(pcContent);
break;
default:
PrintClientError("Invalid Stdin Status!!!\n");
break;
}
return ret;
}
/**/
static int SelectMainUICMD()
{
int iCMD = -1;
char buf[10] = {0};
MyGetString(buf,10);
sscanf(buf,"%d",&iCMD);
return iCMD;
}
static void SelectReceiverName(char *pcName)
{
char buf[NAME_LEN] = {0};
MyGetString(buf,NAME_LEN);
strcpy(pcName,buf);
return;
}
static int CheckReceiverName(struct LanChatClientCTL * pstClient,const char *pcName)
{
int ret = 0;
int i = 0;
if(0 == strcmp(pcName,“group”))
{
return 0;
}
if(pstClient->iNumOfUsers <= 0)
{
return -1;
}
for(i = 0;i < pstClient->iNumOfUsers;i++)
{
if(0 == strcmp(pcName,pstClient->pcAllUserName + i * NAME_LEN))
{
break;
}
}
if(i >= pstClient->iNumOfUsers)
{
ret = -2;
}
else
{
ret = 0;
}
return ret;
}
static int GetMsgContentFromStdin(char **ppOut)
{
int len = 0;
int size = 0;
int readsize = 0;
char *pcTemp = NULL;
const char *pcTmpFileName = “/tmp/lanchatc.log”;
FILE *fpTmp = NULL;
char acBuf[64] = {0};
if(NULL == ppOut)
{
PrintClientError(“Input Parameter is invalid\n”);
return -1;
}
/将用户输入的消息内容先存到文件中/
fpTmp = fopen(pcTmpFileName,“w”);
if(NULL == fpTmp)
{
PrintClientError(“Open file failed!!!\n”);
return -2;
}
fgets(acBuf,64,stdin);
len =strlen(acBuf);
fprintf(fpTmp,"%s",acBuf);
while(acBuf[len - 1] != ‘\n’)
{
memset(acBuf,0,64);
fgets(acBuf,64,stdin);
len =strlen(acBuf);
fprintf(fpTmp,"%s",acBuf);
}
fclose(fpTmp);
/通过文件知晓内容大小,分配空间,再将文件内容读到分配的空间中/
fpTmp = fopen(pcTmpFileName,“rb”);
if(NULL == fpTmp)
{
PrintClientError(“Open file failed!!!\n”);
return -3;
}
fseek(fpTmp,0,SEEK_END);
len = ftell(fpTmp);
fseek(fpTmp,0,SEEK_SET);
*ppOut = (char *)malloc(len+1);
if(NULL == *ppOut)
{
PrintClientError(“Malloc Failed!!!\n”);
fclose(fpTmp);
return -4;
}
memset(*ppOut,0,len + 1);
readsize = len;
pcTemp = *ppOut;
size = fread(pcTemp,1,readsize,fpTmp);
while(size < readsize && size > 0)
{
readsize -= size;
pcTemp += size;
size = fread(pcTemp,1,readsize,fpTmp);
}
fclose(fpTmp);
return len + 1;
}
#include “cprivate.h”
static int GetUsersList(struct LanChatClientCTL * pstClient);
int UserLogin(struct LanChatClientCTL * pstClient)
{
int ret = 0;
struct LanChatPDU *pstPDU = NULL;
char acUserName[NAME_LEN] = {0};
char acPassword[PASS_LEN] = {0};
if(NULL == pstClient)
{
PrintClientError(“Invalid Input Parameter!!!\n”);
return -1;
}
/读用户输入的用户名和密码/
printf("$$$
P
l
e
a
s
e
I
n
p
u
t
Y
o
u
r
L
o
g
i
n
N
a
m
e
:
"
)
;
M
y
G
e
t
S
t
r
i
n
g
(
a
c
U
s
e
r
N
a
m
e
,
N
A
M
E
L
E
N
)
;
p
r
i
n
t
f
(
"
Please Input Your Login Name:"); MyGetString(acUserName,NAME_LEN); printf("
PleaseInputYourLoginName:");MyGetString(acUserName,NAMELEN);printf("$$$Please Input Your Login Password:");
MyGetString(acPassword,PASS_LEN);
/创建并发送登录PDU/
pstPDU = CreateLoginPDU(acUserName,acPassword);
if(NULL == pstPDU)
{
PrintClientError(“Create Login User Name PDU Error!!!\n”);
return -1;
}
ret = SendPDU(pstClient->sockfd,pstPDU);
DestroyLanChatPDU(pstPDU);
pstPDU = NULL;
/接收并处理服务发送过来回应/
if(0 == ret)
{
pstPDU = RecvPDU(pstClient->sockfd);
if(pstPDU != NULL && LC_PDU_TYPE_LOGIN_RSP == pstPDU->type && 0 == *(long )pstPDU->buf)
{//登录成功
strcpy(pstClient->acClientUserName,acUserName);
DestroyLanChatPDU(pstPDU);
}
else
{//登录失败
if(NULL == pstPDU)
{
PrintClientError(“Login Failed:RecvPDU Error\n”);
}
if(LC_PDU_TYPE_LOGIN_RSP != pstPDU->type)
{
PrintClientError(“Login Failed:The PDU is invalid\n”);
}
else
{
PrintClientError(“Login Check Name Failed Cause:%ld\n”,(long *)(pstPDU->buf));
}
DestroyLanChatPDU(pstPDU);
return -1;
}
}
else
{
PrintClientError(“Send Login PDU Failed\n”);
return -1;
}
/获取用户列表/
ret = GetUsersList(pstClient);
return ret;
}
static int GetUsersList(struct LanChatClientCTL * pstClient)
{
int ret = 0;
struct LanChatPDU *pstPDU = NULL;
if(NULL == pstClient)
{
PrintClientError(“Invalid Input Parameter!!!\n”);
return -1;
}
pstPDU = CreateRequestUserListPDU(pstClient->acClientUserName);
if(NULL == pstPDU)
{
PrintClientError(“Create Login Request UserList PDU Error!!!\n”);
return -1;
}
ret = SendPDU(pstClient->sockfd,pstPDU);
DestroyLanChatPDU(pstPDU);
pstPDU = NULL;
if(ret != 0)
{
PrintClientError(“Send Login PDU Failed\n”);
return -1;
}
pstPDU = RecvPDU(pstClient->sockfd);
if(pstPDU != NULL && LC_PDU_TYPE_USERLIST_RSP == pstPDU->type &&
pstPDU->len > 0 && pstPDU->len % NAME_LEN == 0)
{//获取成功
pstClient->pcAllUserName = (char *)malloc(pstPDU->len);
if(NULL == pstClient->pcAllUserName)
{
PrintClientError(“Malloc Failed\n”);
DestroyLanChatPDU(pstPDU);
return -1;
}
memcpy(pstClient->pcAllUserName,pstPDU->buf,pstPDU->len);
pstClient->iNumOfUsers = pstPDU->len / NAME_LEN;
DestroyLanChatPDU(pstPDU);
}
else
{//获取失败
if(NULL == pstPDU)
{
PrintClientError(“Get User List Failed:RecvPDU Error\n”);
}
if(LC_PDU_TYPE_USERLIST_RSP != pstPDU->type)
{
PrintClientError(“Get User List Failed:The PDU is invalid\n”);
}
else
{
PrintClientError(“Get User List Failed:Server handle error\n”);
}
DestroyLanChatPDU(pstPDU);
return -1;
}
return 0;
}
#include “cprivate.h”
static void DisplayMainUI();
static void DisplayInputMsgContentUI();
static void DisplayInputReceiverNameUI(struct LanChatClientCTL * pstClient);
void DisplayClientUI(struct LanChatClientCTL * pstClient)
{
if(NULL == pstClient)
{
PrintClientError(“Input Parameter is invalid\n”);
return;
}
switch(pstClient->uilayer)
{
case 1://登录后主界面
DisplayMainUI();
break;
case 2://输入消息接收者界面
DisplayInputReceiverNameUI(pstClient);
break;
case 3://输入消息内容界面
DisplayInputMsgContentUI();
break;
default:
PrintClientError(“This UI is not supported\n”);
break;
}
}
static void DisplayMainUI()
{
printf("\n");
printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
printf("@@@@@@@@@@@@@@@@1.Send Message@@@@@@@@@@@@@@@@\n");
printf("@@@@@@@@@@@@@@@@2.Quit LanChat@@@@@@@@@@@@@@@@\n");
printf("@@@@@@@@@@@Please Input Your Choice@@@@@@@@@@@\n");
printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
}
static void DisplayInputReceiverNameUI(struct LanChatClientCTL * pstClient)
{
int i = 0;
printf("\n");
printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
printf("@@@@@@@@@@@@@@@@All User Name:@@@@@@@@@@@@@@@@\n");
for(i = 0;i < pstClient->iNumOfUsers;i++)
{
printf("@@@@@@@@@@@@@%24s@@@@@@@@@@@@@\n",
pstClient->pcAllUserName + i * NAME_LEN);
}
printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
printf("@@@@@@@Note:group means all users!!!@@@@@@@\n");
printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
printf("@@@@@@@Please Input Receiver User Name:@@@@@@@\n");
printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
}
static void DisplayInputMsgContentUI()
{
printf("\n");
printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
printf("@@@@@@@@@@Please Input Message Text:@@@@@@@@@@\n");
printf("@@@@@@@@Note:Input back means return@@@@@@@@\n");
printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
}
void DisplayChatMessage(const char *pcFrom,
const char *pcTo,
const char *pcContent,
int iLenOfContent)
{
int i = 0;
const char * pcTemp = NULL;
if(NULL == pcFrom ||
NULL == pcContent ||
iLenOfContent <= 0)
{
PrintClientError(“Invalid Input Parameter!!!\n”);
return;
}
printf("\n");
printf("##############################################\n");
if(strcmp(pcTo,“group”) == 0)
{//群聊内容
printf("%s say to %s:\n",pcFrom,“all”);
}
else
{//私聊内容
printf("%s say to %s:\n",pcFrom,“me”);
}
printf("##############################################\n");
pcTemp = pcContent;
for( i = iLenOfContent - 1;i > 0;)
{
if(i >= 46)
{
write(1,pcContent,46);
write(1,"\n",1);
pcTemp = pcTemp + 46;
i = i - 46;
}
else
{
write(1,pcTemp,strlen(pcTemp));
write(1,"\n",1);
break;
}
}
printf("##############################################\n");
}
#include “lanchatpublic.h”
struct LanChatPDU *CreateLoginPDU(char *name,char *password)
{
long len = 0;
struct LanChatPDU *pstPDU = NULL;
/函数的输入参数做合法性检查/
if(NULL == name || NULL == password)
{
PrintPublicError(“Input Param is invalid\n”);
return NULL;
}
/*计算总的空间的大小*/
len = LANCHAT_PDU_HEADER_SIZE + PASS_LEN;
/*分配空间*/
pstPDU = (struct LanChatPDU *)malloc(len);
if(NULL == pstPDU)
{
PrintPublicError("Malloc Failed\n");
return NULL;
}
memset(pstPDU,0,len);
/*向被分配的空间填值*/
pstPDU->size = len;
pstPDU->type = LC_PDU_TYPE_LOGIN_REQ;
pstPDU->len = PASS_LEN;
strncpy(pstPDU->sender,name,NAME_LEN - 1);
strcpy(pstPDU->recver,"server");
strncpy(pstPDU->buf,password,PASS_LEN - 1);
/*返回被分配空间的首地址*/
return pstPDU;
}
struct LanChatPDU *CreatePrivateChatPDU(char *sender,char *recver,char *content)
{
long len = 0;
long clen = 0;
struct LanChatPDU *pstPDU = NULL;
/函数的输入参数做合法性检查/
if(NULL == sender || NULL == recver || NULL == content)
{
PrintPublicError(“Input Param is invalid\n”);
return NULL;
}
/*计算总的空间的大小*/
clen = strlen(content);
len = LANCHAT_PDU_HEADER_SIZE + clen + 1;
/*分配空间*/
pstPDU = (struct LanChatPDU *)malloc(len);
if(NULL == pstPDU)
{
PrintPublicError("Malloc Failed\n");
return NULL;
}
memset(pstPDU,0,len);
/*向被分配的空间填值*/
pstPDU->size = len;
pstPDU->type = LC_PDU_TYPE_PVCHAT_REQ;
pstPDU->len = clen+1;
strncpy(pstPDU->sender,sender,NAME_LEN - 1);
strncpy(pstPDU->recver,recver,NAME_LEN - 1);
strcpy(pstPDU->buf,content);
/*返回被分配空间的首地址*/
return pstPDU;
}
struct LanChatPDU *CreateGroupChatPDU(char *sender,char *content)
{
long len = 0;
long clen = 0;
struct LanChatPDU *pstPDU = NULL;
/*函数的输入参数做合法性检查*/
if(NULL == sender || NULL == content)
{
PrintPublicError("Input Param is invalid\n");
return NULL;
}
/*计算总的空间的大小*/
clen = strlen(content);
len = LANCHAT_PDU_HEADER_SIZE + clen + 1;
/*分配空间*/
pstPDU = (struct LanChatPDU *)malloc(len);
if(NULL == pstPDU)
{
PrintPublicError("Malloc Failed\n");
return NULL;
}
memset(pstPDU,0,len);
/*向被分配的空间填值*/
pstPDU->size = len;
pstPDU->type = LC_PDU_TYPE_GPCHAT_REQ;
pstPDU->len = clen + 1;
strncpy(pstPDU->sender,sender,NAME_LEN - 1);
strcpy(pstPDU->recver,"group");
strcpy(pstPDU->buf,content);
/*返回被分配空间的首地址*/
return pstPDU;
}
struct LanChatPDU *CreateRequestUserListPDU(char *sender)
{
long len = 0;
struct LanChatPDU *pstPDU = NULL;
/*函数的输入参数做合法性检查*/
if(NULL == sender)
{
PrintPublicError("Input Param is invalid\n");
return NULL;
}
/*计算总的空间的大小*/
len = LANCHAT_PDU_HEADER_SIZE;
/*分配空间*/
pstPDU = (struct LanChatPDU *)malloc(len);
if(NULL == pstPDU)
{
PrintPublicError("Malloc Failed\n");
return NULL;
}
memset(pstPDU,0,len);
/*向被分配的空间填值*/
pstPDU->size = len;
pstPDU->type = LC_PDU_TYPE_USERLIST_REQ;
pstPDU->len = 0;
strncpy(pstPDU->sender,sender,NAME_LEN - 1);
strcpy(pstPDU->recver,"server");
/*返回被分配空间的首地址*/
return pstPDU;
}
struct LanChatPDU *CreateReuestUserListRspPDU(char *recver,char *username,long count)
{
long len = 0;
struct LanChatPDU *pstPDU = NULL;
/函数的输入参数做合法性检查/
if(count <= 0 || NULL == username || NULL == recver)
{
PrintPublicError(“Input Param is invalid\n”);
return NULL;
}
/*计算总的空间的大小*/
len = LANCHAT_PDU_HEADER_SIZE + NAME_LEN * count;
/*分配空间*/
pstPDU = (struct LanChatPDU *)malloc(len);
if(NULL == pstPDU)
{
PrintPublicError("Malloc Failed\n");
return NULL;
}
memset(pstPDU,0,len);
/*向被分配的空间填值*/
pstPDU->size = len;
pstPDU->type = LC_PDU_TYPE_USERLIST_RSP;
pstPDU->len = NAME_LEN * count;
strcpy(pstPDU->sender,"server");
strncpy(pstPDU->recver,recver,NAME_LEN-1);
memcpy(pstPDU->buf,username,NAME_LEN * count);
/*返回被分配空间的首地址*/
return pstPDU;
}
struct LanChatPDU *CreateOtherRspPDU(char *recver,long type,long value)
{
long len = 0;
struct LanChatPDU *pstPDU = NULL;
/函数的输入参数做合法性检查/
if((type != LC_PDU_TYPE_LOGIN_RSP && type != LC_PDU_TYPE_PVCHAT_RSP) || NULL == recver)
{
PrintPublicError(“Input Param is invalid\n”);
return NULL;
}
/*计算总的空间的大小*/
len = LANCHAT_PDU_HEADER_SIZE + sizeof(long);
/*分配空间*/
pstPDU = (struct LanChatPDU *)malloc(len);
if(NULL == pstPDU)
{
PrintPublicError("Malloc Failed\n");
return NULL;
}
memset(pstPDU,0,len);
/*向被分配的空间填值*/
pstPDU->size = len;
pstPDU->type = type;
pstPDU->len = sizeof(long);
strcpy(pstPDU->sender,"server");
strncpy(pstPDU->recver,recver,NAME_LEN-1);
*((long *)pstPDU->buf) = value;
/*返回被分配空间的首地址*/
return pstPDU;
}
int DestroyLanChatPDU(struct LanChatPDU * pstPDU)
{
if(pstPDU != NULL)
{
free(pstPDU);
}
return 0;
}
int SendPDU(int fd,struct LanChatPDU *pstPDU)
{
int ret = 0;
if(fd < 0 || NULL == pstPDU)
{
PrintPublicError(“Input Param is invalid\n”);
return -1;
}
ret = MyWrite(fd,pstPDU,pstPDU->size);
if(ret != pstPDU->size)
{
PrintPublicError("Send PDU Failed\n");
return -1;
}
return 0;
}
int LockSendPDU(int fd,struct LanChatPDU *pstPDU,pthread_mutex_t *plock)
{
int ret = 0;
if(fd < 0 || NULL == pstPDU || NULL == plock)
{
PrintPublicError(“Input Param is invalid\n”);
return -1;
}
pthread_mutex_lock(plock);
ret = MyWrite(fd,pstPDU,pstPDU->size);
pthread_mutex_unlock(plock);
if(ret != pstPDU->size)
{
PrintPublicError("Send PDU Failed\n");
return -1;
}
return 0;
}
struct LanChatPDU * RecvPDU(int fd)
{
long len = 0;
int ret = 0;
struct LanChatPDU *pstPDU = NULL;
if(fd < 0)
{
PrintPublicError(“Input Param is invalid\n”);
return NULL;
}
ret = MyRead(fd,&len,sizeof(long));
if(ret != sizeof(long) || len <= 0)
{
PrintPublicError("read size error\n");
return NULL;
}
pstPDU = (struct LanChatPDU *)malloc(len);
if(NULL == pstPDU)
{
PrintPublicError("Malloc Failed\n");
return NULL;
}
memset(pstPDU,0,len);
pstPDU->size = len;
ret = MyRead(fd,&pstPDU->type,len - sizeof(long));
if(ret != len - sizeof(long))
{
PrintPublicError("receive failed\n");
free(pstPDU);
pstPDU = NULL;
}
return pstPDU;
}
#include “lanchatpublic.h”
int MyWrite(int fd, void *pvBuf, size_t n)//
{
size_t nLeft = n;
size_t nWrite = 0;
char *pcTemp = (char *)pvBuf;
while(nLeft > 0)
{
nWrite = write(fd,pcTemp,nLeft);
if(nWrite <= 0)
{
if(nWrite < 0 && errno == EINTR)
{
nWrite = 0;
}
else
{
return -1;
}
}
nLeft = nLeft - nWrite;
pcTemp = pcTemp + nWrite;
}
return (n - nLeft);
}
int MyRead(int fd, void *pvBuf, size_t n)
{
size_t nLeft = n;
size_t nRead = 0;
char *pcTemp = (char *)pvBuf;
while(nLeft > 0)
{
nRead = read(fd,pcTemp,nLeft);
if(nRead < 0)
{
if(errno == EINTR)
{
nRead = 0;
}
else
{
return -1;
}
}
else if(0 == nRead)
{
return 0;
}
nLeft = nLeft - nRead;
pcTemp = pcTemp + nRead;
}
return (n - nLeft);
}
char *MyGetString(char *pacBuf,int size)//从键盘读取信息
{
int len = 0;
char *p = 0;
if(NULL == pacBuf || size <= 0)
{
PrintPublicError(“Input Param is invalid\n”);
return NULL;
}
p = fgets(pacBuf,size,stdin);
if(NULL == p)
{
PrintPublicError(“fgets failed\n”);
return NULL;
}
len = strlen(pacBuf);
if(pacBuf[len-1]==’\n’)
{
pacBuf[len-1] = ‘\0’;
}
else
{
while(getchar()!=’\n’)
{
;
}
}
return pacBuf;
}
char *MyReadLineFromTxt(char *pacBuf,int size,FILE *pf)//从文件读取
{
int len = 0;
char *p = 0;
if(NULL == pacBuf || size <= 0)
{
PrintPublicError(“Input Param is invalid \n”);
return NULL;
}
printf(“pacBuf%s\n”,pacBuf);
p = fgets(pacBuf,size,pf);
printf(“pacBuf%s\n”,pacBuf);
if(NULL == p)
{
// PrintPublicError(“fgets failed\n”);
// return NULL;
}
len = strlen(pacBuf);
if(pacBuf[len-1]==’\n’)
{
pacBuf[len-1] = ‘\0’;
}
else
{
while(fgetc(pf)!=’\n’)
{
;
}
}
return pacBuf;
}
TARGET = lanchatpublic
INC=…/…/inc
LIB=…/…/lib
CC = gcc
CFLAGS = -fPIC
OBJS= lanchatpublic.o lanchatprotocol.o
INCLUDES= -I$(INC)
%.o:%.c
$(CC) -c $(INCLUDES) $(CFLAGS) $< -o $@
install:$(OBJS)
(
C
C
)
−
f
P
I
C
−
s
h
a
r
e
d
−
o
l
i
b
(CC) -fPIC -shared -o lib
(CC)−fPIC−shared−olib(TARGET).so
(
O
B
J
S
)
−
L
(OBJS) -L
(OBJS)−L(LIB) -lpthread
cp lib$(TARGET).so $(LIB)
clean:
-rm $(OBJS) ./*.so *.o
(
L
I
B
)
/
l
i
b
(LIB)/lib
(LIB)/lib(TARGET).so -f