下面是server代码:
服务器主要负责等待客服端连接,处理数据,转发!随便瞎写的,主要是为了学习epoll多路复用,有逻辑错误的地方。
#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include <netinet/in.h>
#include <errno.h>
#include <sys/epoll.h>
#include <semaphore.h>
#define OPEN_MAX 20
typedef struct {
int client_fd;
char client_name[128];
struct sockaddr_in client_addr;
}client;
static client *clients = NULL;
static sem_t send_sem;
char from[32] = {0};
char to[32] = {0};
char msg[128] = {0};
char recv_buf[1024] = {0};
struct epoll_event event;
struct epoll_event wait_event;
int server_fd = -1,target_fd = -1,epfd = -1;
static int retVal = -1;
static int sin_size = 0;
struct sockaddr_in server_addr;
struct sockaddr_in new_client_addr;
pthread_t send_thread_id;
pthread_t recv_thread_id;
/*
*
*
* test
*
*
* */
static void showAllClients(void)
{
int i;
for(i = 0; i < OPEN_MAX; i++){
if(clients[i].client_fd == 0){
continue;
}else{
printf("showAllClients clients[%d]:client_fd = %d :name = %s\n",i,clients[i].client_fd,clients[i].client_name);
}
}
}
static int getClientsIndex(int byfd, char * byname)
{
int i;
if( byfd > 0 ){
for(i = 0; i < OPEN_MAX;i++){
if(clients[i].client_fd == byfd){
return i;
}else{
continue;
}
}
}
else if ( byname != NULL){
for(i = 0; i < OPEN_MAX;i++){
if(strstr(clients[i].client_name,byname)){
return i;
}else{
continue;
}
}
}
else {
printf("getClientsIndex error\n");
return -1;
}
}
void send_thread(void)
{
int i = 0;
while(1){
sem_wait(&send_sem);
int index = getClientsIndex(0,to);
if(index < 0){
continue;
}
printf("index =%d,target_fd =%d\n",index,clients[index].client_fd);
retVal = write(clients[index].client_fd,msg,strlen(msg));
printf("send %d bytes success \n",retVal);
memset(msg,0,128);
memset(to,0,32);
memset(from,0,32);
}
}
/*
MSG:from:xxx,to:xxx,msg:
*/
static int analysisMessage(int fd)
{
char *p_str,*p_end;
if(recv_buf[0] == 0){
printf("recv_buf is invalid\n");
return -1;
}
printf("recv data:%s\n",recv_buf);
p_str = strstr((recv_buf),"register:");
if(p_str){
p_str = p_str+9;
int index = getClientsIndex(fd,NULL);
printf("getClientsIndex index = %d\n",index);
if(index >= 0){
strcpy(clients[index].client_name,p_str);
memset(recv_buf,0,sizeof(recv_buf));
return 0;
}
return -1;
}
p_str = strstr((recv_buf),"from:");
if(p_str){
p_str = p_str+5;
p_end = strstr(p_str,"to:") - 1;
strncpy(from,p_str,p_end-p_str);
printf("from:%s\n",from);
}else {
printf("analysisMessage form error p_str is null\n");
return -1;
}
p_str = strstr((recv_buf),"to:");
if(p_str){
p_str = p_str+3;
p_end = strstr(p_str,"msg:") - 1;
strncpy(to,p_str,p_end-p_str);
printf("to:%s\n",to);
}else {
printf("analysisMessage to error p_str is null\n");
return -1;
}
p_str = strstr((recv_buf),"msg:");
if(p_str){
p_str = p_str+4;
strcpy(msg,p_str);
printf("msg:%s\n",msg);
}else {
printf("analysisMessage msg error p_str is null\n");
return -1;
}
sem_post(&send_sem);
}
int main()
{
int i = 0,connectCount = 0,j = 0;
if(sem_init (&send_sem , 0, 0) < 0){
perror("sem_init:");
return -1;
}
clients = malloc(sizeof(clients)*OPEN_MAX);
if(clients == NULL){
printf("malloc clients fail\n");
return -1;
}
printf("malloc clients success\n");
memset(clients,0, sizeof(clients)*OPEN_MAX);
memset(&event,0,(sizeof(event)));
server_fd = socket(AF_INET, SOCK_STREAM,0);
if(server_fd < 0){
printf("creat socket fail,error:%s\n",strerror(server_fd));
return -1;
}
printf("creat socket success server_fd = %d !\n",server_fd);
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr("198.18.108.235");/*htonl(INADDR_ANY);*/
server_addr.sin_port = htons(6000);
retVal = bind(server_fd,(struct sockaddr *)&server_addr, sizeof(server_addr));
if(retVal < 0){
printf("server bind fail,error:%s,retVal = %d\n",strerror(retVal),retVal);
return -1;
}
printf("server bind success ! server ip:%s,port:6000\n",inet_ntoa(server_addr.sin_addr));
retVal = listen(server_fd,5);
if(retVal < 0){
printf("server listen fail,error:%s\n",strerror(retVal));
return -1;
}
printf("server listen success !\n");
epfd = epoll_create(10);
if( -1 == epfd ){
perror ("epoll_create");
return -1;
}
printf("epoll_create success epfd = %d!\n",epfd);
event.data.fd = server_fd;
event.events = EPOLLIN;
retVal = epoll_ctl(epfd, EPOLL_CTL_ADD, server_fd, &event);
if(-1 == retVal){
perror("epoll_ctl add fail");
return -1;
}
retVal = pthread_create(&send_thread_id,NULL,(void *) send_thread,NULL);
if(retVal < 0){
printf("create send thread fail \n");
return -1;
}
while(1){
retVal = epoll_wait(epfd, &wait_event, connectCount+1, -1);
if((server_fd == wait_event.data.fd) &&
(EPOLLIN == wait_event.events & EPOLLIN)){
showAllClients();
int new_client_fd = accept(server_fd,(struct sockaddr *)&new_client_addr,&sin_size);
if(new_client_fd < 0){
printf("server accept fail,error:%s\n",strerror(clients[i].client_fd));
return -1;
}
if(connectCount >= OPEN_MAX){
close(new_client_fd);
printf("server refuse new connect\n");
continue;
}
printf("a new accept success ,client fd = %d\n",new_client_fd);
for(i = 0;i < OPEN_MAX;i++){
if(clients[i].client_fd == 0){
clients[i].client_fd = new_client_fd;
clients[i].client_addr = new_client_addr;
event.data.fd = new_client_fd;
event.events = EPOLLIN;
printf("+++sjh+++ clients[%d].client_fd = %d\n",i,clients[i].client_fd);
retVal = epoll_ctl(epfd, EPOLL_CTL_ADD, new_client_fd, &event);
if(-1 == retVal){
perror("epoll_ctl add fail");
return -1;
}
connectCount++;
break;
}else {
continue;
}
}
} else {
for(j = 0;j < OPEN_MAX;j++){
if((clients[j].client_fd == wait_event.data.fd)
&& (EPOLLIN == wait_event.events & EPOLLIN)){
retVal = recv(clients[j].client_fd, recv_buf, sizeof(recv_buf), 0);
if(retVal < 0){
if(errno == ECONNRESET)
{
connectCount--;
close(clients[j].client_fd);
memset(&clients[j],0,sizeof(clients));
}
else
perror("read error:");
} else if(retVal == 0){
printf("client [fd:%d,name:%s] has been closed\n",clients[j].client_fd,clients[j].client_name);
connectCount--;
close(clients[j].client_fd);
memset(&clients[j],0,sizeof(clients));
} else {
analysisMessage(clients[j].client_fd);
}
}
}
}
}
/*
retVal = pthread_create(&recv_thread_id,NULL,(void *) recv_thread,NULL);
if(retVal < 0){
printf("create recv thread fail \n");
return -1;
}*/
// pthread_join(recv_thread_id, NULL);
pthread_join(send_thread_id, NULL);
return 0;
}
下面是客户端程序:
/*************************************
name: client.c
linux sockek
*/
#include <stdlib.h>
#include <sys/types.h>
#include <stdio.h>
#include <sys/socket.h>
#include <linux/in.h>
#include <string.h>
//#include <netinet/in.h>
int client_fd;
int retVal,recBytes;
int sin_size;
struct sockaddr_in s_add,c_add;
unsigned short portnum=6000;
char client_name[128] = {0};
pthread_t send_thread_id;
pthread_t recv_thread_id;
//from:xxx,to:xxx,msg:
void send_thread(void)
{
char msg[128] = {0};
char send_buf[128] = {0};
while(1){
printf("send data:\n");
fgets(msg,128,stdin);
sprintf(send_buf,"from:%s,%s",client_name,msg);
if(client_fd != -1){
retVal = write(client_fd,send_buf,strlen(send_buf));
printf("send %d bytes success \n",retVal);
}else {
printf("client exit !\n");
break;
}
memset(send_buf,0,128);
memset(msg,0,128);
}
}
void recv_thread(void)
{
char recv_buf[128] = {0};
while(1){
retVal = read(client_fd,recv_buf,sizeof(recv_buf));
if(retVal == 0){
close(client_fd);
client_fd = -1;
printf("server has been closed\n press down any key to exit!\n");
break;
}
printf("recv data :%s\n",recv_buf);
memset(recv_buf,0,128);
}
}
int main(int argc,char** argv)
{
char register_cmd[128] = {0};
if(argc < 2){
printf("please input parameter !\n");
return -1;
}else {
strcpy(client_name,argv[1]);
strcpy(register_cmd,"register:");
strcat(register_cmd,argv[1]);
}
printf("Hello,welcome to client !\r\n");
client_fd = socket(AF_INET, SOCK_STREAM, 0);
if(-1 == client_fd) {
printf("socket fail ! \r\n");
return -1;
}
printf("socket ok !\r\n");
bzero(&s_add,sizeof(struct sockaddr_in));
s_add.sin_family=AF_INET;
s_add.sin_addr.s_addr= inet_addr("198.18.108.235");
s_add.sin_port=htons(portnum);
//printf("s_addr = %s ,port : %d\r\n",inet_ntoa(s_add.sin_addr),s_add.sin_port);
if(-1 == connect(client_fd,(struct sockaddr *)(&s_add), sizeof(struct sockaddr))) {
printf("connect fail !\r\n");
close(client_fd);
return -1;
}
write(client_fd,register_cmd,strlen(register_cmd));
printf("connect ok !\r\n");
retVal = pthread_create(&send_thread_id,NULL,(void *) send_thread,NULL);
if(retVal < 0){
printf("create send thread fail \n");
close(client_fd);
return -1;
}
retVal = pthread_create(&recv_thread_id,NULL,(void *) recv_thread,NULL);
if(retVal < 0){
printf("create recv thread fail \n");
close(client_fd);
return -1;
}
pthread_join(send_thread_id, NULL);
pthread_join(recv_thread_id, NULL);
/*
close(client_fd);*/
return 0;
}