UDP聊天室

pub.h   定义了一些消息的结构和宏变量

#ifndef _PUB_H_

#define _PUB_H_

#include <list>

#include <algorithm>

using namespace std;

// C2S

#define C2S_LOGIN            0x01

#define C2S_LOGOUT            0x02

#define C2S_ONLINE_USER        0x03

#define MSG_LEN                512

// S2C

#define S2C_LOGIN_OK        0x01

#define S2C_ALREADY_LOGINED    0x02

#define S2C_SOMEONE_LOGIN    0x03

#define S2C_SOMEONE_LOGOUT    0x04

#define S2C_ONLINE_USER        0x05

// C2C

#define C2C_CHAT            0x06

typedef struct message

{

int cmd;

char body[MSG_LEN];

} MESSAGE;

typedef struct user_info

{

char username[16];

unsigned int ip;

unsigned short port;

} USER_INFO;

typedef struct chat_msg

{

char username[16];

char msg[100];

}CHAT_MSG;

typedef list<USER_INFO> USER_LIST;

#endif /* _PUB_H_ */

chat.c

#include <unistd.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <signal.h>

#include <stdlib.h>

#include <stdio.h>

#include <errno.h>

#include <string.h>

#include "pub.h"

#define ERR_EXIT(m) \

do \

{ \

perror(m); \

exit(EXIT_FAILURE); \

} while(0)

// 当前用户名

char username[16];

// 聊天室成员列表

USER_LIST client_list;

void do_someone_login(MESSAGE& msg);

void do_someone_logout(MESSAGE& msg);

void do_getlist();

void do_chat();

void parse_cmd(char* cmdline, int sock, struct sockaddr_in *servaddr);

bool sendmsgto(int sock, char* username, char* msg);

void parse_cmd(char* cmdline, int sock, struct sockaddr_in *servaddr)

{

char cmd[10]={0};

char *p;

p = strchr(cmdline, ‘ ‘);

if (p != NULL)

*p = ‘\0‘;

strcpy(cmd, cmdline);

if (strcmp(cmd, "exit") == 0)

{

MESSAGE msg;

memset(&msg,0,sizeof(msg));

msg.cmd = htonl(C2S_LOGOUT);

strcpy(msg.body, username);

if (sendto(sock, &msg, sizeof(msg), 0, (struct sockaddr *)servaddr, sizeof(struct sockaddr_in)) < 0)

ERR_EXIT("sendto");

printf("user %s has logout server\n", username);

exit(EXIT_SUCCESS);

}

else if (strcmp(cmd, "send") == 0)

{

char peername[16]={0};

char msg[MSG_LEN]={0};

/* send  user  msg  */

/*       p     p2   */

while (*p++ == ‘ ‘) ;

char *p2;

p2 = strchr(p, ‘ ‘);

if (p2 == NULL)

{

printf("bad command\n");

printf("\nCommands are:\n");

printf("send username msg\n");

printf("list\n");

printf("exit\n");

printf("\n");

return;

}

*p2 = ‘\0‘;

strcpy(peername, p);

while (*p2++ == ‘ ‘) ;

strcpy(msg, p2);

sendmsgto(sock, peername, msg);

}

else if (strcmp(cmd, "list") == 0)

{

MESSAGE msg;

memset(&msg, 0, sizeof(msg));

msg.cmd = htonl(C2S_ONLINE_USER);

if (sendto(sock, &msg, sizeof(msg), 0, (struct sockaddr *)servaddr, sizeof(struct sockaddr_in)) < 0)

ERR_EXIT("sendto");

}

else

{

printf("bad command\n");

printf("\nCommands are:\n");

printf("send username msg\n");

printf("list\n");

printf("exit\n");

printf("\n");

}

}

bool sendmsgto(int sock, char* name, char* msg)

