客户端A发送消息,服务端转发消息给其他客户端。
服务端;
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
#include <pthread.h>
#include <fcntl.h>
#define LISTENQ 2 //最大监听队列
#define PORT 5000 //监听端口
#define MAXFD 2 //最大的在线用户数量
static int maxi = 0; //maxi表示当前client数组中最大的用户的i值
typedef struct sockNode SOCKNODE;
struct sockNode
{
int fd;
struct sockNode *pNext;
};
SOCKNODE sockList; // 全局的套接字链表
void initList(SOCKNODE *sockList)
{
sockList = (SOCKNODE *)malloc(sizeof(SOCKNODE));
sockList->pNext = NULL;
sockList->fd = 0;
}
void insertList(SOCKNODE *sockList, SOCKNODE *newSock) //头部插入链表
{
SOCKNODE *p = sockList;
while(p->pNext != NULL)
{
p = p->pNext;
}
p->pNext = newSock;
}
void transmit(int fd, char *buffer)
{
SOCKNODE *sock = &sockList;
sock = sock->pNext; // 第一个节点
while(sock->fd != fd || sock->pNext != NULL) //相邻
{
if(sock->fd == fd && sock->pNext != NULL) // 满足while第一个条件,跳过,第二条件,执行
sock = sock->pNext;
strcat(buffer, "from othgers!");
send(sock->fd, buffer, strlen(buffer),0);
if(sock->pNext == NULL)// 到达末尾
break;
else
sock = sock->pNext;
}
}
void recvandsend(void) //监听转发线程入口函数
{
int index=0;
int nbytes=0;
char buffer[1024];
int len;
int outindex=0;
printf("receive socket and return message!\n");
while(1)
{
SOCKNODE *sock = &sockList;
while(sock->pNext != NULL)
{
sock = sock->pNext;
memset(buffer, 0, sizeof(buffer));
nbytes = 0;
nbytes = recv(sock->fd, buffer, sizeof(buffer),0);
if(nbytes > 0) // 在某个套接字有消息进来
{
buffer[nbytes] = '\0';
printf("%s\n", buffer);
transmit(sock->fd, buffer);
}
}
}
pthread_exit(NULL);
exit(1);
}
int closeConnection(int sockfd)
{
char buffer[1024];
memset(buffer, 0 ,sizeof(buffer));
strncpy(buffer, "close", sizeof("close"));
if(write(sockfd, buffer, sizeof(buffer)) == -1)
return 1;
else
return 0;
}
int connectSucceeddMess(int sockfd)
{
char buffer[1024];
memset(buffer, 0 ,sizeof(buffer));
strncpy(buffer, "SERVER : welecome to this chat room!", sizeof("SERVER : welecome to this chat room!"));
if(write(sockfd, buffer, sizeof(buffer)) == -1)
return 1;
else
return 0;
}
int main(int argc, char *argv[])
{
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
int sin_size;
int sockfd, new_fd;
int thr_id; /* thread ID for the newly createdthread */
pthread_t p_thread; /* thread's structure */
SOCKNODE *sockNew;
char buffer[1024];
int nbytes=0;
int flags;
initList(&sockList); // 初始化套接字链表
if(argc != 1)
{
fprintf(stderr,"Usage:%sportnumber\a\n",argv[0]);
exit(1);
}
/* 服务器端开始建立 socket 描述符 */
if((sockfd = socket(AF_INET,SOCK_STREAM,0))==-1)
{
fprintf(stderr,"Socketerror:%s\n\a",strerror(errno));
exit(1);
}
/* 服务器端填充 sockaddr 结构 */
bzero(&server_addr,sizeof(struct sockaddr_in));
server_addr.sin_family=AF_INET;
server_addr.sin_addr.s_addr=htonl(INADDR_ANY);
server_addr.sin_port=htons(PORT);
/* 捆绑 sockfd 描述符 */
if(bind(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1)
{
fprintf(stderr,"Binderror:%s\n\a",strerror(errno));
exit(1);
}
printf("Server Port : %d ... ...\n",PORT);
/* 监听 sockfd 描述符 */
if(listen(sockfd,LISTENQ)==-1)
{
fprintf(stderr,"Listenerror:%s\n\a",strerror(errno));
exit(1);
}
thr_id = pthread_create(&p_thread, NULL, recvandsend, NULL);
while(1)
{
// 服务器阻塞,直到客户程序建立连接
sin_size = sizeof(struct sockaddr_in);
new_fd = accept(sockfd,(struct sockaddr *)(&client_addr),&sin_size);
if(maxi >= MAXFD)
{
printf("will colse socket %d!\n",new_fd);
if((new_fd != -1) && (closeConnection(new_fd) == 0))
{
close(new_fd);
printf("close %d connection success\n",new_fd);
}
}
else
{
if(new_fd == -1)
{
printf("socket Error!\n");
exit(1);
}
else
{
if(!connectSucceeddMess(new_fd))
{
// 设置非阻塞方式
flags = fcntl(new_fd, F_GETFL, 0);
fcntl(new_fd, F_SETFL, flags | O_NONBLOCK);
sockNew = (SOCKNODE *)malloc(sizeof(SOCKNODE));
sockNew->fd = new_fd;
sockNew->pNext = NULL;
insertList(&sockList, sockNew); // 新套接字插入到链表中
printf("client %d to Chat Room!\n", new_fd);
maxi = maxi + 1;
}
}
}
}
close(sockfd);
exit(0);
}
客户端:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
#include <pthread.h>
#define TRUE 1
#define PORT 5000
static int sockfd;
static int closeFlag = 1;
void closeClient()
{
char mes[1024];
int nbytes=0;
int re;
nbytes = read(sockfd, mes, sizeof(mes));
re = strncmp(mes, "close", sizeof("close"));
printf("mes is [%s]\n", mes);
if(re == 0)
{
printf("will colse socke, and exit client!\n");
exit(1);
}
}
void* recvfromserver() //接受服务器消息线程入口函数
{
char mes[1024];
int nbytes=0;
int re;
while(1)
{
memset(mes, 0, sizeof(mes));
nbytes = read(sockfd, mes, sizeof(mes));
if(nbytes > 0)
{
mes[nbytes] = '\0';
printf("%s\n", mes);
}
re = strncmp(mes, "close", sizeof("close"));
if(re == 0)
{
printf("will colse socke, and exit client!\n");
closeFlag = 0;
}
}
pthread_exit(NULL);
return NULL;
}
void logOut(int sockfd)
{
char mes[1024];
memset(mes, 0, sizeof(mes));
strncpy(mes, "client %d will close!", sizeof("client %d will close!"));
if(write(sockfd, mes, sizeof(mes)) == -1)
printf("close client %d succeed!\n", sockfd);
else
printf("close client %d failed!\n", sockfd);
}
int main(int argc, char *argv[])
{
char buffer[1024];
struct sockaddr_in server_addr;
struct hostent *host;
int portnumber,nbytes;
char strhost[16];
char mes[1024];
int thr_id; /* thread ID for the newly createdthread */
pthread_t p_thread; /* thread's structure */
if(argc!=1)
{
fprintf(stderr,"Usage:%s\a\n",argv[0]);
exit(1);
}
printf("Please input the ip address : ");
scanf("%s",strhost);
if((host = gethostbyname(strhost)) == NULL)
{
fprintf(stderr,"Gethostnameerror\n");
exit(1);
}
/* 客户程序开始建立 sockfd 描述符 */
printf("Connection ... ...\n");
if((sockfd = socket(AF_INET,SOCK_STREAM,0)) == -1)
{
fprintf(stderr,"SocketError:%s\a\n",strerror(errno));
exit(1);
}
/* 客户程序填充服务端的资料 */
bzero(&server_addr,sizeof(server_addr));
server_addr.sin_family=AF_INET;
server_addr.sin_port=htons(PORT);
server_addr.sin_addr=*((struct in_addr *)host->h_addr);
printf("Create Connection succeed ... ...\n");
/* 客户程序发起连接请求 */
if(connect(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1)
{
fprintf(stderr,"ConnectError:%s\a\n",strerror(errno));
exit(1);
}
/* 连接成功了 */
printf("connected the server succed, ... ...\n");
thr_id = pthread_create(&p_thread, NULL, recvfromserver, NULL);
closeClient();
printf("\nPress Quit or q or Q disconnect server!\n");
while(1)
{
memset(buffer, 0, sizeof(buffer));
memset(mes, 0, sizeof(mes));
gets(buffer);
strcat(mes, ":");
strcat(mes, buffer);
printf("mes: [ %s ]\n", mes);
if((write(sockfd,mes,sizeof(mes)))== -1)
{
fprintf(stderr,"WriteError:%s\n",strerror(errno));
exit(1);
}
if(strcmp(buffer,"Quit")==0 || strcmp(buffer,"q")==0 || strcmp(buffer,"Q")==0)
{
logOut(sockfd);
break;
}
}
close(sockfd);
exit(0);
}