代码是别人的,作为例子跑跑。主要是做个修改标记,致谢前辈。
代码如下:
/*tcp_server.c*/
#include <sys/wait.h>//防退出添加
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <pthread.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <arpa/inet.h>
#define portnumber 8500
#define buffer_size 10
/* -------mutex valibale ---------*/
pthread_mutex_t mutex_r,mutex_w;
char read_flag,write_flag;
void read_pthread(void);
void write_pthread(void);
/*-------Glocal read/write data ----------------*/
char read_buffer[buffer_size];
char write_buffer[buffer_size];
/*-------Glocal conncetion ID-------------*/
int new_fd;
int sockfd;
int num ;
int main(int argc, char *argv[])
{
/*
int sockfd;
int new_fd;
*/
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
struct sigaction sa;//防退出添加
int sin_size;
int nbytes;
/*----------------define local variables,related to thread-----------------*/
int ret;
pthread_t id1,id2;
//initialize the mutex
pthread_mutex_init(&mutex_r,NULL);
pthread_mutex_init(&mutex_w,NULL);
/* ---------------------related to network ---------------------------------*/
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1) // AF_INET:IPV4;SOCK_STREAM:TCP
{
fprintf(stderr,"Socket error:%s\n\a",strerror(errno));
exit(1);
}
bzero(&server_addr,sizeof(struct sockaddr_in));
server_addr.sin_family=AF_INET; // Internet
server_addr.sin_addr.s_addr=htonl(INADDR_ANY);
server_addr.sin_port=htons(portnumber);
if(bind(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1)
{
fprintf(stderr,"Bind error:%s\n\a",strerror(errno));
exit(1);
}
if(listen(sockfd,5)==-1)
{
fprintf(stderr,"Listen error:%s\n\a",strerror(errno));
exit(1);
}
printf("start listen...\n");
sa.sa_handler = SIG_IGN;//防退出添加
sigaction( SIGPIPE, &sa, 0 );//防退出添加
while(1)
{
sin_size=sizeof(struct sockaddr_in);// This is must be in while()?
printf("waiting for connection ----\n");
if((new_fd=accept(sockfd,(struct sockaddr *)(&client_addr),&sin_size))==-1)
{
fprintf(stderr,"Accept error:%s\n\a",strerror(errno));
exit(1);
}
fprintf(stderr,"Server get connection from %s\n",inet_ntoa(client_addr.sin_addr));
/*------ create the read thread -------- */
ret = pthread_create(&id1, NULL, (void*)read_pthread, NULL);
if (ret)
{
printf("Create pthread error!\n");
return 1;
}
printf("start the read_pthread successed \n");
/*--------create the wirte thread----------------*/
//启动写线程便会终止整个程序,不知为何??
ret = pthread_create(&id2, NULL, (void*)write_pthread, NULL);
if (ret)
{
printf("Create pthread error!\n");
return 1;
}
printf("start the write_pthread successed\n");
printf("start to read/write data \n");
/* -----------read and write data ------------------*/
while(1)
{
//How long time to check ?
if(pthread_kill(id1,0)!=0)
{
printf("read_pthread is stoped ,\n");
break;
}
if(!pthread_mutex_lock(&mutex_r))
{
if(read_flag)
{
//实际操作中,把read_buffer中数据传给main 循环中的变量
printf("Server received--%i ----%s \n",num,read_buffer);
}
pthread_mutex_unlock(&mutex_r);
}
usleep(20000);
//close(new_fd);
}
}
close(sockfd); //How to jump here ?
printf("Close socket !\n");
exit(0);
}
void write_pthread(void)
{
/*
int state;
state=PTHREAD_CANCEL_DEFERRED;
pthread_setcancelstate(state,&oldstate);
*/
static int nbytes;
static char buffer[buffer_size];
while(1) //
{
/*这里进行互斥标志位的判断,把数据传递到buffer */
/*
pthread_mutex_lock(&mutex_w);
write_flag=0;
pthread_mutex_unlock(&mutex_w);
*/
/*transfer datas */
/*memcpy(read_buffer,buffer,nbytes);*/
strcpy(buffer,"tcp_send ok");
/*
pthread_mutex_lock(&mutex_w);
write_flag=1;
pthread_mutex_unlock(&mutex_w);
*/
/*string -> char **/
nbytes=write(new_fd,buffer,buffer_size);
if(nbytes<0)
{
fprintf(stderr,"write error:%s\n\a",strerror(errno));
}
usleep(20000);
}
}
//方法要对变量加上互斥锁
void read_pthread(void)
{
static int nbytes;
static char buffer[buffer_size];
while(1)
{
nbytes=read(new_fd,buffer,buffer_size);
num++;
if((nbytes==0)||(nbytes==-1))
{
if(nbytes==0)
{ //the connection had be closed .
printf("The connection is error !\n");
break;
}
else
fprintf(stderr,"Read Error:%s\n",strerror(errno));
close(new_fd);
exit(1);
}
//这里的加锁是可预见的
/*-------mutex lock----------*/
pthread_mutex_lock(&mutex_r);
read_flag=0;
pthread_mutex_unlock(&mutex_r);
memcpy(read_buffer,buffer,nbytes);
pthread_mutex_lock(&mutex_r);
read_flag=1;
pthread_mutex_unlock(&mutex_r);
}
printf("read_pthread is quit\n");
}
在断开client连接时候,服务器端进程退出的解决办法
文件中添加:
#include <sys/wait.h>
struct sigaction sa;
sa.sa_handler = SIG_IGN;
sigaction( SIGPIPE, &sa, 0 );