{

if (strcmp(name, username) == 0)

{

printf("can‘t send message to self\n");

return false;

}

USER_LIST::iterator it;

for (it=client_list.begin(); it != client_list.end(); ++it)

{

if (strcmp(it->username,name) == 0)

break;

}

if (it == client_list.end())

{

printf("user %s has not logined server\n", name);

return false;

}

MESSAGE m;

memset(&m,0,sizeof(m));

m.cmd = htonl(C2C_CHAT);

CHAT_MSG cm;

strcpy(cm.username, username);

strcpy(cm.msg, msg);

memcpy(m.body, &cm, sizeof(cm));

//strcpy(m.body,msg);

struct sockaddr_in    peeraddr;

memset(&peeraddr,0,sizeof(peeraddr));

peeraddr.sin_family      = AF_INET;

peeraddr.sin_addr.s_addr = it->ip;

peeraddr.sin_port        = it->port;

in_addr tmp;

tmp.s_addr = it->ip;

printf("sending message [%s] to user [%s] <-> %s:%d\n",  msg, name, inet_ntoa(tmp), ntohs(it->port));

sendto(sock, (const char*)&m, sizeof(m), 0, (struct sockaddr *)&peeraddr, sizeof(peeraddr));

return true;

}

void do_getlist(int sock)

{

int count;

recvfrom(sock, &count, sizeof(int), 0, NULL, NULL);

printf("has %d users logined server\n", ntohl(count));

client_list.clear();

int n = ntohl(count);

for (int i=0; i<n; i++)

{

USER_INFO user;

recvfrom(sock,&user, sizeof(USER_INFO), 0, NULL, NULL);

client_list.push_back(user);

in_addr tmp;

tmp.s_addr = user.ip;

printf("%s <-> %s:%d\n", user.username, inet_ntoa(tmp), ntohs(user.port));

}

}

void do_someone_login(MESSAGE& msg)

{

USER_INFO *user = (USER_INFO*)msg.body;

in_addr tmp;

tmp.s_addr = user->ip;

printf("%s <-> %s:%d has logined server\n", user->username, inet_ntoa(tmp), ntohs(user->port));

client_list.push_back(*user);

}

void do_someone_logout(MESSAGE& msg)

{

USER_LIST::iterator it;

for (it=client_list.begin(); it != client_list.end(); ++it)

{

if (strcmp(it->username,msg.body) == 0)

break;

}

if (it != client_list.end())

client_list.erase(it);

printf("user %s has logout server\n", msg.body);

}

void do_chat(const MESSAGE& msg)

{

CHAT_MSG *cm = (CHAT_MSG*)msg.body;

printf("recv a msg [%s] from [%s]\n", cm->msg, cm->username);

//recvfrom(sock, &count, sizeof(int), 0, NULL, NULL);

}

void chat_cli(int sock)

