使用多路复用实现客户端与客户端进行通信;

原理:客户端只要一连上服务器,立马给服务器发送用户名,然后在服务端将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实现客户端与客户端的通信的更多相关文章

  1. tcp 服务端如何判断客户端断开连接

    一篇文章:   最近在做一个服务器端程序,C/S结构.功能方面比较简单就是client端与server端建立连接,然后发送消息给server.我在server端会使用专门的线程处理一条socket连接 ...

  2. 网络编程之Socket的TCP协议实现客户端与客户端之间的通信

    我认为当你学完某个知识点后,最好是做一个实实在在的小案例.这样才能更好对知识的运用与掌握 如果你看了我前两篇关于socket通信原理的入门文章.我相信对于做出我这个小案列是完全没有问题的!! 既然是小 ...

  3. 【VS开发】TCP服务端如何判断客户端断开连接

    原文出自:http://www.cnblogs.com/youxin/p/4056041.html 一篇文章:   最近在做一个服务器端程序,C/S结构.功能方面比较简单就是client端与serve ...

  4. 客户端验证、tcp协议中多个客户端的同时在线

    一.客户端验证 当在一个局域网内需要验证是否为合法的客户端连接时,我们需要写代码进行验证. Server端 import os import hmac import socket def auth(c ...

  5. 基于开源SuperSocket实现客户端和服务端通信项目实战

    一.课程介绍 本期带给大家分享的是基于SuperSocket的项目实战,阿笨在实际工作中遇到的真实业务场景,请跟随阿笨的视角去如何实现打通B/S与C/S网络通讯,如果您对本期的<基于开源Supe ...

  6. socket 客户端和服务端通信

    客户端要连接服务器:首先要知道服务器的IP地址.而服务器里有很多的应用程序,每一个应用程序对应一个端口号 所以客户端想要与服务器中的某个应用程序进行通信就必须要知道那个应用程序的所在服务器的IP地址, ...

  7. Python进阶----SOCKET套接字基础, 客户端与服务端通信, 执行远端命令.

    Python进阶----SOCKET套接字基础, 客户端与服务端通信, 执行远端命令. 一丶socket套接字 什么是socket套接字: ​ ​  ​ 专业理解: socket是应用层与TCP/IP ...

  8. springboot整合websocket实现客户端与服务端通信

    定义  WebSocket是通过单个TCP连接提供全双工(双向通信)通信信道的计算机通信协议.此WebSocket API可在用户的浏览器和服务器之间进行双向通信.用户可以向服务器发送消息并接收事件驱 ...

  9. Netty入门之客户端与服务端通信(二)

    Netty入门之客户端与服务端通信(二) 一.简介 在上一篇博文中笔者写了关于Netty入门级的Hello World程序.书接上回,本博文是关于客户端与服务端的通信,感觉也没什么好说的了,直接上代码 ...

随机推荐

  1. linux CentOS部署【minimal 】

    1.为什么选择CentOS不选择其他版本:http://www.cnblogs.com/TeemoHQ/p/6377260.html 2.准备的资源:VMware[官网下载],CentOS镜像 [阿里 ...

  2. 我是如何将网站全站启用Https的?-记录博客安装配置SSL证书全过程

    评论»   文章目录 为什么要Https 如何选择Https 安装部署SSL证书 平滑过渡Https 搜索引擎的响应 启用Https小结 正如大家所看到的,部落全站已经启用了Https访问了,连续几天 ...

  3. 关于将dede织梦data目录迁移出web目录

    关于将dede织梦data目录迁移出web目录织梦官方提供了一个教程,但是如果你是按照他们提供的教程做的话会出现很多问题.比如验证码问题,图片显示问题等等一大堆.织梦官方这种是很不负责任的,因为那个教 ...

  4. IIS  发布  dedecms  网站教程

    这里只是说明了配置 php 前后 iis 默认网站属性的变化,其实在配置完 php 后系统的环境变 量等也是发生了相应的变化了的, 这里就不一一列举了, 这些只有在你手动完成 php 的配置 之后才能 ...

  5. 急!!ftp登录错误,提示 530 not logged in,连接失败 ,,是怎么回事啊

    愤怒地青鸟 | 浏览 68533 次 发布于2017-04-11 00:44 最佳答案 核心提示:Ftp登陆不了是很经常碰到的事,很多人常常是不加分析就发贴询问.老实说,这样既浪费自己时间,又浪费别人 ...

  6. destoon标签

    http://blog.csdn.net/oYuHuaChen/article/details/54601509 ------------

  7. 【编程技巧】alert vs Ext.Msg.alert

    alert会阻塞程序的运行. Ext.Msg.alert是异步的,它的调用并不会停止浏览器中代码的执行.

  8. 阿里云Maven配置,Maven仓库配置,Maven镜像配置

    阿里云Maven配置,Maven仓库配置,Maven镜像配置 ======================== 蕃薯耀 2018年1月29日 http://www.cnblogs.com/fanshu ...

  9. Hive总结(七)Hive四种数据导入方式

  10. python_如何通过实例方法名字调用方法?

    案例: 某项目中,我们的代码使用的2个不同库中的图形类: Circle,Triangle 这两个类中都有一个获取面积的方法接口,但是接口的名字不一样 需求: 统一这些接口,不关心具体的接口,只要我调用 ...