Linux下面基于TCP多线程聊天室(服务器)

    接上篇博文,本文是服务器端的实现,主要实现的功能,就是现实客户端的连接,转发客户端发送的消息,以及客户端掉线提示等功能,同时可以在这这上面扩展和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
微信扫一扫,关注我!

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
项目简介: 采用I/O复用技术select实现socket通信,采用多线程负责每个客户操作处理,完成Linux下的多客户聊天室! OS:Ubuntu 15.04 IDE:vim gcc make DB:Sqlite 3 Time:2015-12-09 ~ 2012-12-21 项目功能架构: 1. 采用client/server结构; 2. 给出客户操作主界面(注册、登录、帮助和退出)、登录后主界面(查看在线列表、私聊、群聊、查看聊天记录、退出); 3. 多客户可同时连接服务器进行自己操作; ##服务器端## 1. server.c:服务器端主程序代码文件; 2. config.h:服务器端配置文件(包含需要的头文件、常量、数据结构及函数声明); 3. config.c:服务器端公共函数的实现文件; 4. list.c:链表实现文件,用于维护在线用户链表的添加、更新、删除操作; 5. register.c:服务器端实现用户注册; 6. login.c:服务器端实现用户登录; 7. chat.c:服务器端实现用户的聊天互动操作; 8. Makefile:服务器端make文件,控制台执行make命令可直接生成可执行文件server ##客户端## 1. client.c:客户端主程序代码文件; 2. config.h:客户端配置文件(包含需要的头文件、常量、数据结构及函数声明); 3. config.c:客户端公共函数的实现文件; 4. register.c:客户端实现用户注册; 5. login.c:客户端实现用户登录; 6. chat.c:客户端实现用户的聊天互动操作; 7. Makefile:客户端make文件,控制台执行make命令可直接生成可执行文件client;
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值