使用tcp+select实现客户端与客户端的通信
使用多路复用实现客户端与客户端进行通信;
原理:客户端只要一连上服务器,立马给服务器发送用户名,然后在服务端将newsocketfd存放在同一个结构体中,客户端先给服务器发送数据,然后通过服务器转发给客户端。(服务器先会查找对应名字的newsocketfd 然后向该newsocketfd中写入数据)。
服务器端程序:
#include<stdio.h>
#include<netinet/in.h>
#include<stdlib.h>
#include<string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include<pthread.h>
#include<strings.h>
struct fd_info
{
int cfd;
char cname[];
};
void send1(struct fd_info a[])
{
int i;
char buf[];
bzero(buf,);
fgets(buf,,stdin);
for(i=;i<;i++)
{ if(a[i].cfd !=)
send(a[i].cfd,buf,,);
}
}
int main()
{
struct fd_info fds[]; int maxfd = -; int socketfd = socket(PF_INET,SOCK_STREAM,);
if(socketfd>maxfd)
maxfd = socketfd;
struct sockaddr_in saddr;
memset(&saddr,,sizeof(saddr));
saddr.sin_family = PF_INET;
saddr.sin_port = htons();
saddr.sin_addr.s_addr = inet_addr("192.168.1.46");
int newsocketfd;
int n = ;
setsockopt(socketfd, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(int));
if(bind(socketfd,(struct sockaddr*)&saddr,sizeof(struct sockaddr_in))<)
perror("bind() error!\n"); if(listen(socketfd,)<)
perror("listen() error!\n");
struct sockaddr_in caddr;
int s = sizeof(struct sockaddr);
// newsocketfd = accept(socketfd,(struct sockaddr*)&caddr,&s);
fd_set fd;
FD_ZERO(&fd);
int ret;
char buf[],buf1[];
int i;
for(i=;i<;i++)
{
fds[i].cfd = ;
}
char namebuf[];
int rsize;
char *split = ":";
char *token,*tokem,*tokeu;
while()
{
FD_ZERO(&fd);
FD_SET(,&fd);
FD_SET(socketfd,&fd);
/*将新socket加入到fd_set中*/
for(i=;i<;i++)
{
// printf("--------------\n");
if(fds[i].cfd!=)
FD_SET(fds[i].cfd,&fd);
}
/*监视老socketfd的状态是否改变,一旦改变说明有新的服务器连接进来
然后接受客户端发送过来的数据,并将其和newsocketfd存放于同一个结构体中*/
ret = select(maxfd+,&fd,NULL,NULL,NULL);
if(ret<)
{
perror("select() error!\n");
break;
}
else if(ret ==)
{
continue;
}
else
{
if(FD_ISSET(socketfd,&fd))
{
newsocketfd = accept(socketfd,(struct sockaddr*)&caddr,&s);
if(newsocketfd>maxfd)
{
maxfd = newsocketfd; recv(newsocketfd,namebuf,,); // printf("%s\n",namebuf);
for(i=;i<;i++)
{
if(fds[i].cfd==)
{
fds[i].cfd = newsocketfd;
strcpy(fds[i].cname,namebuf);
printf("%s\n",fds[i].cname);
// printf("--------------\n");
break;
}
} }
continue;
}
// printf("helo\n");
/*将接受到的数据进行解析*/
for(i=;i<;i++)
{
if((fds[i].cfd !=) && FD_ISSET(fds[i].cfd,&fd))
{
bzero(buf1,);
if(recv(fds[i].cfd,buf1,,)==)
{
//printf("core error!\n");
close(fds[i].cfd);
// printf("core error!\n");
fds[i].cfd = ;
// printf("core error!\n");
break;
}
// printf("%s\n",buf1);
token = strtok(buf1,split);
// printf("token=%s\n",token);
tokem = strtok(NULL,split);
// printf("tokem=%s\n",tokem);
tokeu = strtok(NULL,split);
// printf("tokeu=%s\n",tokeu); /*判断是要给那个newsocketfd发送数据,然后将数据发送出去*/
for(i=;i<;i++)
{
// int flag;
// printf("----\n");
if(!strncmp(fds[i].cname,token,))
{
// printf("----\n");
strcat(tokeu,":");
// printf("----\n");
strcat(tokeu,tokem);
printf("cname = %s\n",fds[i].cname); // break; if(send(fds[i].cfd,tokeu,strlen(tokeu),)<)
perror("send() error!\n");
// break;
}
else
{
// printf("this is not present!\n");
} }
}
continue;
}
/**给所有客户端发送数据*/
if(FD_ISSET(0,&fd))
{
send1(fds);
}
}
}
close(socketfd);
close(newsocketfd); } //客户端代码:
#include<stdio.h>
#include<pthread.h>
#include<netinet/in.h>
#include<stdlib.h>
#include<string.h>
#include<strings.h>
#include<sys/types.h>
#include<sys/socket.h>
int main(int argc,char **argv)
{
int socketfd,ret;
fd_set fd;
FD_ZERO(&fd);
FD_SET(0,&fd); socketfd = socket(PF_INET,SOCK_STREAM,0);
FD_SET(socketfd,&fd);
ret = select(socketfd+1,&fd,NULL,NULL,NULL);
struct sockaddr_in saddr;
memset(&saddr,0,sizeof(saddr));
saddr.sin_family = PF_INET;
saddr.sin_port = htons(6000);
saddr.sin_addr.s_addr = inet_addr("192.168.1.46"); if(connect(socketfd,(struct sockaddr *)&saddr,sizeof(struct sockaddr))<0) perror("connect() error!\n");
//只要与服务器连上立马将自己的昵称发送过去
send(socketfd,argv[],strlen(argv[]),);
char buf[],buf1[];
while()
{
bzero(buf,);
bzero(buf1,); FD_SET(,&fd);
FD_SET(socketfd,&fd);
ret = select(socketfd+,&fd,NULL,NULL,NULL);
if(FD_ISSET(socketfd,&fd))
{
if(recv(socketfd,buf1,sizeof(buf1),)<)
perror("recv() error!\n");
printf("%s\n",buf1);
continue;
}
if(FD_ISSET(,&fd))
{
scanf("%s",buf);
strcat(buf,":");
strcat(buf,argv[]);
if(send(socketfd,buf,strlen(buf),)<)
perror("send() error!\n");
continue;
} }
}
使用tcp+select实现客户端与客户端的通信的更多相关文章
- tcp 服务端如何判断客户端断开连接
一篇文章: 最近在做一个服务器端程序,C/S结构.功能方面比较简单就是client端与server端建立连接,然后发送消息给server.我在server端会使用专门的线程处理一条socket连接 ...
- 网络编程之Socket的TCP协议实现客户端与客户端之间的通信
我认为当你学完某个知识点后,最好是做一个实实在在的小案例.这样才能更好对知识的运用与掌握 如果你看了我前两篇关于socket通信原理的入门文章.我相信对于做出我这个小案列是完全没有问题的!! 既然是小 ...
- 【VS开发】TCP服务端如何判断客户端断开连接
原文出自:http://www.cnblogs.com/youxin/p/4056041.html 一篇文章: 最近在做一个服务器端程序,C/S结构.功能方面比较简单就是client端与serve ...
- 客户端验证、tcp协议中多个客户端的同时在线
一.客户端验证 当在一个局域网内需要验证是否为合法的客户端连接时,我们需要写代码进行验证. Server端 import os import hmac import socket def auth(c ...
- 基于开源SuperSocket实现客户端和服务端通信项目实战
一.课程介绍 本期带给大家分享的是基于SuperSocket的项目实战,阿笨在实际工作中遇到的真实业务场景,请跟随阿笨的视角去如何实现打通B/S与C/S网络通讯,如果您对本期的<基于开源Supe ...
- socket 客户端和服务端通信
客户端要连接服务器:首先要知道服务器的IP地址.而服务器里有很多的应用程序,每一个应用程序对应一个端口号 所以客户端想要与服务器中的某个应用程序进行通信就必须要知道那个应用程序的所在服务器的IP地址, ...
- Python进阶----SOCKET套接字基础, 客户端与服务端通信, 执行远端命令.
Python进阶----SOCKET套接字基础, 客户端与服务端通信, 执行远端命令. 一丶socket套接字 什么是socket套接字: 专业理解: socket是应用层与TCP/IP ...
- springboot整合websocket实现客户端与服务端通信
定义 WebSocket是通过单个TCP连接提供全双工(双向通信)通信信道的计算机通信协议.此WebSocket API可在用户的浏览器和服务器之间进行双向通信.用户可以向服务器发送消息并接收事件驱 ...
- Netty入门之客户端与服务端通信(二)
Netty入门之客户端与服务端通信(二) 一.简介 在上一篇博文中笔者写了关于Netty入门级的Hello World程序.书接上回,本博文是关于客户端与服务端的通信,感觉也没什么好说的了,直接上代码 ...
随机推荐
- GMP大法教你重新做人(从入门到实战)
一.引言 GMP(The GNU Multiple Precision Arithmetic Library)又叫GNU多精度算术库,是一个提供了很多操作高精度的大整数,浮点数的运算的算术库,几乎没有 ...
- YUI3组件框架之plugin
plugin相关源码分析: plugin功能包括如下几个模块, 简单分析如下: pluginhost-base 维护对象 this._plugins = {}: 并提供方法: plug.unplug. ...
- dedecms下的tplcache模板缓存文件过多怎么清理?
时间:2016-04-18 09:32来源:www.ucbug.cc作者:网络 相信很多站长,或者seoer人员在备份用dedecms程序开发的网站时,发现下载到tplcache这个文件夹内容时候花了 ...
- Thinkphp5.0+Vue2.0前后端分离框架Vuethink
VueThink是一套基于Vue全家桶(Vue2.x + Vue-router2.x + Vuex)+ Thinkphp的前后端分离框架. 脚手架构建也可以通过vue官方的vue-cli脚手架工具构建 ...
- 解除织梦dedeCMS标题/关键词/ 简略标题长度限制听语音
dedeCMS標題.關鍵詞和簡略標題長度有限制,展示不全. 三者均使用SQL修改dede_archives主表關鍵詞和簡略標題還需修改/dede/目錄中的: archives_add.php, ...
- 关于JAVA字符编码:Unicode,ISO-8859-1,GBK,UTF-8编码及相互转换
我们最初学习计算机的时候,都学过ASCII编码. 但是为了表示各种各样的语言,在计算机技术的发展过程中,逐渐出现了很多不同标准的编码格式, 重要的有Unicode.UTF.ISO-8859-1和中国人 ...
- Performance Testing 前期准备以及场景设计
性能测试的session参加过几个,也查阅了很多相关的资料.年前被分配了测试任务,一直拖到现在,准备开始做的时候,才发现真的是不知道如何做起啊.今天和同事聊了一下,有很大启发.测试小白一枚,只分享一下 ...
- Long转Date/页面自定义标签
运行时发现异常:org.apache.jasper.JasperException: javax.el.ELException: java.lang.IllegalArgumentException: ...
- Linux修改主机名脚本-不重启-支持RedHat、SUSE
需要用脚本修改主机名,涉及RedHat.SUSE系统,并且要求修改立即生效且不重启,下面就是我的脚本. 使用脚本的方法如下: 1 首先创建一个脚本文件,假如命名为ModifyHostname.sh: ...
- Java的NIO
1. 基本 概念 IO 是主存和外部设备 ( 硬盘.终端和网络等 ) 拷贝数据的过程. IO 是操作系统的底层功能实现,底层通过 I/O 指令进行完成. 所有语言运行时系统提供执行 I/O 较高级 ...