{

struct sockaddr_in servaddr;

memset(&servaddr, 0, sizeof(servaddr));

servaddr.sin_family = AF_INET;

servaddr.sin_port = htons(5188);

servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");

struct sockaddr_in peeraddr;

socklen_t peerlen;

MESSAGE msg;

while (1)

{

memset(username,0,sizeof(username));

printf("please inpt your name:");

fflush(stdout);

scanf("%s", username);

memset(&msg, 0, sizeof(msg));

msg.cmd = htonl(C2S_LOGIN);

strcpy(msg.body, username);

sendto(sock, &msg, sizeof(msg), 0, (struct sockaddr *)&servaddr, sizeof(servaddr));

memset(&msg, 0, sizeof(msg));

recvfrom(sock, &msg, sizeof(msg), 0, NULL, NULL);

int cmd = ntohl(msg.cmd);

if (cmd == S2C_ALREADY_LOGINED)

printf("user %s already logined server, please use another username\n", username);

else if (cmd == S2C_LOGIN_OK)

{

printf("user %s has logined server\n", username);

break;

}

}

int count;

recvfrom(sock, &count, sizeof(int), 0, NULL, NULL);

int n = ntohl(count);

printf("has %d users logined server\n", n);

for (int i=0; i<n; i++)

{

USER_INFO user;

recvfrom(sock, &user, sizeof(USER_INFO), 0, NULL, NULL);

client_list.push_back(user);

in_addr tmp;

tmp.s_addr = user.ip;

printf("%d %s <-> %s:%d\n", i, user.username, inet_ntoa(tmp), ntohs(user.port));

}

printf("\nCommands are:\n");

printf("send username msg\n");

printf("list\n");

printf("exit\n");

printf("\n");

fd_set rset;

FD_ZERO(&rset);

int nready;

while (1)

{

FD_SET(STDIN_FILENO, &rset);

FD_SET(sock, &rset);

nready = select(sock+1, &rset, NULL, NULL, NULL);

if (nready == -1)

ERR_EXIT("select");

if (nready == 0)

continue;

if (FD_ISSET(sock, &rset))

{

peerlen = sizeof(peeraddr);

memset(&msg,0,sizeof(msg));

recvfrom(sock, &msg, sizeof(msg), 0, (struct sockaddr *)&peeraddr, &peerlen);

int cmd = ntohl(msg.cmd);

switch (cmd)

{

case S2C_SOMEONE_LOGIN:

do_someone_login(msg);

break;

case S2C_SOMEONE_LOGOUT:

do_someone_logout(msg);

break;

case S2C_ONLINE_USER:

do_getlist(sock);

break;

case C2C_CHAT:

do_chat(msg);

break;

default:

break;

}

}

if (FD_ISSET(STDIN_FILENO, &rset))

{

char cmdline[100] = {0};

if (fgets(cmdline, sizeof(cmdline), stdin) == NULL)

break;

if (cmdline[0] == ‘\n‘)

continue;

cmdline[strlen(cmdline) - 1] = ‘\0‘;

parse_cmd(cmdline, sock, &servaddr);

}

}

memset(&msg,0,sizeof(msg));

msg.cmd = htonl(C2S_LOGOUT);

strcpy(msg.body, username);

sendto(sock, (const char*)&msg, sizeof(msg), 0, (struct sockaddr *)&servaddr, sizeof(servaddr));

close(sock);

}

int main(void)

{

int sock;

if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0)

ERR_EXIT("socket");

chat_cli(sock);

return 0;

}

chatsrv.cpp

#include <unistd.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <signal.h>

#include <stdlib.h>

#include <stdio.h>

#include <errno.h>

#include <string.h>

#include "pub.h"

#define ERR_EXIT(m) \

do \

{ \

perror(m); \

exit(EXIT_FAILURE); \

} while(0)

// 当前用户名

char username[16];

// 聊天室成员列表

USER_LIST client_list;

void do_someone_login(MESSAGE& msg);

void do_someone_logout(MESSAGE& msg);

void do_getlist();

void do_chat();

void parse_cmd(char* cmdline, int sock, struct sockaddr_in *servaddr);

bool sendmsgto(int sock, char* username, char* msg);

void parse_cmd(char* cmdline, int sock, struct sockaddr_in *servaddr)

