实现udp的网络聊天室
服务器端:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#define ERR_MSG(msg) do{\
perror(msg);\
}while(0)
#define SUC_MSG(msg) do{\
printf("%s success\n",msg);\
}while(0)
#define SER_PORT 6666
#define SER_IP "192.168.10.104"
struct msg{
char type;
char name[20];
char text[128];
};
char buf[149];
int len = 0;
int cliNum = 0;
struct msg cliData;
struct sockaddr_in serIN;
int sfd = 0;
int res = 0;
pthread_t tid1,tid2;
struct sockaddr_in cin;
struct sockaddr_in cliIN[1022];
void *send_to_cli(void *arg){
while(1){
bzero(buf,sizeof(buf));
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf) - 1] = 0;
cliData.type = 'S';
strcpy(cliData.name,"system");
strcpy(cliData.text,buf);
bzero(buf,sizeof(buf));
*buf = cliData.type;
strcpy(buf+1,cliData.name);
strcpy(buf+21,cliData.text);
for(int i = 0; i < cliNum;i++){
res = sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)(cliIN + i),len);
if(res < 0){
ERR_MSG("send to cli");
}
}
}
}
void *recv_from_cli(void *arg){
while(1){
bzero(buf,sizeof(buf));
len = sizeof(cin);
res = recvfrom(sfd,buf,sizeof(buf),0,(struct sockaddr*)&cin,&len);
cliData.type = *buf;
strcpy(cliData.name,buf+1);
strcpy(cliData.text,buf+21);
if(res < 0){
ERR_MSG("Receive from cli");
}
if(res == 0)
{
printf("cli is off\n");
}
else if(res > 0)
{
if(*buf == 'L'){
res = write(1,"User ",5);
res = write(1,buf+1,sizeof(cliData.name));
printf(" has logged in.\n");
if(res < 0){
ERR_MSG("Log in msg");
}
cliIN[cliNum] = cin;
cliNum++;
*buf = 'L';
}else if(*buf == 'Q'){
res= write(1,"Client: ",8);
res = write(1,buf+1,sizeof(cliData.name));
printf(" has logged off.\n");
if(res < 0){
ERR_MSG("Offline message");
}
for(int i = 0; i < cliNum; i++){
if(cliIN[i].sin_port == cin.sin_port){
for(int j = i;j < cliNum - 1;j++){
cliIN[j] = cliIN[j+1];
}
break;
}
}
cliNum--;
}else if(*buf == 'C'){
res = write(1,buf,sizeof(char));
res = write(1,":",1);
res = write(1,buf+21,sizeof(buf)-21);
puts("");
if(res < 0){
ERR_MSG("Chat message");
}
}
bzero(buf,sizeof(buf));
*buf = cliData.type;
strcpy(buf+1,cliData.name);
strcpy(buf+21,cliData.text);
for(int i = 0; i < cliNum;i++){
if(cliIN[i].sin_port != cin.sin_port)
{
len = sizeof(cliIN[i]);
res = sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&cliIN[i],len);
if(res < 0){
ERR_MSG("send to cli");
}
}
}
}
}
}
int main(int argc, const char *argv[])
{
sfd = socket(AF_INET,SOCK_DGRAM,0);
if(sfd < 0){
ERR_MSG("socket");
}
SUC_MSG("server socket");
//bind the ip
serIN.sin_family = AF_INET;
serIN.sin_port = htons(SER_PORT);
serIN.sin_addr.s_addr = inet_addr(SER_IP);
if(bind(sfd,(struct sockaddr*)&serIN,sizeof(serIN)) < 0){
ERR_MSG("bind");
}
SUC_MSG("server bind");
if(pthread_create(&tid1,NULL,send_to_cli,NULL) < 0){
ERR_MSG("pthread_create");
}
if(pthread_create(&tid2,NULL,recv_from_cli,NULL) < 0){
ERR_MSG("pthread_create");
}
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
if(close(sfd) < 0){
ERR_MSG("close");
}
return 0;
}
客户端
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/select.h>
#define ERR_MSG(msg) do{\
perror(msg);\
}while(0)
#define SUC_MSG(msg) do{\
printf("%s success\n",msg);\
}while(0)
#define SER_PORT 6666
#define SER_IP "192.168.10.104"
struct msg{
char type;
char name[20];
char text[128];
};
char buf[149];
int len = 0;
struct msg cliData;
struct sockaddr_in serIN;
int sfd;
int res;
pthread_t tid1,tid2;
void *send_to_ser(void *arg){
while(1){
bzero(buf,sizeof(buf));
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf) - 1] = 0;
if(strcasecmp(buf,"q") == 0){
cliData.type = 'Q';
*buf = cliData.type;
strcpy(buf+1,cliData.name);
strcpy(buf+21,cliData.text);
res = sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&serIN,len);
if(res < 0){
ERR_MSG("send to server");
}
pthread_cancel(tid2);
pthread_exit(NULL);
}else{
cliData.type = 'C';
strcpy(cliData.text,buf);
bzero(buf,sizeof(buf));
*buf = cliData.type;
strcpy(buf+1,cliData.name);
strcpy(buf+21,cliData.text);
res = sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&serIN,len);
if(res < 0){
ERR_MSG("send to server");
}
}
}
}
void *recv_from_ser(void *arg){
while(1){
bzero(buf,sizeof(buf));
res = recvfrom(sfd,buf,sizeof(buf),0,(struct sockaddr*)&serIN,&len);
if(res < 0){
ERR_MSG("Receive from server");
}
if(res == 0)
{
printf("Server is off\n");
}
else if(res > 0)
{
if(*buf == 'S'){
res = write(1,"System: ",8);
res = write(1,buf+21,sizeof(buf)-21);
puts("");
if(res < 0){
ERR_MSG("system message");
}
}else if(*buf == 'Q'){
res = write(1,"Client ",7);
res = write(1,buf+1,sizeof(cliData.name));
if(res < 0){
ERR_MSG("Offline message");
}
printf(" is offline\n");
}else if(*buf == 'C'){
res = write(1,buf+1,sizeof(cliData.name));
res = write(1,":",1);
res = write(1,buf+21,sizeof(buf)-21);
puts("");
if(res < 0){
ERR_MSG("Chat message");
}
}else if(*buf == 'L'){
res = write(1,"Client ",7);
res = write(1,buf+1,sizeof(cliData.name));
printf("has logged in.\n");
if(res < 0){
ERR_MSG("Log in");
}
}
}
}
}
int main(int argc, const char *argv[])
{
sfd = socket(AF_INET,SOCK_DGRAM,0);
if(sfd < 0){
ERR_MSG("socket");
}
SUC_MSG("cli socket");
serIN.sin_family = AF_INET;
serIN.sin_port = htons(SER_PORT);
serIN.sin_addr.s_addr = inet_addr(SER_IP);
len = sizeof(serIN);
printf("Please log in first:\n");
bzero(buf,sizeof(buf));
fgets(cliData.name,sizeof(cliData.name),stdin);
cliData.name[strlen(cliData.name) - 1] = 0;
strcpy(cliData.text,"");
cliData.type = 'L';
strcpy(cliData.text,"");
*buf = cliData.type;
strcpy(buf+1,cliData.name);
strcpy(buf+21,cliData.text);
res = sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&serIN,len);
if(res < 0){
ERR_MSG("Log in failed.");
return -1;
}
if(pthread_create(&tid1,NULL,send_to_ser,NULL) < 0){
ERR_MSG("pthread_create");
}
if(pthread_create(&tid2,NULL,recv_from_ser,NULL) < 0){
ERR_MSG("pthread_create");
}
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
if(close(sfd) < 0){
ERR_MSG("close");
}
return 0;
}