比较简单的多人聊天程序,可直接运行。
主要是实现功能。没有界面也没有多余功能,只是实现群聊天的功能。c/s模式。
server端用select多路复用来做,可以接受多个客户端连接。client端启动2个线程控制发送和接受数据。
==================================================================================================
server.h
#include <unistd.h>
#include <stdio.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdlib.h>
#include <arpa/inet.h>
int init(struct sockaddr_in addr)
{
int sock;
int ret;// 记录错误马
sock=socket(AF_INET,SOCK_STREAM,0);
if(sock==-1)return -1;
ret=bind(sock,(struct sockaddr*)&addr,sizeof(addr));
if(ret==-1)return -1;
listen(sock,10);
return sock;
}
int Link(int sock)
{
int ret;//返回值
int Maxfd;//最大描述符号
int acpsock;//accpet函数返回值
struct sockaddr_in acpaddr;//accpet用到的地址
socklen_t len;//地址大小
char buf[20];//接受到的消息内容
int resock;//recv中用到的文件么描述符号、
int client[10];//存储连接的文件描述符
int i,j;//for循环变量
fd_set refd,allfd;
for(i=0;i<10;i++)
client[i]=-1;
FD_ZERO(&refd);
FD_ZERO(&allfd);
Maxfd=sock;
FD_SET(sock,&allfd);
while(1)
{
refd=allfd;
ret=select(Maxfd+1,&refd,0,0,0);
if(ret==-1)return -1;
if(FD_ISSET(sock,&refd))
{
printf("someone connect\n");
len=sizeof(acpaddr);
acpsock=accept(sock,(struct sockaddr*) &acpaddr,&len);
j=0;
while(j<10 && client[j]!=-1)++j;
client[j]=acpsock;
Maxfd=Maxfd>acpsock?Maxfd:acpsock;
FD_SET(acpsock,&allfd);
}
for(i=0;i<10;i++)
{
if((resock=client[i])<0)continue;
if(FD_ISSET(resock,&refd))
{
if((j=recv(resock,buf,20,0))==0)
{
printf("someone exit\n");
close(resock);
FD_CLR(resock,&allfd);
client[i]=-1;
}
else
{
printf("%s",buf);
for(i=0;i<10;i++)
{
if(client[i]!=resock)
{
//printf("%d ,",client[i]);
send(client[i],buf,j,0);
}
}
}
}
}
}
return 0;
}
=====================================================================
server.cpp
#include "server.h"
#define SERVER_PORT 8888
int main()
{
int Sock;
struct sockaddr_in servaddr;
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");//htonl(INADDR_ANY);
servaddr.sin_port = htons(SERVER_PORT);
Sock=init(servaddr);
if(-1==Sock)
{
printf("init error\n");
return -1;
}
printf("初始化成功\n");
Link(Sock);
return 0;
}
============================
client端启动2个线程用于读和写
client.h
#ifndef _CLENT_H_
#define _CLENT_H_
#include <unistd.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <iostream>
using namespace std;
int init( struct sockaddr_in addr)
{
int sock;
int ret;
sock=socket(AF_INET,SOCK_STREAM,0);
ret=connect(sock,(struct sockaddr*)&addr,sizeof(addr));
if(ret==-1)printf("connect erro\n");
return sock;
}
int Chat(int sock)
{
//启动两个线程进行读写
fd_set refd;
int Maxfd;
char talk[20];
int ret;
Maxfd=sock;
while(1)
{
FD_ZERO(&refd);
FD_SET(0,&refd);
FD_SET(sock,&refd);
ret=select(Maxfd+1,&refd,0,0,0);
if (ret==-1)break;
if(FD_ISSET(0,&refd))
{
//scanf("%s",talk);
memset(talk,0,20);
fgets(talk,20,stdin);
send(sock,talk,strlen(talk)+1,0);
}
else if(FD_ISSET(sock,&refd))
{
memset(talk,0,20);
recv(sock,talk,20,0);
printf("%s",talk);
}
}
}
void * ForRead(void *arg)
{
char talk[20];
int* sock;
sock=(int*)arg;
while(1)
{
memset(talk,0,20);
fgets(talk,20,stdin);
send(*sock,talk,strlen(talk)+1,0);
}
}
void * ForWrite(void *arg)
{
char talk[20];
int *sock=(int *)arg;
while(1)
{
memset(talk,0,20);
recv(*sock,talk,20,0);
cout<<talk;
}
}
#endif
====================================================================================================
client.cpp
#include "client.h"
int main()
{
pthread_t rid,wid;
int sock,ret;
struct sockaddr_in client_addr;
client_addr.sin_family = AF_INET;
client_addr.sin_port = htons(8888);
//client_addr1.sin_addr.s_addr = inet_addr("127.0.0,1");
inet_pton(AF_INET, "127.0.0.1", &client_addr.sin_addr);
sock=init(client_addr);
// Chat(sock);
pthread_create(&rid,0,ForRead,&sock);
pthread_create(&wid,0,ForWrite,&sock);
pthread_join(rid,0);
pthread_join(wid,0);
return 0;
}