server
#include <stdio.h>
#include <string.h>
#include <unistd.h> //exit()
#include <stdlib.h> //
#include <sys/types.h> //socket()
#include <sys/socket.h> //socket()
#include <netinet/in.h> //struct sockaddr_in
#include <arpa/inet.h> //inet_addr
#include <string.h> //strlen()
#include <sys/select.h>
#include <sys/time.h>
#define ERR_LOG(errmsg) do{\
perror(errmsg);\
fprintf(stdout, "%s - %s - %d", __FILE__, __func__, __LINE__);\
exit(1);\
}while(0)
#define MAX 128
int main( int argc, char *argv[])
{
if( argc != 3 )
{
fprintf( stdout, "Usage:%s<IP><port>\n", argv[0]);
exit(1);
}
int sockfd, acceptfd; //套接字,sockfd负责连接,accept负责通信
struct sockaddr_in serveraddr, clientaddr; //服务器网络信息结构体,客户端网络信息结构体
socklen_t addrlen = sizeof(serveraddr); //网络信息结构体大小
char buf[MAX] = {0}; //用于通信存放数据
//创建套接字
if( (sockfd = socket( AF_INET, SOCK_STREAM, 0)) == -1 )
{
ERR_LOG("fail to socket");
}
//填充网络信息结构体
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
serveraddr.sin_port = htons(atoi(argv[2]));
//绑定套接字和网络信息结构体
if( bind( sockfd, (struct sockaddr *)&serveraddr, addrlen) == -1 )
{
ERR_LOG("fail to bind");
}
//设置套接字为监听状态
if( listen( sockfd, 5) == -1 )
{
ERR_LOG("fail to listen");
}
// 初始化表
fd_set readfds, tempfds;
FD_ZERO(&readfds);
FD_ZERO(&tempfds);
FD_SET(sockfd,&readfds);
FD_SET(0,&readfds);
int maxfd = sockfd;
int select_retval = 0;
int recv_retval = 0;
while(1)
{
tempfds = readfds;
if( (select_retval = select(maxfd + 1,&tempfds,NULL,NULL,NULL)) == -1 )
{
ERR_LOG("fail to select");
}
for(int i = 0; i < maxfd + 1; i++)
{
if(FD_ISSET(i,&tempfds))
{
if(i == sockfd)
{
if( (acceptfd = accept( sockfd, (struct sockaddr *)&clientaddr, &addrlen)) == -1 )
{
ERR_LOG("fail to accept");
}
printf("客户端已连接: <ip>:%s <port>:%d\n",inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));
FD_SET(acceptfd,&readfds);
maxfd = maxfd > acceptfd ? maxfd : acceptfd;
printf("maxfd = %d\n", maxfd);
}
else if(i == 0) // 广播
{
memset(buf,0,sizeof(buf));
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1] = 0;
for(int j = sockfd + 1; j < maxfd + 1; j++)
{
if(FD_ISSET(j,&readfds))
{
if(send(j,buf,sizeof(buf),0)<0)
{
ERR_LOG("fail to send");
return -1;
}
}
}
}
else
{
recv_retval = recv(i, &buf, sizeof(buf),0); // 如果发送方关闭套接字或者结束进程,recv的返回值是0
if( recv_retval == 0 )
{
FD_CLR(i, &readfds); // 从合集中清除文件描述符。
close(i); // 关闭文件描述符
printf("%d客户端已退出\n",i);
for(int j=maxfd;j>0;j--) // 刷新maxfd
{
if(FD_ISSET(j,&readfds))
{
maxfd = j;
break;
}
}
}
else
printf("%s %d:%s\n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port), buf);
}
}
}
}
return 0;
}
client
#include <stdio.h>
#include <string.h>
#include <unistd.h> //exit()
#include <stdlib.h> //
#include <sys/types.h> //socket()
#include <sys/socket.h> //socket()
#include <netinet/in.h> //struct sockaddr_in
#include <arpa/inet.h> //inet_addr
#include <sys/select.h>
#include <sys/time.h>
#define ERR_LOG(errmsg) do{\
perror(errmsg);\
fprintf(stdout, "%s - %s - %d", __FILE__, __func__, __LINE__);\
exit(1);\
}while(0)
#define MAX 128
int main( int argc, char *argv[])
{
if( argc != 3 )
{
fprintf( stdout, "Usage:%s<IP><port>\n", argv[0]);
exit(1);
}
int sockfd; //套接字,sockfd负责连接,accept负责通信
struct sockaddr_in serveraddr; //服务器网络信息结构体
socklen_t addrlen = sizeof(serveraddr); //网络信息结构体大小
char buf[MAX] = {0}; //用于通信存放数据
//1. 创建套接字
if( (sockfd = socket( AF_INET, SOCK_STREAM, 0)) == -1 )
{
ERR_LOG("fail to socket");
}
//2. 填充网络信息结构体
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
serveraddr.sin_port = htons(atoi(argv[2]));
//3. 请求连接
if( connect( sockfd, (struct sockaddr *)&serveraddr, addrlen) == -1 )
{
ERR_LOG("fail to connect");
}
//通信
fd_set readfds, tempfds;
FD_ZERO(&readfds);
FD_ZERO(&tempfds);
FD_SET(sockfd,&readfds);
FD_SET(0,&readfds);
int maxfd = sockfd;
int select_retval = 0;
int recv_retval = 0;
while(1)
{
tempfds = readfds;
if( (select_retval = select(maxfd + 1,&tempfds,NULL,NULL,NULL)) == -1 )
{
ERR_LOG("fail to select");
}
for(int i = 0; i < maxfd + 1; i++)
{
if(FD_ISSET(i,&tempfds))
{
if(i == 0)
{
memset(buf,0,sizeof(buf));
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1] = 0;
if(send(sockfd,buf,sizeof(buf),0)<0)
{
ERR_LOG("fail to send");
return -1;
}
}
else if(i == sockfd)
{
recv_retval = recv(i, &buf, sizeof(buf),0);
if( recv_retval == 0 )
{
ERR_LOG("服务器已关闭");
close(sockfd);
exit(1);
}
printf("收到服务器广播:%s\n",buf);
}
}
}
}
}