QQ登录

只需一步,快速开始

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 1457|回复: 8

网络编程问题:select

[复制链接]
发表于 2006-4-20 08:44:28 | 显示全部楼层 |阅读模式
我写了一个客户端程序,一个并发服务器程序,SOCKET描述符都设置成非阻塞方式,服务器程序开多个线程接收多个客户端程序的连接请求,用select处理服务器程序的输入,向客户端程序发消息和接收客户端程序发来的消息;而客户端程序也用select来处理服务器程序发来的消息和向服务器程序发消息.
问题是:客户端程序与服务器程序连接后,如果我非法关闭服务器程序,比如按Ctrl+C结束服务器程序,则客户端程序出现异常,不断的刷屏,请问这个情况该怎么解决呢?是否要我发两个程序的简单代码过来给大家看?
发表于 2006-4-20 20:08:29 | 显示全部楼层
看你的程序
回复

使用道具 举报

 楼主| 发表于 2006-4-21 08:31:49 | 显示全部楼层
client.c:
[code:1]
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <stdio.h>
#include <netdb.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <arpa/inet.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>

#define SERVER_PORT 9527
#define MAXDATASIZE 4096
#define STDIN 0

char *HOST_NAME = "INADDR_ANY";

int main(int argc, char *argv[])
{
        int client_sockfd;
        struct sockaddr_in server_address;
        fd_set rfd_set, wfd_set, efd_set;

        struct timeval time_out;

        int numb_recv=0;
        char recv_buf[MAXDATASIZE];
        char send_buf[MAXDATASIZE];
        int ret;
        int send_len=0;
        char user_name[9] = "roc      ";
        char msg_client[9] = "roc      ";
        msg_client[7] = ':';
        msg_client[9] = '\0';
        int i=0;

        if((client_sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
        {
                perror("create server_sockfd error!");
                return -1;
        }

        bzero(&server_address, sizeof(server_address));
        server_address.sin_family = AF_INET;
        server_address.sin_port = htons(SERVER_PORT);
//        inet_aton("10.5.12.101",&server_address.sin_addr);
        server_address.sin_addr.s_addr = INADDR_ANY;//&HOST_NAME;/*server's address set local address*/

        if((connect(client_sockfd, (struct sockaddr *)&server_address, sizeof(struct sockaddr))) == -1)
        {
                perror("connect error!");
                return -1;
        }

        fcntl(client_sockfd, F_SETFD, O_NONBLOCK);
        fflush(stdout);

        while(1)
        {

                FD_ZERO(&rfd_set);
                FD_ZERO(&wfd_set);
                FD_ZERO(&efd_set);
                FD_SET(STDIN, &rfd_set);
                FD_SET(client_sockfd, &rfd_set);
                FD_SET(client_sockfd, &wfd_set);
                FD_SET(client_sockfd, &efd_set);

                for(i=0; i<10; i++)
                {
                        msg_client[i] = user_name[i];
                }
                msg_client[7] = ':';

                time_out.tv_sec = 2;
                time_out.tv_usec = 0;

                ret = select(client_sockfd+1, &rfd_set, &wfd_set, &efd_set, &time_out);

/*                if(ret == 0)
                {
                        continue;
                }*/
                if(ret < 0)
                {
                        perror("select error!");
                        return -1;
                }

                if(FD_ISSET(STDIN, &rfd_set))
                {
                        fgets(send_buf, MAXDATASIZE, stdin);
                        send_buf[strlen(send_buf)-1] = '\0';
                        if(strncmp("quit", send_buf, 4) == 0)
                        {
                                if(send(client_sockfd, "user logout", 11, 0) == -1)
                                {
                                        perror("send error!");
                                        return -1;
                                }
                                usleep(50000);
                                break;
                        }

                        strcat(msg_client, send_buf);
                        if((send_len = strlen(msg_client) + strlen(send_buf)) >= MAXDATASIZE)
                        {
                                send_len = MAXDATASIZE;
                        }

                        if(send(client_sockfd, msg_client, send_len, 0) == -1)
                        {
                                perror("send error!");
                                return -1;
                        }
                        bzero(msg_client,sizeof(msg_client));
                        bzero(send_buf,sizeof(send_buf));
                }

                if(FD_ISSET(client_sockfd, &rfd_set))
                {
                        if((numb_recv = recv(client_sockfd, recv_buf, MAXDATASIZE, 0)) == -1)
                        {
                                perror("recv error!");
                                return -1;
                        }
                        recv_buf[numb_recv] = '\0';

                        if(strncmp("server quit", recv_buf, 11) == 0)
                        {
                                usleep(50000);
                                break;
                        }

                        printf("%s\n", recv_buf);
                        bzero(recv_buf, sizeof(recv_buf));
                }

                if(FD_ISSET(client_sockfd, &efd_set))
                {
                        close(client_sockfd);
                        break;
                }
        }

        close(client_sockfd);

        return 0;
}
[/code:1]
回复

使用道具 举报

 楼主| 发表于 2006-4-21 08:32:52 | 显示全部楼层
server_msg.c:

[code:1]
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <pthread.h> /*aid -lpthread while compling*/
#include <errno.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <stdio.h>
#include <netdb.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>

#define SERVER_PORT 9527
#define MAXDATASIZE 4096
#define BACKLOG 10
#define STDIN 0
//Message constant
char *SERVER_CLIENT_FIRST = "Login motley_talk server OK! Welcome!";
char *SERVER_QUIT_MSG = "server quit";
//pthread_mutex variable
pthread_mutex_t file_mutex;// = PTHREAD_ERRORCHECK_MUTEX_INITIALZER_NP;
int offset_write = 0;
int last_offset_r = 0;//file read offset
int msg_id_count = 4;
char *message_file;

static void *client_pthread(void *);/*client_pthread for each user*/
int msg_file_rw(char rw, int last_msg_id, char *message_msg);
int test_file();

int main(int argc, char *argv[])
{
        int server_sockfd, *client_temp;
        struct sockaddr_in server_address;
        struct sockaddr_in client_address;

        int size_of_addr;

        pthread_t db_pthread_id;
        pthread_t client_pthread_id;
        pthread_mutexattr_t attr;
        pthread_mutexattr_init(&attr);
        pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_TIMED_NP);
        pthread_mutex_init(&file_mutex, &attr);//PTHREAD_MUTEX_ERRORCHECK_NP);

        system("rm -f msg_db");

        if((server_sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
        {
                perror("create server_sockfd error!");
                exit(-1);
        }

        bzero(&server_address, sizeof(server_address));
        server_address.sin_family = AF_INET;
        server_address.sin_port = htons(SERVER_PORT);
        server_address.sin_addr.s_addr = INADDR_ANY;/*server's address is local address*/

        if(bind(server_sockfd, (struct sockaddr *)&server_address,sizeof(struct sockaddr)) == -1)
        {
                perror("bind error!");
                exit(-1);
        }

        if(listen(server_sockfd, BACKLOG) == -1)
        {
                perror("listen error!");
                exit(-1);
        }

        int t;
        for(t=0; t<5; t++)
        {
                size_of_addr = sizeof(client_address);
                client_temp = malloc(sizeof(int));
                *client_temp = accept(server_sockfd, (struct sockaddr *)&client_address, &size_of_addr);

                pthread_create(&client_pthread_id, NULL, &client_pthread, client_temp);
        }

        pthread_mutex_destroy(&file_mutex);
        close(server_sockfd);
        exit(0);
}

/*
* Description: client pthread
* Input: client's sockfd from Main
* Output: Message
* Returns: 0 for correct, -1 for error
*/
static void *client_pthread(void *client_temp)
{
        int client_sockfd;
        int ret;
        fd_set rfd_set, wfd_set, efd_set;

        client_sockfd = *((int *)client_temp);
        free(client_temp);

        struct timeval time_out;

        int send_len=0;
        int numb_recv;
        char recv_buf[MAXDATASIZE];
        char send_buf[MAXDATASIZE];
        char server_name[9] = "server   ";
        char msg_server[9] = "server   ";
        msg_server[7] = ':';
        msg_server[9] = '\0';
        int i;

        if(send(client_sockfd, SERVER_CLIENT_FIRST, strlen(SERVER_CLIENT_FIRST), 0) == -1)
        {
                perror("send error!");
                exit(-1);
        }

        fcntl(client_sockfd, F_SETFD, O_NONBLOCK);

        while(1)
        {
                FD_ZERO(&rfd_set);
                FD_ZERO(&wfd_set);
                FD_ZERO(&efd_set);
                FD_SET(STDIN, &rfd_set);
                FD_SET(client_sockfd, &rfd_set);
                FD_SET(client_sockfd, &wfd_set);
                FD_SET(client_sockfd, &efd_set);

                for(i=0; i<10; i++)
                {
                        msg_server[i] = server_name[i];
                }
                msg_server[7] = ':';

                time_out.tv_sec = 2;
                time_out.tv_usec = 0;

                ret = select(client_sockfd+1, &rfd_set, &wfd_set, &efd_set, &time_out);

                if(ret < 0)
                {
                        perror("select error!");
                        exit(-1);
                }

                if(FD_ISSET(STDIN, &rfd_set))
                {
                        fgets(send_buf, MAXDATASIZE, stdin);
                        send_buf[strlen(send_buf)-1] = '\0';
                        if(strncmp("quit", send_buf, 4) == 0)
                        {
                                if(send(client_sockfd, SERVER_QUIT_MSG, 11, 0) == -1)
                                {
                                        perror("send error!");
                                        exit(-1);
                                }

                                pthread_mutex_lock(&file_mutex);
                                msg_id_count = msg_id_count + 1;
                                offset_write = offset_write + 11;
                                msg_file_rw('w', msg_id_count, SERVER_QUIT_MSG);
                                pthread_mutex_unlock(&file_mutex);

                                usleep(50000);
                                break;
                        }

                        for(i=0; i<10; i++)
                        {
                                msg_server[i] = server_name[i];
                        }
                        msg_server[7] = ':';

                        strcat(msg_server, send_buf);

                        if((send_len = strlen(msg_server) + strlen(send_buf)) >= MAXDATASIZE)
                        {
                                send_len = MAXDATASIZE;
                        }

                        if(send(client_sockfd, msg_server, send_len, 0) == -1)
                        {
                                perror("send error!");
                                exit(-1);
                        }

                        pthread_mutex_lock(&file_mutex);
                        msg_id_count = msg_id_count + 1;
                        offset_write = offset_write + send_len;
                        msg_file_rw('w', msg_id_count, msg_server);
                        pthread_mutex_unlock(&file_mutex);

                        bzero(msg_server,sizeof(msg_server));
                        bzero(send_buf, sizeof(send_buf));
                }

                if(FD_ISSET(client_sockfd, &rfd_set))
                {
                        if((numb_recv = recv(client_sockfd, recv_buf, MAXDATASIZE, 0)) == -1)
                        {
                                perror("recv error!");
                                exit(-1);
                        }
                        recv_buf[numb_recv] = '\0';

                        pthread_mutex_lock(&file_mutex);
                        msg_id_count =msg_id_count + 1;
                        offset_write = offset_write + numb_recv;
                        msg_file_rw('w', msg_id_count, recv_buf);
                        pthread_mutex_unlock(&file_mutex);

                        if(strncmp("user logout", recv_buf, 11) == 0)
                        {
                                usleep(50000);
                                break;
                        }

                        printf("%s\n", recv_buf);

                        bzero(recv_buf, sizeof(recv_buf));
                }

                if(FD_ISSET(client_sockfd, &efd_set))
                {
                        close(client_sockfd);
                        exit(-1);
                }
        }

        close(client_sockfd);
        return 0;
}

/*
* Description: use the last message_id and message_msg, write them into the msg_file
* Input: last message_id and the message
* Output: NULL
* Returns: -1 for error, 0 for read one message, 1 for file end
* Attention:
*/
int msg_file_rw(char rw, int last_msg_id, char *message_msg)
{
        FILE *msg_file_fp;
        int bytes_read;
        size_t nbytes =0;
        char *strings_line = NULL;

        if(rw == 'w')
        {

                msg_file_fp = fopen("msg_db","ab");
                if(msg_file_fp == NULL)
                {
                        printf("fail to open msg_file while writing!\n");
                        return -1;
                }
                fprintf(msg_file_fp, "INSERT INTO motley_talk_table VALUES (%d, \"%s\")\n", last_msg_id, message_msg);
                fflush(msg_file_fp);
                fclose(msg_file_fp);
                return 0;
        }
        else
        {
                msg_file_fp = fopen("msg_db","r");
                if(msg_file_fp == NULL)
                {
                        printf("fail to open msg_file while reading!\n");
                        return -1;
                }

                fseek(msg_file_fp, last_offset_r, SEEK_SET);

                if((bytes_read = getline(&strings_line, &nbytes, msg_file_fp)) != -1)
                {
                        if(strings_line[strlen(strings_line) -1] == '\n')
                        {
                                strings_line[strlen(strings_line)-1] = '\0';
                        }
                        message_file = strings_line;
                        last_offset_r = last_offset_r + strlen(strings_line) + 1;
                        fclose(msg_file_fp);
                        return 0;//file not end
                }
                else
                {
                        fclose(msg_file_fp);
                        return 1;//file end
                }
        }
}
[/code:1]
回复

使用道具 举报

 楼主| 发表于 2006-4-21 08:40:56 | 显示全部楼层
初学,写的不规范,麻烦你了

谢谢!
回复

使用道具 举报

发表于 2006-4-21 10:49:05 | 显示全部楼层
http://www.linuxfans.org/nuke/modules.php?name=Forums&file=viewtopic&t=143469
回复

使用道具 举报

发表于 2006-4-21 11:25:12 | 显示全部楼层
看了上火呀,没看懂呀。
版主别生气了,先给给说说吧。

我替他改中不?
[code:1]
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <pthread.h> /*aid -lpthread while compling*/
//#include <mysql/mysql.h> /*aid -lmysqlclient while compling*/
#include <errno.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <stdio.h>
#include <netdb.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>

//#include "motley_talk.h"

#define SERVER_PORT 9527
#define MAXDATASIZE 4096
#define BACKLOG 10
#define STDIN 0
//Message constant
char *SERVER_CLIENT_FIRST = "Login motley_talk server OK! Welcome!";
char *SERVER_QUIT_MSG = "server quit";
//pthread_mutex variable
pthread_mutex_t file_mutex;// = PTHREAD_ERRORCHECK_MUTEX_INITIALZER_NP;
//pthread_mutex_t db_mutex;
//database variable
/*char *host = "localhost";
char *username = "root";
char *password = "root";
char *database = "motley_talk_db";*/
//file variable
int offset_write = 0;
int last_offset_r = 0;//file read offset
int msg_id_count = 3;
//variable values for insert database
//int last_id_file;
char *message_file;

//functions,running in pthread
static void *client_pthread(void *);/*client_pthread for each user*/
//static void *msg_file_read(void *temp);/*read file for database*/
//file read and write functions,running in pthread functions
int msg_file_rw(char rw, int last_msg_id, char *message_msg);
//static void *db_pthread(void *temp);/*insert database message for all users*/

int main(int argc, char *argv[])
{
int server_sockfd, *client_temp;
struct sockaddr_in server_address;
struct sockaddr_in client_address;

int size_of_addr;

pthread_t db_pthread_id;
pthread_t client_pthread_id;
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_TIMED_NP);
pthread_mutex_init(&file_mutex, &attr);//PTHREAD_MUTEX_ERRORCHECK_NP);

system("rm -f msg_file");
// system("vi msg_file");

if((server_sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
  perror("create server_sockfd error!");
  exit(-1);
}

bzero(&server_address, sizeof(server_address));
server_address.sin_family = AF_INET;
server_address.sin_port = htons(SERVER_PORT);
server_address.sin_addr.s_addr = INADDR_ANY;/*server's address is local address*/

if(bind(server_sockfd, (struct sockaddr *)&server_address,sizeof(struct sockaddr)) == -1)
{
  perror("bind error!");
  exit(-1);
}

if(listen(server_sockfd, BACKLOG) == -1)
{
  perror("listen error!");  
  exit(-1);
}

// pthread_create(&db_pthread_id, NULL, &db_pthread, NULL);

int t;
for(t=0; t<5; t++)
{
  size_of_addr = sizeof(client_address);
  client_temp = malloc(sizeof(int));
  *client_temp = accept(server_sockfd, (struct sockaddr *)&client_address, &size_of_addr);

  pthread_create(&client_pthread_id, NULL, &client_pthread, client_temp);
}

pthread_mutex_destroy(&file_mutex);
close(server_sockfd);
exit(0);
}

/*
* Description: client's pthread
* Input: client's sockfd from Main
* Output: Message
* Returns: 0 for correct, -1 for error
*/
static void *client_pthread(void *client_temp)
{
int client_sockfd;
int ret;
fd_set rfd_set, wfd_set, efd_set;

client_sockfd = *((int *)client_temp);
free(client_temp);

struct timeval time_out;

int send_len=0;
int numb_recv;
char recv_buf[MAXDATASIZE];
char send_buf[MAXDATASIZE];
char server_name[9] = "server ";
char msg_server[9] = "server ";
msg_server[7] = ':';
msg_server[9] = '\0';
int i;

if(send(client_sockfd, SERVER_CLIENT_FIRST, strlen(SERVER_CLIENT_FIRST), 0) == -1)
{
  perror("send error!");
  exit(-1);
}

fcntl(client_sockfd, F_SETFD, O_NONBLOCK);

while(1)
{
  FD_ZERO(&rfd_set);  
  FD_ZERO(&wfd_set);
  FD_ZERO(&efd_set);
  FD_SET(STDIN, &rfd_set);
  FD_SET(client_sockfd, &rfd_set);
  FD_SET(client_sockfd, &wfd_set);
  FD_SET(client_sockfd, &efd_set);

for(i=0; i<10; i++)
{
  msg_server[i] = server_name[i];
}
msg_server[7] = ':';

time_out.tv_sec = 2;
time_out.tv_usec = 0;

ret = select(client_sockfd+1, &rfd_set, &wfd_set, &efd_set, &time_out);

if(ret < 0)
{
  perror("select error!");
  exit(-1);
}

/**/ if(FD_ISSET(STDIN, &rfd_set))
{
  fgets(send_buf, MAXDATASIZE, stdin);
  send_buf[strlen(send_buf)-1] = '\0';
  if(strncmp("quit", send_buf, 4) == 0)
  {
     if(send(client_sockfd, SERVER_QUIT_MSG, 11, 0) == -1)
     {
        perror("send error!");
        exit(-1);
     }

     pthread_mutex_lock(&file_mutex);
     msg_id_count = msg_id_count + 1;
     offset_write = offset_write + 11;
     msg_file_rw('w', msg_id_count, SERVER_QUIT_MSG);
     pthread_mutex_unlock(&file_mutex);

     usleep(50000);
     break;
  }

strcat(msg_server, send_buf);

if((send_len = strlen(msg_server) + strlen(send_buf)) >= MAXDATASIZE)
{
  send_len = MAXDATASIZE;
}

if(send(client_sockfd, msg_server, send_len, 0) == -1)
{
  perror("send error!");
  exit(-1);
}

pthread_mutex_lock(&file_mutex);
msg_id_count = msg_id_count + 1;
offset_write = offset_write + send_len;
msg_file_rw('w', msg_id_count, msg_server);
pthread_mutex_unlock(&file_mutex);

bzero(msg_server,sizeof(msg_server));
bzero(send_buf, sizeof(send_buf));
/**/ }

if(FD_ISSET(client_sockfd, &rfd_set))
{
  if((numb_recv = recv(client_sockfd, recv_buf, MAXDATASIZE, 0)) == -1)
  {
     perror("recv error!");
     exit(-1);
  }
  recv_buf[numb_recv] = '\0';

pthread_mutex_lock(&file_mutex);
msg_id_count =msg_id_count + 1;
offset_write = offset_write + numb_recv;
msg_file_rw('w', msg_id_count, recv_buf);
pthread_mutex_unlock(&file_mutex);

if(strncmp("user logout", recv_buf, 11) == 0)
{
usleep(50000);
break;
}

printf("%s\n", recv_buf);

bzero(recv_buf, sizeof(recv_buf));
// fflush(stdout);
}

if(FD_ISSET(client_sockfd, &efd_set))
{
close(client_sockfd);
exit(-1);
}
}

close(client_sockfd);
return 0;
}

/*
* Description: use hte last message_id and message_msg, write them into the msg_file
* Input: last message_id and the message
* Output: NULL
* Returns: -1 for error, 0 for read one message, 1 for file end
* Attention:
*/
int msg_file_rw(char rw, int last_msg_id, char *message_msg)
{
FILE *msg_file_fp;
int bytes_read;
size_t nbytes =0;
char *strings_line = NULL;

if(rw == 'w')
{

msg_file_fp = fopen("msg_file","ab");
if(msg_file_fp == NULL)
{
printf("fail to open msg_file while writing!\n");
return -1;
}
// fseek(msg_file_fp, last_offset, SEEK_SET);
fprintf(msg_file_fp, "(%d, \"%s\")\n", last_msg_id, message_msg);
fflush(msg_file_fp);
// fsync(msg_file_fp);
fclose(msg_file_fp);
return 0;
}
else
{
msg_file_fp = fopen("msg_file","r");
if(msg_file_fp == NULL)
{
printf("fail to open msg_file while reading!\n");
return -1;
}

fseek(msg_file_fp, last_offset_r, SEEK_SET);

if((bytes_read = getline(&strings_line, &nbytes, msg_file_fp)) != -1)
{
if(strings_line[strlen(strings_line) -1] == '\n')
{
strings_line[strlen(strings_line)-1] = '\0';
}
message_file = strings_line;
last_offset_r = last_offset_r + strlen(strings_line) + 1;
fclose(msg_file_fp);
return 0;//file not end
}
else
{
fclose(msg_file_fp);
return 1;//file end
}
}
}
[/code:1]
回复

使用道具 举报

 楼主| 发表于 2006-4-21 15:44:30 | 显示全部楼层
对不起,我改一下

这些代码是截下来的,我尽量把无关的部分去掉.

谢谢
回复

使用道具 举报

发表于 2006-4-22 20:15:04 | 显示全部楼层
运行了一下。似乎不是不反应,只是对CTRL+c的反应比较特殊。加个SIGINT的信号处理试试。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

GMT+8, 2024-11-2 18:25 , Processed in 0.040640 second(s), 16 queries .

© 2021 Powered by Discuz! X3.5.

快速回复 返回顶部 返回列表