head.h
#ifndef __HEAD_H__
#define __HEAD_H__
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <pthread.h>
#include <sys/select.h>
#include <sys/time.h>
#include <poll.h>
#include <sys/un.h>
#define ERR_MSG(msg) do{\
fprintf(stderr,"line:%d ",__LINE__);\
perror(msg);\
}while(0)
#define ERR_MSG_1(msg) ERR_MSG(msg);return -1
#define IF_RET_ERR(ret,fi,msg) do{\
if (ret fi)\
{\
ERR_MSG_1(msg);\
}\
}while(0)
#define IF_RET_ERR_0(ret,msg) IF_RET_ERR(ret,<0,msg)
#define PORT 2222
#define IP "192.168.1.33"
#endif
客户端
#include "head.h"
struct cli_msg
{
char type;
char name[20];
char text[128];
};
int main(int argc, const char *argv[])
{
int sfd=socket(AF_INET,SOCK_DGRAM,0);
IF_RET_ERR_0(sfd,"socket");
struct sockaddr_in sin;
sin.sin_family=AF_INET;
sin.sin_port=htons(PORT);
sin.sin_addr.s_addr=inet_addr(IP);
printf("请输入名字>>>");
char name[20]="";
scanf("%s",name);
getchar();
struct cli_msg sndbuf;
sndbuf.type='L';
strcpy(sndbuf.name,name);
strcpy(sndbuf.text,"上线");
IF_RET_ERR_0(connect(sfd,(struct sockaddr*)&sin,sizeof(sin)),"connect");
IF_RET_ERR_0(send(sfd,&sndbuf,sizeof(sndbuf),0),"send");
struct cli_msg rcvbuf;
char buf[128]="";
ssize_t res=0;
pid_t cpid=fork();
if (cpid>0)
{
while(1)
{
bzero(buf,sizeof(buf));
fgets(buf,sizeof(buf),stdin);
sndbuf.type='C';
if (!strcmp(sndbuf.text,"quit"))
{
sndbuf.type='Q';
strcpy(sndbuf.text,"下线");
send(sfd,&sndbuf,sizeof(sndbuf),0);
break;
}
strcpy(sndbuf.text,buf);
send(sfd,&sndbuf,sizeof(sndbuf),0);
}
}
else if (0==cpid)
{
while (1)
{
res=recv(sfd,&rcvbuf,sizeof(rcvbuf),0);
IF_RET_ERR_0(res,"recv");
printf("[%s]:%s",rcvbuf.name,rcvbuf.text);
}
}
else
{
ERR_MSG_1("fork");
}
close(sfd);
return 0;
}
服务端
#include "head.h"
struct cli_msg
{
char type;
char name[20];
char text[128];
};
int do_login();
int do_chat();
int do_quit();
int main(int argc, const char *argv[])
{
int sfd=socket(AF_INET,SOCK_DGRAM,0);
IF_RET_ERR_0(sfd,"socket");
struct sockaddr_in sin;
sin.sin_family=AF_INET;
sin.sin_port=htons(PORT);
sin.sin_addr.s_addr=inet_addr(IP);
IF_RET_ERR_0(bind(sfd,(struct sockaddr*)&sin,sizeof(sin)),"bind");
char buf[128]="";
int len=sizeof(buf)/sizeof(buf[0]);
ssize_t res=0;
struct sockaddr_in cin;
socklen_t addrlen=sizeof(cin);
pid_t cpid=fork();
if (cpid>0)
{
struct sockaddr_in login[128]={0};
struct cli_msg rcvbuf;
while (1)
{
res=recvfrom(sfd,&rcvbuf,sizeof(rcvbuf),0,(struct sockaddr*)&cin,&addrlen);
IF_RET_ERR_0(res,"recvfrom");
printf("type=%c\n",rcvbuf.type);
switch(rcvbuf.type)
{
case 'L':
for (int i=0; i<len; i++)
{
if (!memcmp(&cin,&login[i],sizeof(cin)))
{
IF_RET_ERR_0(\
sendto(sfd,&rcvbuf,sizeof(rcvbuf),0,(struct sockaddr*)&login[i],sizeof(struct sockaddr_in)),"semdto");
}
}
for (int i=0; i<len; i++)
{
if(memcmp(login[i],0,sizeof(login[0]))
{
login[i]=cin;
break;
}
}
break;
case 'C':
for (int i=0; i<len; i++)
{
if (!memcmp(&cin,&login[i],sizeof(cin)))
{
IF_RET_ERR_0(\
sendto(sfd,&rcvbuf,sizeof(rcvbuf),0,(struct sockaddr*)&login[i],sizeof(struct sockaddr_in)),"semdto");
}
}
break;
case 'Q':
for (int i=0; i<len; i++)
{
if(login[i].sin_addr.s_addr==cin.sin_addr.s_addr\
|| login[i].sin_port==cin.sin_port)
{
memset(&login[i],0,sizeof(login[0]));
break;
}
}
for (int i=0; i<len; i++)
{
if (!memcmp(&cin,&login[i],sizeof(cin)))
{
IF_RET_ERR_0(\
sendto(sfd,&rcvbuf,sizeof(rcvbuf),0,(struct sockaddr*)&login[i],sizeof(struct sockaddr_in)),"semdto");
}
}
break;
default:
printf("协议%c错误\n", rcvbuf.type);
}
}
}
else if (0==cpid)
{
struct cli_msg sndbuf;
sndbuf.type='C';
strcpy(sndbuf.name,"系统消息");
bzero(buf,sizeof(buf));
fgets(buf,sizeof(buf),stdin);
strcpy(sndbuf.text,buf);
IF_RET_ERR_0(connect(sfd,(struct sockaddr*)&sin,sizeof(sin)),"connect");
IF_RET_ERR_0(send(sfd,&sndbuf,sizeof(sndbuf),0),"send");
}
else
{
ERR_MSG_1("fork");
}
close(sfd);
return 0;
}