首页 > 代码库 > Linux下面基于TCP多线程聊天室(服务器)

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

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