{

char cmd[10]={0};

char *p;

p = strchr(cmdline, ‘ ‘);

if (p != NULL)

*p = ‘\0‘;

strcpy(cmd, cmdline);

if (strcmp(cmd, "exit") == 0)

{

MESSAGE msg;

memset(&msg,0,sizeof(msg));

msg.cmd = htonl(C2S_LOGOUT);

strcpy(msg.body, username);

if (sendto(sock, &msg, sizeof(msg), 0, (struct sockaddr *)servaddr, sizeof(struct sockaddr_in)) < 0)

ERR_EXIT("sendto");

printf("user %s has logout server\n", username);

exit(EXIT_SUCCESS);

}

else if (strcmp(cmd, "send") == 0)

{

char peername[16]={0};

char msg[MSG_LEN]={0};

/* send  user  msg  */

/*       p     p2   */

while (*p++ == ‘ ‘) ;

char *p2;

p2 = strchr(p, ‘ ‘);

if (p2 == NULL)

{

printf("bad command\n");

printf("\nCommands are:\n");

printf("send username msg\n");

printf("list\n");

printf("exit\n");

printf("\n");

return;

}

*p2 = ‘\0‘;

strcpy(peername, p);

while (*p2++ == ‘ ‘) ;

strcpy(msg, p2);

sendmsgto(sock, peername, msg);

}

else if (strcmp(cmd, "list") == 0)

{

MESSAGE msg;

memset(&msg, 0, sizeof(msg));

msg.cmd = htonl(C2S_ONLINE_USER);

if (sendto(sock, &msg, sizeof(msg), 0, (struct sockaddr *)servaddr, sizeof(struct sockaddr_in)) < 0)

ERR_EXIT("sendto");

}

else

{

printf("bad command\n");

printf("\nCommands are:\n");

printf("send username msg\n");

printf("list\n");

printf("exit\n");

printf("\n");

}

}

bool sendmsgto(int sock, char* name, char* msg)

{

if (strcmp(name, username) == 0)

{

printf("can‘t send message to self\n");

return false;

}

USER_LIST::iterator it;

for (it=client_list.begin(); it != client_list.end(); ++it)

{

if (strcmp(it->username,name) == 0)

break;

}

if (it == client_list.end())

{

printf("user %s has not logined server\n", name);

return false;

}

MESSAGE m;

memset(&m,0,sizeof(m));

m.cmd = htonl(C2C_CHAT);

CHAT_MSG cm;

strcpy(cm.username, username);

strcpy(cm.msg, msg);

memcpy(m.body, &cm, sizeof(cm));

//strcpy(m.body,msg);

struct sockaddr_in    peeraddr;

memset(&peeraddr,0,sizeof(peeraddr));

peeraddr.sin_family      = AF_INET;

peeraddr.sin_addr.s_addr = it->ip;

peeraddr.sin_port        = it->port;

in_addr tmp;

tmp.s_addr = it->ip;

printf("sending message [%s] to user [%s] <-> %s:%d\n",  msg, name, inet_ntoa(tmp), ntohs(it->port));

sendto(sock, (const char*)&m, sizeof(m), 0, (struct sockaddr *)&peeraddr, sizeof(peeraddr));

return true;

}

void do_getlist(int sock)

{

int count;

recvfrom(sock, &count, sizeof(int), 0, NULL, NULL);

printf("has %d users logined server\n", ntohl(count));

client_list.clear();

int n = ntohl(count);

for (int i=0; i<n; i++)

{

USER_INFO user;

recvfrom(sock,&user, sizeof(USER_INFO), 0, NULL, NULL);

client_list.push_back(user);

in_addr tmp;

tmp.s_addr = user.ip;

printf("%s <-> %s:%d\n", user.username, inet_ntoa(tmp), ntohs(user.port));

}

}

void do_someone_login(MESSAGE& msg)

{

USER_INFO *user = (USER_INFO*)msg.body;

in_addr tmp;

tmp.s_addr = user->ip;

printf("%s <-> %s:%d has logined server\n", user->username, inet_ntoa(tmp), ntohs(user->port));

client_list.push_back(*user);

}

void do_someone_logout(MESSAGE& msg)

{

USER_LIST::iterator it;

for (it=client_list.begin(); it != client_list.end(); ++it)

{

if (strcmp(it->username,msg.body) == 0)

break;

}

if (it != client_list.end())

client_list.erase(it);

printf("user %s has logout server\n", msg.body);

}

void do_chat(const MESSAGE& msg)

{

CHAT_MSG *cm = (CHAT_MSG*)msg.body;

printf("recv a msg [%s] from [%s]\n", cm->msg, cm->username);

//recvfrom(sock, &count, sizeof(int), 0, NULL, NULL);

}

void chat_cli(int sock)

