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

原理:客户端只要一连上服务器,立马给服务器发送用户名,然后在服务端将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. UE4 Xml读写

    UE4自带一个XmlParser,可以很方便的实现Xml的读写. 1,在PublicDependencyModuleNames.AddRange中添加XmlParser. 2,include XmlP ...

  2. Ajax beforeSend和complete 方法

    http://blog.csdn.net/chenjianandiyi/article/details/52274591 .ajax({ beforeSend: function(){ // Hand ...

  3. 小白的Python之路 day5 logging模块

    logging模块的特点及用法 一.概述 很多程序都有记录日志的需求,并且日志中包含的信息即有正常的程序访问日志,还可能有错误.警告等信息输出,python的logging模块提供了标准的日志接口,你 ...

  4. NSLog( @"%@", i );

    NSLog( @"%@", i );  %@需要显示对象,所以这个i必须是个对象类型.

  5. python爬虫知乎

    在之前写过一篇使用python爬虫爬取电影天堂资源的博客,重点是如何解析页面和提高爬虫的效率.由于电影天堂上的资源获取权限是所有人都一样的,所以不需要进行登录验证操作,写完那篇文章后又花了些时间研究了 ...

  6. Redis集群方案怎么做?大牛给你介绍五种方案!

    Redis集群方案 Redis数据量日益增大,而且使用的公司越来越多,不仅用于做缓存,同时趋向于存储这块,这样必促使集群的发展,各个公司也在收集适合自己的集群方案,目前行业用的比较多的是下面几种集群架 ...

  7. python_10_文件操作

    文件操作逻辑? 打开文件,赋值给一个对象 用对象操作文件 关闭文件 如何打开文件? 在windows中,默认格式gbk,python3.x默认unicode(utf-8),要指定编码值 语法: f = ...

  8. Python 正则表达式 (python网络爬虫)

    昨天 2018 年 01 月 31 日,农历腊月十五日.20:00 左右,152 年一遇的月全食.血月.蓝月将今晚呈现空中,虽然没有看到蓝月亮,血月.月全食也是勉强可以了,还是可以想像一下一瓶蓝月亮洗 ...

  9. 通过反编译深入理解Java String及intern(转)

    通过反编译深入理解Java String及intern 原文传送门:http://www.cnblogs.com/paddix/p/5326863.html 一.字符串问题 字符串在我们平时的编码工作 ...

  10. curl错误码说明

    1.得到错误码 $errno=curl_errno($ch); if($errno!=0){ -- } 2.错误码说明 <?php return [ '1'=>'CURLE_UNSUPPO ...