接上篇博文,本文是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. uiautomator 一个简单脚本创建流程

    http://www.codeceo.com/article/android-ui-auto-test.html

  2. oracle无参数和带参数的存储过程实例

    SQL中调用存储过程语句:call procedure_name(); 注:调用时”()”是不可少的,无论是有参数还是无参数. 定义对数据库存储过程的调用时1.无参数存储过程:{call proced ...

  3. 【java基础 14】锁的粒度:ThreadLocal、volatile、Atomic和Synchronized

    导读:题目中提到的几个关键字,分别是解决并发问题中,加锁所使用到的几个关键字,每个关键字代表的锁的粒度 不同,本篇博客,主要是从概念定义上,区分这几个关键字的应用场景.(PS:睡梦中,依稀记得有回面试 ...

  4. iOS使用cookie

    // // ViewController.m // cookie // // Created by 谭启宏 on 16/3/4. // Copyright © 2016年 tqh. All right ...

  5. linux工作笔记

    1. Linux基础 1.1. Unix 1965年,AT&T贝尔电话实验室.通用电气公司.麻省理工学院MAC课题组一起联合开发一个称为Multics的新操作系统.该项目目的是让大型主机可以同 ...

  6. bzoj1566【Noi2009】管道取珠

    题意:http://www.lydsy.com/JudgeOnline/problem.php?id=1566 两个栈不断pop,共C(n+m,n)种,ai表示每个相同序列的方案数,求∑(ai^2) ...

  7. 洛谷 [P2859] 摊位预定

    贪心 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm ...

  8. ado:SqlDataAdapter,dataset 与SqlDataReader的用法一

    原文发布时间为:2008-08-01 -- 来源于本人的百度文章 [由搬家工具导入] using System;using System.Data;using System.Configuration ...

  9. PAT 甲级 1087 All Roads Lead to Rome(SPFA+DP)

    题目链接 All Roads Lead to Rome 题目大意:求符合题意(三关键字)的最短路.并且算出路程最短的路径有几条. 思路:求最短路并不难,SPFA即可,关键是求总路程最短的路径条数. 我 ...

  10. 洛谷——P1508 Likecloud-吃、吃、吃

    P1508 Likecloud-吃.吃.吃 题目背景 问世间,青春期为何物? 答曰:“甲亢,甲亢,再甲亢:挨饿,挨饿,再挨饿!” 题目描述 正处在某一特定时期之中的李大水牛由于消化系统比较发达,最近一 ...