{

struct sockaddr_in servaddr;

memset(&servaddr, 0, sizeof(servaddr));

servaddr.sin_family = AF_INET;

servaddr.sin_port = htons(5188);

servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");

struct sockaddr_in peeraddr;

socklen_t peerlen;

MESSAGE msg;

while (1)

{

memset(username,0,sizeof(username));

printf("please inpt your name:");

fflush(stdout);

scanf("%s", username);

memset(&msg, 0, sizeof(msg));

msg.cmd = htonl(C2S_LOGIN);

strcpy(msg.body, username);

sendto(sock, &msg, sizeof(msg), 0, (struct sockaddr *)&servaddr, sizeof(servaddr));

memset(&msg, 0, sizeof(msg));

recvfrom(sock, &msg, sizeof(msg), 0, NULL, NULL);

int cmd = ntohl(msg.cmd);

if (cmd == S2C_ALREADY_LOGINED)

printf("user %s already logined server, please use another username\n", username);

else if (cmd == S2C_LOGIN_OK)

{

printf("user %s has logined server\n", username);

break;

}

}

int count;

recvfrom(sock, &count, sizeof(int), 0, NULL, NULL);

int n = ntohl(count);

printf("has %d users logined server\n", n);

for (int i=0; i<n; i++)

{

USER_INFO user;

recvfrom(sock, &user, sizeof(USER_INFO), 0, NULL, NULL);

client_list.push_back(user);

in_addr tmp;

tmp.s_addr = user.ip;

printf("%d %s <-> %s:%d\n", i, user.username, inet_ntoa(tmp), ntohs(user.port));

}

printf("\nCommands are:\n");

printf("send username msg\n");

printf("list\n");

printf("exit\n");

printf("\n");

fd_set rset;

FD_ZERO(&rset);

int nready;

while (1)

{

FD_SET(STDIN_FILENO, &rset);

FD_SET(sock, &rset);

nready = select(sock+1, &rset, NULL, NULL, NULL);

if (nready == -1)

ERR_EXIT("select");

if (nready == 0)

continue;

if (FD_ISSET(sock, &rset))

{

peerlen = sizeof(peeraddr);

memset(&msg,0,sizeof(msg));

recvfrom(sock, &msg, sizeof(msg), 0, (struct sockaddr *)&peeraddr, &peerlen);

int cmd = ntohl(msg.cmd);

switch (cmd)

{

case S2C_SOMEONE_LOGIN:

do_someone_login(msg);

break;

case S2C_SOMEONE_LOGOUT:

do_someone_logout(msg);

break;

case S2C_ONLINE_USER:

do_getlist(sock);

break;

case C2C_CHAT:

do_chat(msg);

break;

default:

break;

}

}

if (FD_ISSET(STDIN_FILENO, &rset))

{

char cmdline[100] = {0};

if (fgets(cmdline, sizeof(cmdline), stdin) == NULL)

break;

if (cmdline[0] == ‘\n‘)

continue;

cmdline[strlen(cmdline) - 1] = ‘\0‘;

parse_cmd(cmdline, sock, &servaddr);

}

}

memset(&msg,0,sizeof(msg));

msg.cmd = htonl(C2S_LOGOUT);

strcpy(msg.body, username);

sendto(sock, (const char*)&msg, sizeof(msg), 0, (struct sockaddr *)&servaddr, sizeof(servaddr));

close(sock);

}

int main(void)

{

int sock;

if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0)

ERR_EXIT("socket");

chat_cli(sock);

return 0;

}

makefile:

.PHONY:clean all

CC=g++

CPPFLAGS=-Wall -g

BIN=chatsrv chatcli

all:$(BIN)

%.o:%.cpp

$(CC) $(CPPFLAGS) -c $< -o [email protected]

clean:

rm -f *.o $(BIN)

实现的代码,有看不懂的可以留言!

UDP聊天室

时间: 2024-12-14 18:40:55

UDP聊天室的相关文章

python 入门 socket 实现udp聊天室

