socket实现全双工通信
客户端:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/wait.h>
#include <pthread.h>
#include <semaphore.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <arpa/inet.h>
#define IP "127.0.0.1" //服务器IP地址
#define PORT 7268 // 服务器端口号
int sockfd;
void* run(void* arg)
{
char wbuf[128];
while(1)
{
//接收服务器发来的信息
bzero(wbuf,sizeof(wbuf));
recv(sockfd,wbuf,sizeof(wbuf),0);
printf("\033[1;32;10m\033[16D收到服务器的信息为:\033[0m%s\n",wbuf);
}
}
int main(int argc, const char *argv[])
{
//1.创建套接字:用于接收客户端链接请求
sockfd=socket(AF_INET,SOCK_STREAM,0);
if(sockfd==-1)
{
perror("socket error");
return -1;
}
printf("socket success sockfd=%d\n",sockfd); //3
//2.绑定IP地址和端口号
//3.连接服务器
//3.1填充要连接的服务器地址信息结构体
struct sockaddr_in sin;
sin.sin_family=AF_INET; //协议族
sin.sin_port=htons(PORT); //服务器端口号
sin.sin_addr.s_addr=inet_addr(IP); //服务器IP
//3.2连接服务器
if(connect(sockfd,(struct sockaddr*)&sin,sizeof(sin))==-1)
{
perror("connect error\n");
return -1;
}
printf("connect success\n");
pthread_t id;
pthread_create(&id,0,run,0);
pthread_detach(id);
//4.数据通信
char wbuf[128]=""; //用于接收信息
while(1)
{
//从终端获取数据
bzero(wbuf,sizeof(wbuf));
printf("\033[1;34;10m[客户端]请输入:\033[0m");
fgets(wbuf,sizeof(wbuf),stdin);
if(wbuf[strlen(wbuf)-1]=='\n')
wbuf[strlen(wbuf)-1]='\0';
if(strcmp(wbuf,"quit")==0)
{
break;
}
//将数据发送给服务器
send(sockfd,wbuf,strlen(wbuf),0);
}
//5.关闭套接字
close(sockfd);
return 0;
}
服务器端:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/wait.h>
#include <pthread.h>
#include <semaphore.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <arpa/inet.h>
#define IP "127.0.0.1" //服务器IP地址
#define PORT 7268 // 服务器端口号
int acceptfd;
void* run(void* arg)
{
char rbuf[128];
while(1)
{
//向客户端发送信息
bzero(rbuf,sizeof(rbuf)); //清空容器
printf("\033[1;33;10m[服务器端]请输入:\033[0m");
fgets(rbuf,sizeof(rbuf),stdin);
send(acceptfd,rbuf,strlen(rbuf),0);
}
}
int main(int argc, const char *argv[])
{
//1.创建套接字:用于接收客户端链接请求
int sockfd=socket(AF_INET,SOCK_STREAM,0);
if(sockfd==-1)
{
perror("socket error");
return -1;
}
printf("socket success sockfd=%d\n",sockfd); //3
//2.绑定IP地址和端口号
//2.1填充地址信息结构体
struct sockaddr_in sin;
sin.sin_family=AF_INET; //地址族
sin.sin_port=htons(PORT); //端口号
sin.sin_addr.s_addr=inet_addr(IP); //IP地址
//2.2绑定工作
if(bind(sockfd,(struct sockaddr*)&sin,sizeof(sin))==-1)
{
perror("bind error");
return -1;
}
printf("bind success!\n");
//3.将套接字设置为被动监听状态
if(listen(sockfd,128)==-1)
{
perror("listen error\n");
return -1;
}
printf("listen success!\n");
//4.阻塞等待客户端链接请求
//定义地址信息结构体用于接收客户端地址信息
struct sockaddr_in cin;
socklen_t socklen=sizeof(cin); //接收地址信息的长度
//返回一个数据交互的文件描述符
acceptfd=accept(sockfd,(struct sockaddr*)&cin,&socklen);
if(acceptfd==-1)
{
perror("accept error\n");
return -1;
}
printf("[\033[1;32;10m%s:%d]:已链接\033[0m \033[1;33;10macceptfd=%d\n\033[0m",\
inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),acceptfd);//IP Port client
pthread_t id;
pthread_create(&id,0,run,0);
pthread_detach(id);
//数据通信
char rbuf[128]=""; //用于接收信息
while(1)
{
//从套接字文件中读取信息
bzero(rbuf,sizeof(rbuf)); //清空容器
int ret=recv(acceptfd,rbuf,sizeof(rbuf),0);
if(ret==0)
{
printf("\033[1;33;10m客户端已下线\n\033[0m");
break;
}
else if(ret<0)
{
perror("recv");
return -1;
}
else
printf("\033[1;32;10m\033[17D[%s:%d]:\033[0m%s\n",\
inet_ntoa(sin.sin_addr),ntohs(cin.sin_port),rbuf);
}
//6.关闭套接字
close(sockfd);
close(acceptfd);
return 0;
}
结果:
多个客户端接入服务器端 (多线程实现并发)
服务器端:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/wait.h>
#include <pthread.h>
#include <semaphore.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <arpa/inet.h>
#define PORT 7268
#define IP "127.0.0.1"
void* run(void * arg)
{
int acceptfd =*(int *)arg;
char buf[128];
while(1)
{
//从套接字文件中读取信息
bzero(buf,sizeof(buf)); //清空容器
int ret=recv(acceptfd,buf,sizeof(buf),0);
if(ret==0)
{
printf("\033[1;33;10m客户端%d已下线\n\033[0m",acceptfd);
break;
}
else if(ret<0)
{
perror("recv");
return NULL;
}
else
printf("\033[1;32;10m\033[17D客户端%d发送的消息为:\033[0m%s\n",acceptfd,buf);
}
}
int main(int argc)
{
char buf[128];
int sockfd=socket(AF_INET,SOCK_STREAM,0);
if(sockfd==-1)
{
perror("socket");
return -1;
}
//2.绑定IP地址和端口号
//2.1填充地址信息结构体
struct sockaddr_in sin;
sin.sin_family=AF_INET; //地址族
sin.sin_port=htons(PORT); //端口号
sin.sin_addr.s_addr=inet_addr(IP); //IP地址
//2.2绑定工作
if(bind(sockfd,(struct sockaddr*)&sin,sizeof(sin))==-1)
{
perror("bind error");
return -1;
}
printf("bind success!\n");
//3.将套接字设置为被动监听状态
if(listen(sockfd,128)==-1)
{
perror("listen error\n");
return -1;
}
printf("listen success!\n");
while(1)
{
//4.阻塞等待客户端链接请求
//定义地址信息结构体用于接收客户端地址信息
struct sockaddr_in cin;
socklen_t socklen=sizeof(cin); //接收地址信息的长度
//返回一个数据交互的文件描述符
int acceptfd=accept(sockfd,(struct sockaddr*)&cin,&socklen);
printf("%d connect sucessifully!\n",acceptfd);
pthread_t id;
pthread_create(&id,0,run,&acceptfd);
pthread_detach(id);
}
close(sockfd);
return 0;
}