接上篇博文,本文是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

微信扫一扫,关注我!


Linux以下基于TCP多线程聊天室(server)的更多相关文章

  1. Linux以下基于TCP多线程聊天室(client)

    不怎么会弄这个博客的排版,就直接将代码附上: 主要是使用多线程去等待接受数据和发送数据.以下是client的代码: tcpsed.h文件 1 2 3 4 5 6 7 8 9 10 11 12 13 1 ...

  2. TCP多线程聊天室

    TCP协议,一个服务器(ServerSocket)只服务于一个客户端(Socket),那么可以通过ServerSocket+Thread的方式,实现一个服务器服务于多个客户端. 多线程服务器实现原理— ...

  3. Linux下c++11多线程聊天室

    刚看的c++11多线程,写个聊天室试试编译的时候加上 c++11 和 多线程库g++ -Wall -std=c++0x -pthread -o server server.cppserver 和cli ...

  4. Java 网络编程 -- 基于TCP 实现聊天室 群聊 私聊

    分析: 聊天室需要多个客户端和一个服务端. 服务端负责转发消息. 客户端可以发送消息.接收消息. 消息分类: 群聊消息:发送除自己外所有人 私聊消息:只发送@的人 系统消息:根据情况分只发送个人和其他 ...

  5. Linux下c语言TCP多线程聊天室

    开发环境:Linux,GCC 相关知识:TCP(博客:传送门),线程 附加:项目可能还有写不足之处,有些bug没调出来(如:对在线人数的控制),希望大佬赐教. 那么话不多说,放码过来: 码云:传送门, ...

  6. 基于Linux的TCP网络聊天室

    1.实验项目名称:基于Linux的TCP网络聊天室 2.实验目的:通过TCP完成多用户群聊和私聊功能. 3.实验过程: 通过socket建立用户连接并传送用户输入的信息,分别来写客户端和服务器端,利用 ...

  7. 【C++】基于socket的多线程聊天室(控制台版)

    以前学习socket网络编程和多线程编程的时候写的一个练手程序 聊天室基本功能: 1.用户管理:登录,注册,登出,修改用户名,修改密码 2.聊天室功能:群聊,私聊,获取在线用户列表,获取所有用户列表 ...

  8. 基于WebSocket实现聊天室(Node)

    基于WebSocket实现聊天室(Node) WebSocket是基于TCP的长连接通信协议,服务端可以主动向前端传递数据,相比比AJAX轮询服务器,WebSocket采用监听的方式,减轻了服务器压力 ...

  9. [Java聊天室server]实战之五 读写循环(服务端)

    前言 学习不论什么一个稍有难度的技术,要对其有充分理性的分析,之后果断做出决定---->也就是人们常说的"多谋善断":本系列尽管涉及的是socket相关的知识,但学习之前,更 ...

随机推荐

  1. alidoing --使用JS实现多语言框架、喜欢的请进、、瓦特平台!

    大家好! 多语言实现的案例:http://alidoing.com/或者http://www.alidoing.com/ 图:切换语言界面 JS代码实现: 1.首先新建一个对象langobj,当然对象 ...

  2. Java生产者消费者模式

    为什么要使用生产者和消费者模式 在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程.在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能 ...

  3. iOS学习笔记28-系统服务(一)短信和邮件

    一.系统应用 在开发某些应用时,我们可能希望能够调用iOS系统内置的电话.短信.邮件.浏览器应用,或者直接调用安装的第三方应用,这个要怎么实现呢? 这里统一使用UIApplication的一个对象方法 ...

  4. CS231n笔记 Lecture 4 Introduction to Neural Networks

    这一讲主要介绍了神经网络,基本内容之前如果学习过Andrew的Machine learning应该也都有所了解了.不过这次听完这一讲后还是有了新的一些认识. 计算图 Computational gra ...

  5. hdoj--1010<dfs+奇偶剪枝>

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1010 题目描述:在n*m的矩阵中,有一起点和终点,中间有墙,给出起点终点和墙,并给出步数,在该步数情况 ...

  6. Centos7系统rc.local不起作用问题

    Centos7系统rc.local不起作用问题 来源 https://www.cnblogs.com/xjz00/p/7729405.html Centos7已经写了要chmod +x /etc/rc ...

  7. IDA Pro使用技巧及大杂烩

    IDA Pro使用技巧及大杂烩 IDA Pro基本简介 IDA加载完程序后,3个立即可见的窗口分别为IDA-View,Named,和消息输出窗口(output Window). IDA图形视图会有执行 ...

  8. BZOJ4818 [SDOI2017]序列计数 【生成函数 + 快速幂】

    题目 Alice想要得到一个长度为n的序列,序列中的数都是不超过m的正整数,而且这n个数的和是p的倍数.Alice还希望 ,这n个数中,至少有一个数是质数.Alice想知道,有多少个序列满足她的要求. ...

  9. phpMyAdmin操作之改管理员密码

    1.登录phpMyAdmin 默认地址:http://localhost/phpmyadmin 2.点击用户按钮 3.往下拉找到修改密码 点执行就修改了 注意: 如果再次登录时报错提示: #1045 ...

  10. 【BZOJ3529】【SDOI2014】数表 (莫比乌斯反演+树状数组)

    传送门 Description 有一张$n\times m$的数表,其第$i$行第$j$列 $(1≤i≤n,1≤j≤m)$ 的数值为能同时整除$i$和$j$的所有自然数之和.现在给定$a$,计算数表中 ...