什么是 Socket? Socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯. socket()函数 Python 中,我们用 socket()函数来创建套接字,语法格式如下: socket.socket([family[, type[, proto]]]) 参数 family: 套接字家族可以使AF_UNIX或者AF_INET type: 套接字类型可以根据是面向连接的还是非连接分为SOCK

UDP聊天室 java

要求实现一个聊天室,能同时接收和发送信息. 下面的代码用两个线程在处理发送和接收信息.信息在网际的传递采用UDP协议.这种方法不需要建立连接,因此比较高效,但是正因补永济哪里连接,因此会有丢包的不安全性. import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.In

C 基于UDP实现一个简易的聊天室

引言 本文是围绕Linux udp api 构建一个简易的多人聊天室.重点看思路,帮助我们加深 对udp开发中一些api了解.相对而言udp socket开发相比tcp socket开发注意的细节要少很多. 但是水也很深. 本文就当是一个demo整合帮助开发者回顾和继续了解 linux udp开发的基本流程. 首先我们来看看 linux udp 和 tcp的异同. /* 这里简单比较一下TCP和UDP在编程实现上的一些区别: TCP流程 建立一个TCP连接需要三次握手,而断开一个TCP则需要四个

Photon服务器引擎(二)socket/TCP/UDP基础及Unity聊天室的实现

Photon服务器引擎(二)socket/TCP/UDP基础及Unity聊天室的实现 我们平时说的最多的socket是什么呢,实际上socket是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API). 通过Socket,我们才能使用TCP/IP协议.实际上,Socket跟TCP/IP协议没有必然的联系.Socket编程接口在设计的时候,就希望也能适应其他的网络协议.所以说,Socket的出现只是使得程序员更方便地使用TCP/IP协议栈而已,是对TCP/IP协议的抽象,

15.基于UDP协议的聊天室程序

使用UDP协议完成一个聊天室程序的小项目,大部分代码都有注释,一看就能看到的. 实现的功能:               (1)查看/显示已经登陆的用户信息               (2)向已登陆的用户发送消息               (3)输出错误消息,给予提示               (4)退出 共有三个文件: chat_public.h #ifndef _CHAT_PUB_H_ #define _CHAT_PUB_H_ //chat_public.h #include <lis

Java网络编程 - 基于UDP协议 实现简单的聊天室程序

最近比较闲,一直在抽空回顾一些Java方面的技术应用. 今天没什么事做,基于UDP协议,写了一个非常简单的聊天室程序. 现在的工作,很少用到socket,也算是对Java网络编程方面的一个简单回忆. 先看一下效果: 实现的效果可以说是非常非常简单,但还是可以简单的看到一个实现原理. "聊天室001"的用户,小红和小绿相互聊了两句,"聊天室002"的小黑无人理会,在一旁寂寞着. 看一下代码实现: 1.首先是消息服务器的实现,功能很简单: 将客户端的信息(进入了哪一个聊

UDP传输:简易聊天室的搭建。。。

转载请注明出处,谢谢:http://blog.csdn.net/harryweasley/article/details/45665309 最近看了一个教学视频,学习socket编程,里面有一个例子感觉写的不错,我就在此整理一下,帮助我回忆,查看. 编写一个聊天程序. 有收数据的部分,和发数据的部分. 这两部分需要同时执行. 那就需要用到多线程技术. 一个线程控制收,一个线程控制发. 因为收和发动作是不一致的,所以要定义两个run方法. 而且这两个方法要封装到不同的类中. 效果如图所示: 因为我

【tcp-ip学习总结】基于udp的多人聊天室,带有登录注册功能

环境;vs2010,vs2013 服务器端 #include<stdio.h> #include<Winsock2.h> #include<stdlib.h> #pragma comment(lib,"Ws2_32.lib") typedef struct { char username[30];//用户名 char password[50];//用户密码 struct sockaddr_in addr;//用户的地址 int isOnlie;//是

UDP聊天

import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; public class ChatDemo { public