TCP多客户端服务器程序
我正在制作一个tcp多客户端服务器聊天室。我的TCP多客户端服务器和客户端代码随附。我无法向我的程序中添加其他功能,即客户端删除。显示可以从服务器列表中删除空闲客户端。例如,如果客户机闲置30秒,则服务器应将其删除 请帮帮我。这是服务器程序TCP多客户端服务器程序,c,linux,sockets,tcp,C,Linux,Sockets,Tcp,我正在制作一个tcp多客户端服务器聊天室。我的TCP多客户端服务器和客户端代码随附。我无法向我的程序中添加其他功能,即客户端删除。显示可以从服务器列表中删除空闲客户端。例如,如果客户机闲置30秒,则服务器应将其删除 请帮帮我。这是服务器程序 /* to compile me in Linux, type: gcc -o server t1.c -lpthread */ /* t1.c - code for server program that uses TCP/IP */ /*
/* to compile me in Linux, type: gcc -o server t1.c -lpthread */
/* t1.c - code for server program that uses TCP/IP */
/****SERVER CODE****/
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h> //for sockets
#include <sys/types.h>
#include <string.h> //for string operations
#include <netinet/in.h> //Internet Protocol family sockaddr_in defined here
#include <pthread.h> // for the cosy POSIX threads
#include <arpa/inet.h> // for inet_ntoa() function
#include <unistd.h> //NULL constant defined here
#include <signal.h> //for ctrl+c signal
#define BACKLOG 100 // connections in the queue
#define MAXDATALEN 256 //max size of messages to be sent
#define PORT 2012 //default port number
/*Note: The port argument is optional. If no port is specified,
* the server uses the default given by PORT.*/
struct Node /*structure to handle all clients*/
{
int port;
char username[10];
struct Node *next;
};
typedef struct Node *ptrtonode;
typedef ptrtonode head;
typedef ptrtonode addr;
void sendtoall(char *,int new_fd); /*send chat msgs to all connected clients*/
void Quitall( ); /*send msg to all if server shuts down*/
head MakeEmpty( head h ); /*clearing list*/
void Delete( int port, head h ); /*delete client values on client exit*/
void Insert(int port,char*,head h,addr a);/*inserting new client */
void DeleteList( head h ); /*clearing list*/
void Display( const head h ); /*list all clients connected*/
void *Quitproc( ); /*signal handler*/
void *server(void * arg); /*server instance for every connected client*/
void zzz();
char username[10]; /*size of username*/
int sf2;
head h; /*variable of type struct head*/
char buffer[MAXDATALEN];
/******main starts ***********/
int main(int argc, char *argv[]) {
int sockfd,new_fd; /*variables for socket*/
int portnum; /*variable for port numb if provided*/
struct sockaddr_in server_addr; /*structure to hold server's address */
struct sockaddr_in client_addr; /*structure to hold client's address */
int cli_size,z; /*length of address */
pthread_t thr; /*variable to hold thread ID */
int yes=1;
addr a; /*variable of type struct addr*/
printf("\n\t*-*-*-*SERVER STARTED*-*-*-*\n");
/*=optional or default port argument=*/
if( argc == 2 )
portnum = atoi(argv[1]);
else
portnum = PORT; //if port number not given as argument then using default port
printf("PORT NO.:\t%d\n",portnum);
h = MakeEmpty( NULL ); //frees the list
/*=set info of server =*/
server_addr.sin_family=AF_INET; /* set family to Internet */
server_addr.sin_addr.s_addr = htonl(INADDR_ANY); /* set IP address */
server_addr.sin_port=htons(portnum);
printf("IP ADDRESS:\t%s\n",inet_ntoa(server_addr.sin_addr));
/*=creating socket=*/
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd == -1){
printf("server- socket() error"); // debugging
exit(1);
}else
printf("socket\t\tcreated.\n");
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes,sizeof(int)) == -1) {
printf("setsockopt error"); // debugging
exit(1);
}else printf("reusing\t\tport\n");
/*=binding socket=*/
if(bind(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr))==-1){
printf("binding failed\n"); // debugging
exit(1);}
else
printf("binding\t\tsuccess.\n\n");
printf("\t\tPRESS CTRL+z TO VIEW ONLINE CLIENTS\n\n");
/*=socket on listening mode=*/
listen(sockfd, BACKLOG);
printf("waiting for clients......\n");
if (signal(SIGINT,(void *)Quitproc)==0) //signal handler
if(signal(SIGTSTP, zzz)==0) //signal handler
while(1){
cli_size=sizeof(struct sockaddr_in); //cli_size necessary as an argument for pthread_create
new_fd = accept(sockfd, (struct sockaddr *)&client_addr,&cli_size); //accepting connection from client
a =h ;
/*=sign in with name=*/
bzero(username,10);
if(recv(new_fd,username,sizeof(username),0)>0);
username[strlen(username)-1]=':';
printf("\t%d->%s JOINED chatroom\n",new_fd,username);
sprintf(buffer,"%s IS ONLINE\n",username);
Insert( new_fd,username, h, a ); //inserting newly accepted client socked fd in list
a = a->next;
/*=notify all clients about newly joining clients=*/
a = h ;
do{
a = a->next;
sf2 = a->port;
if(sf2!=new_fd)
send(sf2,buffer ,sizeof(buffer),0);
} while( a->next != NULL );
printf("server got connection from %s & %d\n\n",inet_ntoa(client_addr.sin_addr),new_fd); // debugging
struct Node args; //struct to pass multiple arguments to server function
args.port=new_fd;
strcpy(args.username,username);
pthread_create(&thr,NULL,server,(void*)&args); //creating thread for every client connected
pthread_detach(thr);
} /*while end*/
DeleteList(h); //deleting all clients when server closes
close(sockfd);
}/********main ends***********/
/*******ALL FUNCTIONS DEFINED BELOW*********/
/* ==========Server function for every connected Client =========*/
void *server(void * arguments){
struct Node *args=arguments;
char buffer[MAXDATALEN],ubuf[50],uname[10]; /* buffer for string the server sends */
char *strp;
char *msg = (char *) malloc(MAXDATALEN);
int ts_fd,x,y;
int sfd,msglen;
ts_fd = args->port; /*socket variable passed as arg*/
strcpy(uname,args->username);
addr a;
/*=sending list of clients online=*/
a =h ;
do{
a = a->next;
sprintf( ubuf," %s is online\n",a->username );
send(ts_fd,ubuf,strlen(ubuf),0);
} while( a->next != NULL );
/*=start chatting=*/
while(1){
bzero(buffer,256);
y=recv(ts_fd,buffer,MAXDATALEN,0);
if (y==0)
goto jmp;
/*=if a client quits=*/
if ( strncmp( buffer, "quit", 4) == 0 ){
jmp: printf("%d ->%s left chat deleting from list\n",ts_fd,uname);
sprintf(buffer,"%s has left the chat\n",uname);
addr a = h ;
do{
a = a->next;
sfd = a->port;
if(sfd == ts_fd)
Delete( sfd, h );
if(sfd != ts_fd)
send(sfd,buffer,MAXDATALEN,0);
}while ( a->next != NULL );
Display( h );
close(ts_fd);
free(msg);
break;
}
/*=sending message to all clients =*/
printf("%s %s\n",uname,buffer);
strcpy(msg,uname);
x=strlen(msg);
strp = msg;
strp+= x;
strcat(strp,buffer);
msglen=strlen(msg);
addr a = h ;
do{
a = a->next;
sfd = a->port;
if(sfd != ts_fd)
send(sfd,msg,msglen,0);
} while( a->next != NULL );
Display( h );
bzero(msg,MAXDATALEN);
}//end while
return 0;
}// end server
/*=====empties and deletes the list======*/
head MakeEmpty( head h )
{
if( h != NULL )
DeleteList( h );
h = malloc( sizeof( struct Node ) );
if( h == NULL )
printf( "Out of memory!" );
h->next = NULL;
return h;
}
/*======delete list=======*/
void DeleteList( head h )
{
addr a, Tmp;
a = h->next;
h->next = NULL;
while( a != NULL )
{
Tmp = a->next;
free( a );
a = Tmp;
}
}
/*===============inserting new clients to list==========*/
void Insert( int port,char *username, head h, addr a )
{
addr TmpCell;
TmpCell = malloc( sizeof( struct Node ) );
if( TmpCell == NULL )
printf( "Out of space!!!" );
TmpCell->port = port;
strcpy(TmpCell->username,username);
TmpCell->next = a->next;
a->next = TmpCell;
}
/*========displaying all clients in list==================*/
void Display( const head h )
{
addr a =h ;
if( h->next == NULL )
printf( "NO ONLINE CLIENTS\n" );
else
{
do
{
a = a->next;
printf( "%d->%s \t", a->port,a->username );
} while( a->next != NULL );
printf( "\n" );
}
}
/*===========client deleted from list if client quits================*/
void Delete( int port, head h ){
addr a, TmpCell;
a = h;
while( a->next != NULL && a->next->port != port )
a = a->next;
if( a->next != NULL ){
TmpCell = a->next;
a->next = TmpCell->next;
free( TmpCell );
}
}
/*======handling signals==========*/
void *Quitproc(){
printf("\n\nSERVER SHUTDOWN\n");
Quitall( );
exit(0);
}
/*===============notifying server shutdown===========*/
void Quitall(){
int sfd;
addr a = h ;
int i=0;
if( h->next == NULL ) {
printf( "......BYE.....\nno clients \n\n" );
exit(0);
} else {
do{
i++;
a = a->next;
sfd = a->port;
send(sfd,"server down",13,0);
} while( a->next != NULL );
printf("%d clients closed\n\n",i);
}
}
void zzz(){
printf("\rDISPLAYING ONLINE CLIENTS\n\n");
Display(h);
}
/*=====================================================================================================*/
Here is the client program
/* To compile me in Linux type: gcc -o client t2.c -lpthread*/
/* t2.c - code for client that uses TCP */
/***CLIENT CODE*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h> //for string operations
#include <unistd.h> //NULL constant defined here
#include <sys/types.h>
#include <sys/socket.h> //for sockets
#include <netinet/in.h> //Internet Protocol family sockaddr_in defined here
#include <pthread.h> // for the cosy POSIX threads
#include <signal.h> //for ctrl+c signal
#define MYPORT 2012 /* default port number */
#define MAXDATALEN 256
int sockfd;
int n,x; /*variables for socket*/
struct sockaddr_in serv_addr; /* structure to hold server's address */
char buffer[MAXDATALEN];
char buf[10];
void *quitproc();
void* chat_write(int);
void* chat_read(int);
void *zzz();
/***************main starts************/
int main(int argc, char *argv[]){
pthread_t thr1,thr2; /* variable to hold thread ID */
if( argc != 2 ){
printf("help:u need to put server ip\n");
exit(0);
}
/*=============socket creating==============*/
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1)
printf ("client socket error\n");
else
printf("socket\t\tcreated\n");
/*===============set info===================*/
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(MYPORT);
serv_addr.sin_addr.s_addr = inet_addr(argv[1]);
/*=========for username=====================*/
bzero(buf,10);
printf("\nENTER YOUR NAME::");
fgets(buf,10,stdin);
__fpurge(stdin);
buf[strlen(buf)-1]=':';
/*=============client connect to server============*/
if(connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr))==-1)
{
printf("client connect error\n");
exit(0);
}
else
printf("%s connected to server\n",buf);
printf("\rYOU JOINED AS- %s",buffer-1);
send(sockfd,buf,strlen(buf),0);
pthread_create(&thr2,NULL,(void *)chat_write,(void *)sockfd); //thread creation for writing
pthread_create(&thr1,NULL,(void *)chat_read,(void *)sockfd); //thread creation for reading
pthread_join(thr2,NULL);
pthread_join(thr1,NULL);
return 0;
} /*main ends*/
/*======================================================================*/
/*======reading continously from socket=============*/
void* chat_read(int sockfd)
{
if (signal(SIGINT,(void *)quitproc)==0)
if(signal(SIGTSTP, (void *)zzz)==0)
while(1)
{
n=recv(sockfd,buffer,MAXDATALEN-1,0);
if(n==0){
printf("\nDUE TO SOME UNEXPECTED REASONS SERVER HAS BEEN SHUTDOWN\n\n");
exit(0);
}
if(n>0){
printf("\n%s ",buffer);
bzero(buffer,MAXDATALEN);
}
}//while ends
}
/*======writing continously to socket=============*/
void* chat_write(int sockfd)
{
while(1)
{
printf("%s",buf);
fgets(buffer,MAXDATALEN-1,stdin);
if(strlen(buffer)-1>sizeof(buffer)){
printf("buffer size full\t enter within %d characters\n",sizeof(buffer));
bzero(buffer,MAXDATALEN);
__fpurge(stdin);
}
n=send(sockfd,buffer,strlen(buffer),0);
if(strncmp(buffer,"quit",4)==0)
exit(0);
bzero(buffer,MAXDATALEN);
}//while ends
}
/*======handling signals==========*/
void *quitproc(){ //handling ctrl+d
printf("\rPLEASE TYPE 'quit' TO EXIT\n");
}
void *zzz(){ //handling ctrl+z
printf("\rPLEASE TYPE 'quit' TO EXIT\n");
}
/*=================================================================*/
/*要在Linux中编译我,请键入:gcc-oservert1.c-lpthread*/
/*t1.c—使用TCP/IP*的服务器程序的代码
/****服务器代码****/
#包括
#包括
#包括//用于套接字
#包括
#包含//用于字符串操作
#包括//此处定义的Internet协议系列sockaddr\u
#包括//用于cosy POSIX线程
#include//for inet\u ntoa()函数
#包含//此处定义的空常量
#包含//用于ctrl+c信号
#定义队列中的积压100//连接
#定义MAXDATALEN 256//要发送的消息的最大大小
#定义端口2012//默认端口号
/*注意:端口参数是可选的。如果未指定端口,
*服务器使用端口提供的默认值。*/
结构节点/*用于处理所有客户端的结构*/
{
国际港口;
字符用户名[10];
结构节点*下一步;
};
typedef结构节点*ptrtonode;
typedef PTRTO节点头;
typedef ptrtonode addr;
void sendtoall(char*,int new_fd)/*向所有连接的客户端发送聊天MSG*/
void-Quitall()/*如果服务器关闭,向所有人发送消息*/
水头变空(水头h)/*结算清单*/
无效删除(内部端口,头部h)/*在客户端退出时删除客户端值*/
无效插入(内部端口,字符*,标题h,地址a)/*插入新客户端*/
无效删除列表(标题h)/*结算清单*/
无效显示(const head h)/*列出所有已连接的客户端*/
void*Quitproc()/*信号处理器*/
void*服务器(void*arg)/*每个连接的客户端的服务器实例*/
void zzz();
字符用户名[10]/*用户名大小*/
int sf2;
头部h/*结构头类型的变量*/
字符缓冲区[MAXDATALEN];
/******主启动装置*********/
intmain(intargc,char*argv[]){
int sockfd,套接字的新_fd;/*变量*/
int portnum;/*端口号变量(如果提供)*/
server_addr;/*结构中的struct sockaddr_保存服务器地址*/
客户端中的struct sockaddr\u\u addr;/*用于保存客户端地址的结构*/
int cli_size,z;/*地址长度*/
pthread_t thr;/*用于保存线程ID的变量*/
int yes=1;
addr a;/*类型为struct addr*/
printf(“\n\t*-*-*-*服务器已启动*-*-*-*\n”);
/*=可选或默认端口参数=*/
如果(argc==2)
portnum=atoi(argv[1]);
其他的
portnum=PORT;//如果端口号未作为参数提供,则使用默认端口
printf(“端口号:\t%d\n”,portnum);
h=MakeEmpty(NULL);//释放列表
/*=服务器的设置信息=*/
服务器地址sin\u family=AF\u INET;/*将family设置为Internet*/
服务器\u addr.sin\u addr.s\u addr=htonl(INADDR\u ANY);/*设置IP地址*/
服务器地址sin\u port=htons(portnum);
printf(“IP地址:\t%s\n”,inet\u ntoa(服务器地址sin\u地址));
/*=正在创建套接字=*/
sockfd=套接字(AF_INET,SOCK_STREAM,0);
如果(sockfd==-1){
printf(“server-socket()错误”);//调试
出口(1);
}否则
printf(“套接字\t\t已创建。\n”);
if(setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int))=-1{
printf(“setsockopt错误”);//调试
出口(1);
}else printf(“重用\t\tport\n”);
/*=绑定套接字=*/
if(bind(sockfd,(struct sockaddr*)和server_addr,sizeof(struct sockaddr))=-1{
printf(“绑定失败\n”);//调试
退出(1);}
其他的
printf(“绑定\t\t成功。\n\n”);
printf(“\t\t按CTRL+z以查看联机客户端\n\n”);
/*=侦听模式上的套接字=*/
倾听(sockfd,BACKLOG);
printf(“等待客户……”\n);
if(signal(SIGINT,(void*)Quitproc)=0)//信号处理程序
if(信号(SIGTSTP,zzz)==0)//信号处理程序
而第(1)款{
cli_size=sizeof(struct sockaddr_in);//cli_size必须作为pthread_create的参数
new_fd=accept(sockfd,(struct sockaddr*)&client_addr,&cli_size);//接受来自客户端的连接
a=h;
/*=使用name=*/登录
bzero(用户名,10);
如果(recv(new_fd,username,sizeof(username),0)>0);
用户名[strlen(username)-1]=':';
printf(“\t%d->%s加入聊天室\n”,新的\u fd,用户名);
sprintf(缓冲区,“%s处于联机状态\n”,用户名);
Insert(new_fd,username,h,a);//在列表中插入新接受的客户机套接字fd
a=a->next;
/*=通知所有客户有关新加入的客户=*/
a=h;
做{
a=a->next;
sf2=a->端口;
如果(sf2!=新的\u fd)
发送(sf2,缓冲区,sizeof(缓冲区),0);
}while(a->next!=NULL);
printf(“服务器从%s&%d获得连接\n\n”,inet\u ntoa(client\u addr.sin\u addr),new\u fd);//调试
struct Node args;//将多个参数传递给服务器函数的struct
struct timeval tv;
tv.tv_sec = 30; /* 30 Secs Timeout */
tv.tv_usec = 0;
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,sizeof(struct timeval));