step5 . day5 网络编程 基于UDP协议的多人网络在线聊天功能

模拟在线群聊功能,使用多进程完成聊天内容的接受和服务器端的转发,demo代码记录参考

//client_chat_UDP code

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <linux/in.h>
#include <sys/select.h>
#include <signal.h>

#define N 128
typedef struct massage{
char type;
char name[32];
char buf[N];
}MSG;


int main(int argc, const char *argv[])
{
//判断输入、提示格式
if(argc<3){
printf("Usrmag:%s <server IP> <PORT>\n",argv[0]);
return -1;
}

//创建通信套接字 使用UDP通讯协议
int socket_fd;
socket_fd = socket(AF_INET,SOCK_DGRAM,0);
if(socket_fd < 0){
perror("socket failed:");
return -1;
}
printf("socket ok\n");

//填充结构体
struct sockaddr_in serveraddr;
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
serveraddr.sin_port = htons(atoi(argv[2]));

//定义发送接收缓存
MSG sendmsg,recvmsg;
printf("please input your name :");
fgets(sendmsg.name,32,stdin);
sendmsg.name[strlen(sendmsg.name)-1] = '\0';
sendmsg.type = 'L';
sprintf(sendmsg.buf,"%s login",sendmsg.name);
sendto(socket_fd, &sendmsg, sizeof(sendmsg),0,(struct sockaddr*)&serveraddr,sizeof(serveraddr));
//创建多进程,一个用来接收,一个用来发送
int pid;
pid = fork();
if(pid < 0){
perror("fork failed:");
return -1;
}else if(pid == 0){
while(1){
printf("send msg>> ");
fgets(sendmsg.buf,N,stdin);
sendmsg.buf[strlen(sendmsg.buf)-1] = '\0';
if(strncmp(sendmsg.buf,"quit",4)!=0){
sendmsg.type = 'B';
sendto(socket_fd,&sendmsg,sizeof(sendmsg),0,(struct sockaddr*)&serveraddr,sizeof(serveraddr));
printf("send ok.\n");
}
else{
sendmsg.type = 'Q';
sendto(socket_fd,&sendmsg,sizeof(sendmsg),0,(struct sockaddr*)&serveraddr,sizeof(serveraddr));
printf("offline.\n");
close(socket_fd);
kill(getppid(), SIGKILL);
return -1;
}
}
}else{
while(1){
recvfrom(socket_fd, &recvmsg, sizeof(recvmsg),0,NULL,NULL);
printf("\n%s said:%s\n",recvmsg.name,recvmsg.buf);
}
}

close(socket_fd);
return 0;
}

 

 

//server_chat_UDP code

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <linux/in.h>
#include <sys/select.h>
#include <stdlib.h>


#define N 128
//消息结构体
typedef struct massage{
char type;
char name[32];
char buf[N];
}MSG;

//登陆用户链表
typedef struct node{
struct node *next;
char name[32];
struct sockaddr_in addr;
}linklist;

//模块操作判断函数
void login(int sockfd,MSG msg,struct sockaddr_in clientaddr,struct sockaddr_in serveraddr,linklist *head);
void quit(int sockfd,MSG msg,struct sockaddr_in serveraddr,linklist *head);
void broadcast(int socket_fd,MSG msg,linklist *head);

//链表创建函数
linklist * linklist_create(){

linklist *h = (linklist *)malloc(sizeof(linklist));
h->next = NULL;
return h;
}

int main(int argc, const char *argv[])
{
//判断输入、提示格式
if(argc<2){
printf("Usrmag:%s <PORT>\n",argv[0]);
return -1;
}

//创建通信套接字 使用UDP通讯协议
int socket_fd;
socket_fd = socket(AF_INET,SOCK_DGRAM,0);
if(socket_fd < 0){
perror("socket failed:");
return -1;
}
printf("socket ok\n");
//填充结构体
struct sockaddr_in serveraddr;
struct sockaddr_in clientaddr;
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
serveraddr.sin_port = htons(atoi(argv[1]));
socklen_t addrlen = sizeof(struct sockaddr_in);
socklen_t clientaddrlen = sizeof(struct sockaddr_in);
int bind_fd;
bind_fd = bind(socket_fd,(struct sockaddr*)&serveraddr,addrlen);
if(bind_fd < 0){
perror("bind failed:");
return -1;
}
printf("bind ok\n");

//定义发送接收缓存
MSG sendmsg,recvmsg;

//创建用户链表表头
linklist *head = linklist_create();

//创建多进程,一个用来接收,一个用来广播
int pid;
pid = fork();
if(pid < 0){
perror("fork failed:");
return -1;
}else if(pid ==0){ //子进程用来客户端的发送广播
while(1){
strcpy(sendmsg.name,"server");
sendmsg.type = 'B';
fgets(sendmsg.buf,N,stdin);
sendmsg.buf[strlen(sendmsg.buf)-1] = '\0';
sendto(socket_fd,&sendmsg,sizeof(sendmsg),0,(struct sockaddr *)&serveraddr,addrlen);
}
}else{
//父进程接受客户端发送消息
while(1){
recvfrom(socket_fd,&recvmsg,sizeof(recvmsg),0,(struct sockaddr *)&clientaddr,&clientaddrlen);

switch(recvmsg.type){
case 'L':
login(socket_fd,recvmsg,clientaddr,serveraddr,head);
break;
case 'B':
//服务器转发
broadcast(socket_fd,recvmsg,head);
break;
case 'Q':
//退出
printf("quit wait :\n");
printf("%s said:%s\n",recvmsg.name,recvmsg.buf);
quit(socket_fd,recvmsg,serveraddr,head);
break;
}
}

}
close(socket_fd);
return 0;
}

void login(int sockfd,MSG msg,struct sockaddr_in clientaddr,struct sockaddr_in serveraddr,linklist *head){


printf("%s login\n",msg.name);
linklist *p = head;
while(p->next != NULL){
sendto(sockfd,&msg,sizeof(msg),0,(struct sockaddr*)&(p->next->addr),sizeof(serveraddr));
p = p->next;
}
linklist *temp = linklist_create();
strcpy(temp->name,msg.name);
temp->addr = clientaddr;

temp->next = NULL;
p->next = temp;
}

void quit(int sockfd,MSG msg,struct sockaddr_in serveraddr,linklist *head){

linklist *p = head;
while(strcmp(p->next->name,msg.name)!=0){
p = p->next;
}
linklist *temp = p->next;
p->next = temp->next;

sprintf(msg.buf,"%s offline",msg.name);
msg.type = 'B';
sendto(sockfd,&msg,sizeof(msg),0,(struct sockaddr*)&serveraddr,sizeof(serveraddr));

free(temp);
temp = NULL;
}
void broadcast(int sockfd,MSG msg,linklist *head){

printf("%s said:%s\n",msg.name,msg.buf);
linklist *temp = head->next;
while(temp != NULL){
if(strcmp(temp->name,msg.name) ==0){
temp = temp->next;
}
else{
sendto(sockfd,&msg,sizeof(msg),0,(struct sockaddr*)&(temp->addr),sizeof(temp->addr));
temp = temp->next;
}

}

}

转载于:https://www.cnblogs.com/huiji12321/p/11378841.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值