接上篇博文,本文是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. Selenium WebDriver- 操作JavaScript的Alert弹窗

    弹层和弹框是有区别的,弹框是那种完全没样式的框子:弹层是可以直接看到html的,有样式 #encoding=utf-8 import unittest import time from seleniu ...

  2. python相关——如何安装pip

    今天在新的一台电脑上安装了pip.流程有点忘记了,在这里再次记录下来. 本教程基于python3.4,并且需要连接互联网,总共需要两步. 1.要安装pip,首先要安装setuptools,链接:htt ...

  3. kb-07-RMQ线段树--07(动态规划)

    RMQ是一类解决区间最值查询的算法的通称:.一共有四类:在代码中有说明: 下面是ST算法,就是动态规划做法: 来看一下ST算法是怎么实现的(以最大值为例): 首先是预处理,用一个DP解决.设a是要求区 ...

  4. spring分布式事务控制

    应用场景问题描述解决方法多数据源配置单元测试第一种方法:最大努力一次提交模式第二种方法:最大努力一次提交模式 但使用ChainedTransactionManagerChainedTransactio ...

  5. BZOJ3505 & 洛谷P3166 [Cqoi2014]数三角形 【数学、数论】

    题目 给定一个nxm的网格,请计算三点都在格点上的三角形共有多少个.下图为4x4的网格上的一个三角形. 注意三角形的三点不能共线. 输入格式 输入一行,包含两个空格分隔的正整数m和n. 输出格式 输出 ...

  6. 刷题总结——开车旅行(NOIP2012 set+倍增)

    题目: 题目描述 小 A 和小 B 决定利用假期外出旅行,他们将想去的城市从 1 到 N 编号,且编号较小的城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 i 的海拔高度为Hi,城 ...

  7. 常用jar包下载地址汇总

    <常用开发包下载地址汇总> 下载Jackson http://www.java2s.com/Code/Jar/j/Downloadjacksonjar.htm 下载Simple Loggi ...

  8. ActiveMQ使用经验与优化

    摘自:http://blog.csdn.net/m13321169565/article/details/8081314 1.1 不要频繁的建立和关闭连接 JMS使用长连接方式,一个程序,只要和JMS ...

  9. [JLOI2011]飞行路线 (分层图,最短路)

    题目链接 Solution 建立 \(k+1\) 层图跑 \(Dijkstra\) 就好了. Code #include<bits/stdc++.h> #define ll long lo ...

  10. FootAwesome字体图标

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...