使用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程序.书接上回,本博文是关于客户端与服务端的通信,感觉也没什么好说的了,直接上代码 ...
随机推荐
- PhpStorm中报 “Cannot run program git.exe, 系统找不到指定的文件”
http://blog.csdn.net/lamp_yang_3533/article/details/52003021 在使用PhpStorm的GitHub或Git功能时,经常会出现以下错误信息: ...
- Codeforces 899 F. Letters Removing (二分、树状数组)
题目链接:Letters Removing 题意: 给你一个长度为n的字符串,给出m次操作.每次操作给出一个l,r和一个字符c,要求删除字符串l到r之间所有的c. 题解: 看样例可以看出,这题最大的难 ...
- spring boot项目编译出来的jar包如何更改端口号
执行的时候更改端口即可 . java -Dserver.port=9999 -jar boot.jar
- properties文件中中文不能显示或者中文乱码
1.properties 文件中文乱码问题 鼠标“右击”文件 => Resource => Text file encoding => UTF-8 2.properties 文件解析 ...
- uwsgi wsgi nginx centos7.2部署flask
请原谅我比较懒,直接粘贴onenote笔记了 方法一测试完成后,建议用方法三:uwsgi,ginx部署
- SpringMvc4.x--@ControllerAdvice注解
通过@ControllerAdvice.我们可以将对于控制器的全局配置放置在同一个位置,注解了@ControllerAdvice的类的方法可以使用@ExceptionHandler,@InitBind ...
- AMS常见问题
1.安装完AMS是否就可以实现直播点播了? 答:是的,ams运行后,就可以提供各种协议的直播输出地址,和点播地址:不过一般情况下客户还得需要另外的Web系统来配合使用,来完成对前台用户界面的友好化 ...
- Django 中 makemigrations、migrate时 No changes detected
Django创建的项目中,需要更改.增加.删除表中的某些属性,性急直接把之前数据库表删除了,之后再执行: python manage.py makemigrations python manage.p ...
- RequestParam\@ResponseBody
为什么不写 RequestParam 也能拿到参数 三种写法,test(String name), test(@RequestParam String name), test(@RequestPara ...
- MYSQL 5.7 修改密码、登录问题
mysql5.7 关于密码问题 报错: ERROR 1862 (HY000): Your password has expired. To log in you must change it usin ...