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

原理:客户端只要一连上服务器,立马给服务器发送用户名,然后在服务端将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. Java高并发秒杀系统API之SSM框架集成swagger与AdminLTE

    初衷与整理描述 Java高并发秒杀系统API是来源于网上教程的一个Java项目,也是我接触Java的第一个项目.本来是一枚c#码农,公司计划部分业务转java,于是我利用业务时间自学Java才有了本文 ...

  2. Mac 终端 shell 公钥失效解决办法

    mac的终端下面使用ssh user@localhost输入密码不能正常登录解决   今天回来后发现系统突然很奇怪,以前在mac的终端下面使用ssh user@localhost输入密码就可以连接到远 ...

  3. 解决spring定时任务执行2次和tomcat部署缓慢的问题

    spring定时任务执行2次 问题重现和解析 最近使用quartz定时任务框架,结果发现开发环境执行无任何问题,部署到服务器上后,发现同一时间任务执行了多次.经过搜索发现是服务器上tomcat的配置文 ...

  4. Switch 语句

    如果您希望有选择地执行若干代码块之一,请使用 Switch 语句. 使用 Switch 语句可以避免冗长的 if..elseif..else 代码块. 语法 工作原理: 对表达式(通常是变量)进行一次 ...

  5. wamp apache无法启动的解决方法

    作者 grunmin 2014.03.12 14:44* 字数 535 阅读 22167评论 9喜欢 5 如题,近日在安装wamp的时候出现了apache无法启动的情况.wamp图标一直显示橙色.网上 ...

  6. 邓_PHP面试【001】

    1.双引号和单引号的区别 双引号解释变量,单引号不解释变量 双引号里插入单引号,其中单引号里如果有变量的话,变量解释 双引号的变量名后面必须要有一个非数字.字母.下划线的特殊字符,或者用{}讲变量括起 ...

  7. python3 第六章 - 条件判断

    Python条件语句是通过一条或多条语句的执行结果(True或者False)来决定执行的代码块. 条件语句的执行过程,如下图: 条件语句,又称为if语句,它的完整语法如下: if 条件1: 语句块1 ...

  8. 提示让IE8以下版本的浏览器去更新浏览器

    需求: 强制让IE进行页面渲染时候,用最新的方式渲染,并提示让IE8以下的版本去更新浏览器并给一个连接地址 那,如何满足? <!DOCTYPE html> <html lang=&q ...

  9. iterator_category

    /* * 迭代器类型 * 1. input ierator * 2. write iterator * 3. forward iterator 在迭代器所形成的区间上进行读写操作 * 4. bidir ...

  10. TDD入门demo

    OK,前面的博客整理了一系列的junit相关内容,这里举一个例子TDD实际的编码例子,不管实际编码中是否使用TDD,个人觉得这种思想必须要有. 我们不一定在写业务代码之前一定要说是把测试类都写出来,至 ...