php第一季网站开发实例教程,网站的技术维护一般要做些什么,网站投稿源码,河南省能源规划建设局网站基于UDP的网络聊天室
项目需求#xff1a;
如果有用户登录#xff0c;其他用户可以收到这个人的登录信息如果有人发送信息#xff0c;其他用户可以收到这个人的群聊信息如果有人下线#xff0c;其他用户可以收到这个人的下线信息服务器可以发送系统信息 服务器端代码 #in…基于UDP的网络聊天室
项目需求
如果有用户登录其他用户可以收到这个人的登录信息如果有人发送信息其他用户可以收到这个人的群聊信息如果有人下线其他用户可以收到这个人的下线信息服务器可以发送系统信息 服务器端代码 #includemyhead.h
#define SER_PORT 8888
#define SER_IP 192.168.117.74
#define PRINT_ERR(msg) do { printf(%s,%d,%s\n, __FILE__, __LINE__, __func__); perror(msg); exit(-1); } while (0)typedef struct
{char code; //操作码char name[32];char txt[128];
} msg_t;
//链表结构体
typedef struct _NODE
{struct sockaddr_in c_addr;struct _NODE *next;
} node_t;void creat_link(node_t **head);
int do_register(int sockfd, msg_t msg, struct sockaddr_in clientaddr, node_t *phead);
int do_group_chat(int sockfd, msg_t msg, struct sockaddr_in clientaddr, node_t *phead);
int quit_group_chat(int sockfd, msg_t msg, struct sockaddr_in clientaddr, node_t *phead);int main(int argc, const char *argv[])
{//创建套接字int sockfd;if ((sockfd socket(AF_INET, SOCK_DGRAM, 0)) -1){PRINT_ERR(socket error);}//创建服务器网络信息结构体struct sockaddr_in serviceaddr;memset(serviceaddr, 0, sizeof(serviceaddr));serviceaddr.sin_family AF_INET;serviceaddr.sin_addr.s_addr inet_addr(argv[1]);serviceaddr.sin_port htons(atoi(argv[2]));socklen_t serviceaddr_len sizeof(serviceaddr);//将服务器网络信息结构体与套接字绑定if (bind(sockfd, (struct sockaddr *)serviceaddr, serviceaddr_len) -1){PRINT_ERR(bind error);}//创建客户端网络信息结构体struct sockaddr_in clientaddr;memset(clientaddr, 0, sizeof(clientaddr));socklen_t clientaddr_len sizeof(clientaddr);msg_t msg;//创建父子进程pid_t pid;pid fork();if (pid -1){PRINT_ERR(fork error);}else if (pid 0){//子进程//接受数据并处理//定义链表头节点node_t *phead NULL;creat_link(phead);phead-next NULL;while (1){memset(msg, 0, sizeof(msg));memset(clientaddr, 0, sizeof(clientaddr));if ((recvfrom(sockfd, msg, sizeof(msg), 0, (struct sockaddr *)clientaddr, clientaddr_len)) -1){PRINT_ERR(recvfrom error);}printf(%8s : [%s]\n, msg.name, msg.txt);switch (msg.code){case L:do_register(sockfd, msg, clientaddr, phead);break;case C:do_group_chat(sockfd, msg, clientaddr, phead);break;case Q:quit_group_chat(sockfd, msg, clientaddr, phead);break;}}}else if (pid 0){//父进程//发系统消息msg.codeC;strcpy(msg.name,server);while(1){fgets(msg.txt,128,stdin);msg.txt[strlen(msg.txt)-1]\0;if(sendto(sockfd,msg,sizeof(msg_t),0,(struct sockaddr *)serviceaddr,serviceaddr_len)-1){PRINT_ERR(sendto error);}}}close(sockfd);return 0;
}
//创建链表头节点函数
void creat_link(node_t **head)
{*head (node_t *)malloc(sizeof(node_t));
}
//登录操作
int do_register(int sockfd, msg_t msg, struct sockaddr_in clientaddr, node_t *phead)
{//遍历链表将登录信息发送给所以人node_t *p phead;while (p-next ! NULL){p p-next;if (sendto(sockfd, msg, sizeof(msg_t), 0, (struct sockaddr *)(p-c_addr), sizeof(p-c_addr)) -1){PRINT_ERR(recvfrom error);}}//将登录的客户端信息插入保存在链表//头插//定义一个新的指针保存客户端信息node_t *newp NULL;creat_link(newp);newp-c_addr clientaddr;newp-next phead-next;phead-next newp;return 0;
}int do_group_chat(int sockfd, msg_t msg, struct sockaddr_in clientaddr, node_t *phead)
{//遍历链表将消息发给除自己之外的所有人node_t *p phead;while (p-next ! NULL){p p-next;//判断链表客户端信息是否是自己//是自己就不发送if (memcmp((p-c_addr), clientaddr, sizeof(clientaddr))){if (sendto(sockfd, msg, sizeof(msg_t), 0, (struct sockaddr *)(p-c_addr), sizeof(p-c_addr)) -1){PRINT_ERR(recvfrom error);}}}return 0;
}
//退出群聊操作
int quit_group_chat(int sockfd, msg_t msg, struct sockaddr_in clientaddr, node_t *phead)
{node_t *p phead;while (p-next ! NULL){//判断链表客户端信息是否是自己//是自己就不发送并且将自己的客户端信息在链表内删除if (memcmp((p-next-c_addr), clientaddr, sizeof(clientaddr))){p p-next;if (sendto(sockfd, msg, sizeof(msg_t), 0, (struct sockaddr *)(p-c_addr), sizeof(p-c_addr)) -1){PRINT_ERR(recvfrom error);}}else{node_t *pnew;pnew p-next;p-next pnew-next;pnew-next NULL;free(pnew);pnew NULL;}}return 0;
}客户端代码 #includemyhead.h
#define SER_PORT 8888
#define SER_IP 192.168.117.74
#define PRINT_ERR(msg) do { printf(%s,%d,%s\n, __FILE__, __LINE__, __func__); perror(msg); exit(-1); } while (0)typedef struct
{char code; //操作码 char name[32];char txt[128];
} msg_t;int main(int argc, const char *argv[])
{//创建套接字int sockfd;if ((sockfd socket(AF_INET, SOCK_DGRAM, 0)) -1){PRINT_ERR(socket error);}//创建服务器网络信息结构体struct sockaddr_in serviceaddr;memset(serviceaddr, 0, sizeof(serviceaddr));serviceaddr.sin_family AF_INET;serviceaddr.sin_addr.s_addr inet_addr(argv[1]);serviceaddr.sin_port htons(atoi(argv[2]));socklen_t serviceaddr_len sizeof(serviceaddr);//给服务器发送登录数据包msg_t msg;memset(msg, 0, sizeof(msg_t));msg.code L;printf(请输入用户名);fgets(msg.name, 32, stdin);msg.name[strlen(msg.name) - 1] \0;strcpy(msg.txt, 加入群聊);if (sendto(sockfd, msg, sizeof(msg_t), 0, (struct sockaddr *)serviceaddr, serviceaddr_len) -1){PRINT_ERR(sendto error);}//创建父子进程pid_t pid;pid fork();if (pid -1){PRINT_ERR(fork error);}else if (pid 0){//子进程//接受数据并处理while (1){//每次循环前将msg置零memset(msg, 0, sizeof(msg));//接受服务器发过来的信息并打印到终端上if (recvfrom(sockfd, msg, sizeof(msg_t), 0, NULL, NULL) -1){PRINT_ERR(recvfrom error);}printf(%8s:[%s]\n, msg.name, msg.txt);}}else if (pid 0){//父进程//发送消息while (1){ //memset会把name清除msg.code C;fgets(msg.txt, 128, stdin);msg.txt[strlen(msg.txt) - 1] \0;if (strcmp(msg.txt, quit) 0){msg.code Q;strcpy(msg.txt, 退出群聊);}if (sendto(sockfd, msg, sizeof(msg_t), 0, (struct sockaddr *)serviceaddr, serviceaddr_len) -1){PRINT_ERR(sendto error);}if (strcmp(msg.txt, 退出群聊) 0){break;}}kill(pid,SIGKILL);wait(NULL);close(sockfd);}return 0;
}