接上篇博文,本文是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. [转载]ExtJs4 笔记(1) ExtJs大比拼JQuery:Dom文档操作

    出处:[Lipan] (http://www.cnblogs.com/lipan/) 现在主流的JS框架要数ExtJs和JQuery应用的比较广泛.JQuery属于轻量级的,一般做网站应用比较常见,可 ...

  2. 令人惊叹的Chrome浏览器插件

    Chrome是一个简洁而又高效(高性能,高消耗)的浏览器.接下来让我吐血推荐一些常用的Chrome插件. 日常插件 uBlock Origin ----- 比Adblock性能更高的广告插件. Adk ...

  3. PHP模版引擎twig wordpress中调用文章第一张图片

    wordpress当文章没有添加Featured media的时候, 就调用文章第一张图片, 调用的wordpress代码函数为: <?php echo catch_that_image(); ...

  4. 解决Failure to transfer org.apache.maven.plugins:maven-surefire-plugin:pom:2.7

    一般情况下可能是文件格式有问题,将正确的文件内容替换掉错误的文件内容,不断地尝试,直到文件不报错,当然也有可能是下面的原因:下面是2.7.1版本的方法,其他类似) 或者是:进入该jar包指示的路径,删 ...

  5. 小程序语音红包开发中 汉字转拼音的问题 微信小程序红包开发遇到的坑

    公司最近在开发微信小程序的红包功能,语音红包需要用到文字转拼音的功能. 之前介绍过怎么将中文的汉字转为拼音的,具体看下面这篇文章. 微信语音红包小程序开发如何提高精准度 红包小程序语音识别精准度 微信 ...

  6. Process类,Thread类,Pool类,gevent类,ProcessPoolExecutor,ThreadPoolExecutor的用法比较

    一 Process类 multiprocessing模块下的一个类 创建子进程. 有两种方法 方法一 from multiprocessing import Process import os def ...

  7. 一个简单的django user.is_authenticated问题

    Q1:这是我一个view函数: def user_info(request): response=HttpResponse() user=request.user user_id=user.id if ...

  8. 标准C程序设计七---121

    Linux应用             编程深入            语言编程 标准C程序设计七---经典C11程序设计    以下内容为阅读:    <标准C程序设计>(第7版) 作者 ...

  9. set up trace code tool

    這以 GNU GLOBAL 6.5.6 為示範 1: install GNU GLOBAL https://www.gnu.org/software/global/download.html sudo ...

  10. 浅谈JS的arguments对象

    在JavaScript中,arguments属于当前对象的一个内置属性,arguments非常类似于Array对象,但是又不是实例的Array.比如: Array.prototype.testArg ...