Linux以下基于TCP多线程聊天室(server)

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

微信扫一扫,关注我!

时间: 2024-10-10 22:03:20

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

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

Linux下面基于TCP多线程聊天室(客户端)

不怎么会弄这个博客的排版,就直接将代码附上: 主要是使用多线程去等待接受数据和发送数据,下面是客户端的代码: tcpsed.h文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #ifndef RTPSED_H #define RTPSED_H #define BUFFSIZE 512 int runcond; int socketfd; typedef struct TCP_send_arg { char *tcpserver

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

刚看的c++11多线程,写个聊天室试试编译的时候加上 c++11 和 多线程库g++ -Wall -std=c++0x -pthread -o server server.cppserver 和client 都是 q 退出?1. [代码]server.cpp #include <iostream>#include <thread>#include <arpa/inet.h>#include <cstring>#include <vector>#i

基于linux的TCP网络聊天室设计与实现

利用Linux实现基于TCP模式的网络聊天程序 主要完成的两大组成部分为:服务器和客户端. 服务器程序主要负责监听客户端发来的消息. 客户端需要登录到服务器端才可以实现正常的聊天功能.该程序是利用进程以及共享内存来实现群发送消息的. 以下简单分析一下服务器端和客户端两个方面所要完成的任务. 服务器的主要功能如下: 在特定的端口上进行监听,等待客户端的连接. 用户可以配置服务器端的监听端口. 向连接的客户端发送登录成功信息. 向已经连接到服务器的客户端的用户发送系统消息. 使用TCP多线程并发服务

多线程聊天室

基于Java的多线程聊天室 客户端: public class MultiThreadClient { private static class RecMsg implements Runnable{ private Socket client; public RecMsg(Socket client) { this.client = client; } @Override public void run() { Scanner sc = null; try { sc = new Scanner

[Java聊天室server]实战之二 监听类

前言 学习不论什么一个稍有难度的技术,要对其有充分理性的分析,之后果断做出决定---->也就是人们常说的"多谋善断":本系列尽管涉及的是socket相关的知识,但学习之前,更想和广大程序猿分享的是一种心境:学习是一个循序渐进的过程,心态应该随时调节,保持戒骄戒躁的状态.比方近期在看网易公开课MIT<算法导论>,老师提到,学习算法之前要计算机数学+离散数学+概率论等课程的知识,所以一直学不好算法的程序猿最好还是从基础入手,这都是中国式教育惹的祸啊!(此处省略一万字...

MFC笔记之多线程聊天室

新手刚接触,跟着孙鑫老师视频一步一步的做.从VC6.0到VS2010好像并不是那么顺利,下面记录下一点收获. 网络编程的一般步骤: 1声明套接字版本(WSAStartup);2创建套接字(socket);3绑定套接字(bind);4发送接收(sendto/recvfrom);5关闭(closesocket) 第1~3步代码如下: 1 CString error; 2 WORD wver; 3 wver=MAKEWORD(1,1); 4 WSAData data; 5 if(0!=WSAStart

基于java的聊天室/群发控制台程序

java聊天室 1.概述 基于tcp协议的,由一个服务器和多个客户端组成,一个客户端发送消息,其他所有客户端都能接收到消息.在服务器端设置一个线程监听客户端发来的请求(消息),并且向所有的客户端响应.每个客户端也有一个线程用来接收服务器端的请求. 2.代码如下 public class Client { public static void main(String[] args) throws IOException { //创建套接字 Socket socket = new Socket("l

基于java网络聊天室---前言

很久之前做的一个东西,现在拿出来整理一下放在自己的博客中! 一. 设计目的 随着人互联网的发展,人和人之间的沟通方式也越来越便捷和多样化,在线聊天工具已经成为人们生活中够通不可缺少的部分,在学习完 java网络编程课程,如果能开发一款属于自己的聊天工具,和好友进行私密对话,则是一件令人兴奋的事.同时,安全可靠的TCP这两种 通信协议,是非常重要的内容,值得研究. 二. 设计内容 本聊天室程序基于C/S模式,聊天室共分为服务器端和客户端两部分,服务器端程序主要负责侦听客户端发来的消息,客户端需登陆