Linux以下基於TCP多線程聊天室(server)


    接上篇博文,本文是server端的實現,主要實現的功能,就是現實client的連接。轉發client發送的消息。以及client掉線提示等功能,同一時候能夠在這這上面擴展和TCP以及線程相關的功能木塊。

tcpreceive.h

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
       
       
      
      
              
#ifndef TCPRECEIVE_H
#define TCPRECEIVE_H
#define BUFFSIZE 2048
#define listen_max 5
int cond ;
int rscond ;
typedef struct TCP_rcv_arg
{
char * local_addr ;
int tcp_port ;
} TCP_rcv_arg_t ;
void stop_handler ( int signum );
void * tcppackrecv ( void * arg );
#endif
tcpreceive.c 

   1
   2
   3
   4
   5
   6
   7
   8
   9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24
  25
  26
  27
  28
  29
  30
  31
  32
  33
  34
  35
  36
  37
  38
  39
  40
  41
  42
  43
  44
  45
  46
  47
  48
  49
  50
  51
  52
  53
  54
  55
  56
  57
  58
  59
  60
  61
  62
  63
  64
  65
  66
  67
  68
  69
  70
  71
  72
  73
  74
  75
  76
  77
  78
  79
  80
  81
  82
  83
  84
  85
  86
  87
  88
  89
  90
  91
  92
  93
  94
  95
  96
  97
  98
  99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
       
       
      
      
              
#include "tcpreceive.h"
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/param.h>
#include <arpa/inet.h>
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include <ctype.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <pthread.h>
void stop_handler ( int sinnum )
{
cond = 0 ;
rscond = 0 ;
}
void * tcppackrecv ( void * arg )
{
int listen_fd , client_id , len = 1 ;
struct sockaddr_in server_addr ;
struct sockaddr_in client_addr ;
int sin_size ;
fd_set master ;
fd_set read_fds ;
int fdmax , i , newfd , j ;
char buf [ BUFFSIZE + 1 ];
TCP_rcv_arg_t * rcv_arg = ( TCP_rcv_arg_t * ) arg ;
sin_size = sizeof ( client_addr );
if ( - 1 == ( listen_fd = socket ( AF_INET , SOCK_STREAM , 0 )))
{
fprintf ( stderr , "Socket Error:%s \n " , strerror ( errno ));
pthread_exit ( NULL );
}
memset ( & server_addr , 0 , sizeof ( server_addr ));
server_addr . sin_family = AF_INET ;
server_addr . sin_addr . s_addr = htonl ( INADDR_ANY );
//server_addr.sin_addr.s_addr = inet_addr((*rcv_arg).local_addr);
server_addr . sin_port = htons (( * rcv_arg ). tcp_port );
setsockopt ( listen_fd , SOL_SOCKET , SO_REUSEADDR , & len , sizeof ( len ));
if ( - 1 == bind ( listen_fd ,( struct sockaddr * ) & server_addr , sizeof ( server_addr )))
{
fprintf ( stderr , "Bind Error:%s \n " , strerror ( errno ));
pthread_exit ( NULL );
}
if ( - 1 == listen ( listen_fd , listen_max ))
{
fprintf ( stderr , "Listen Error:%s \n " , strerror ( errno ));
pthread_exit ( NULL );
}
//printf("listen ok!\n");
FD_ZERO ( & master );
FD_ZERO ( & read_fds );
FD_SET ( listen_fd , & master );
fdmax = listen_fd ;
cond = 1 ;
while ( cond )
{
read_fds = master ;
if ( - 1 == select ( fdmax + 1 , & read_fds , NULL , NULL , NULL ))
{
fprintf ( stderr , "Server Select Error:%s \n " , strerror ( errno ));
pthread_exit ( NULL );
}
for ( i = 0 ; i <= fdmax ; i ++ )
{
if ( FD_ISSET ( i , & read_fds ))
{
if ( i == listen_fd )
{
if ( - 1 == ( newfd = accept ( listen_fd ,( struct sockaddr * ) & client_addr ,( socklen_t * ) & sin_size )))
{
fprintf ( stderr , "Accept Error:%s \n " , strerror ( errno ));
}
else
{
FD_SET ( newfd , & master );
if ( newfd > fdmax )
{
fdmax = newfd ;
}
sprintf ( buf , "Your SocketID is:%d." , newfd );
if ( send ( newfd , buf , 21 , 0 ) < 0 )
{
printf ( "Send Error! \n " );
}
printf ( "there is a new connection in,form %s,SocketID is %d. \n " , inet_ntoa ( client_addr . sin_addr ), newfd );
}
}
else
{
sprintf ( buf , "Form %2d: \n " , i );
if (( len = recv ( i , buf + 9 , BUFFSIZE - 10 , 0 )) <= 0 )
{
if ( 0 == len )
{
printf ( "SocketID %d has left! \n " , i );
}
else
{
perror ( "the recv() go end! \n " );
}
close ( i );
FD_CLR ( i , & master );
}
else
{
len += 9 ;
buf [ len ] = '\0' ;
printf ( "%s \n " , buf );
for ( j = 0 ; j <= fdmax ; j ++ )
{
if ( FD_ISSET ( j , & master ) && j != listen_fd && j != i )
{
if ( - 1 == send ( j , buf , len , 0 ))
{
perror ( "Send() error! \n " );
}
}
}
}
}
}
}
}
pthread_exit ( NULL );
}
server.c

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
       
       
      
      
              
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include "tcpreceive.h"
#define PORT 8888
#define IP "192.168.1.220"
int main ()
{
pthread_t tid ;
pthread_t id ;
void * tret ;
TCP_rcv_arg_t rcv_arg ;
rcv_arg . tcp_port = PORT ;
rcv_arg . local_addr = IP ;
printf ( "the main process! \n " );
int i = pthread_create ( & tid , NULL ,( void * ) tcppackrecv ,( void * ) & rcv_arg );
if ( i != 0 )
{
printf ( "Create pthread error! \n " );
pthread_exit ( NULL );
}
if ( 0 != pthread_join ( tid , & tret ))
{
printf ( "Join pthread error! \n " );
}
return 0 ;
}
為了大家編譯方便,將Makefile也放上來:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
       
       
      
      
              
all:
gcc -c tcpsed.c
ar cr libtcpsed.a tcpsed.o
gcc -c tcpreceive.c
ar cr libtcpreceive.a tcpreceive.o
gcc -o server server.c -L. -ltcpreceive -lpthread
gcc -o client client.c -L. -ltcpsed -lpthread
clean:
rm -rf *.o *.a server client

CSDN上面源代碼下載地址:

http://download.csdn.net/detail/u012377333/8079943

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
        
        
       
       
               
all:
gcc -c tcpsed.c
ar cr libtcpsed.a tcpsed.o
gcc -c tcpreceive.c
ar cr libtcpreceive.a tcpreceive.o
gcc -o server server.c -L. -ltcpreceive -lpthread
gcc -o client client.c -L. -ltcpsed -lpthread
clean:
rm -rf *.o *.a server client
微信掃一掃,關注我!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM