client 和 server 通讯实例(TCP协议使用 select 函数)
先用标准输入(键盘输入)演示 select 函数的使用:
/****** sample.c for Linux ******/
#include
#include
#include
#define STDIN 0
int main()
{
int n, flag;
char buf[80];
fd_set fds;
struct timeval tv;
int fd = STDIN;
printf("type \"eXit\" to exit.\n");
flag = 1;
while(1 == flag)
{
tv.tv_sec=10;
tv.tv_usec=0;
FD_ZERO(&fds);
FD_SET(fd,&fds);
//[] switch(select(fd+1, &fds, NULL, NULL, &tv))
switch(select(FD_SETSIZE, &fds, NULL, NULL, &tv))
{
case -1: // select错误
printf("返回错误。\n");
flag = -1;
break;
case 0: //再次轮询
printf("超时。\n");
break;
default:
if(FD_ISSET(fd, &fds))
{
fgets(buf, 20, stdin);
n = strlen(buf);
if('\n' == buf[n-1])
buf[n-1] = '\0';
printf("数据:%s\n", buf);
if(0 == strcmp(buf, "eXit")) //退出程序?
{
flag = 0;
break;
}
}
break;
}
}
return flag;
}
[root@localhost ~]# ./sample
type "eXit" to exit.
asdf
数据:asdf
asdfg
数据:asdfg
sdf
数据:sdf
超时。
超时。
eXit
数据:eXit
[root@localhost ~]#
服务器端代码(Linux系统,TCP协议):
/****** server.c for Linux ******/
#include
#include
#include
#include
#include
#define STDIN 0
int main(int argc, char *argv[])
{
int n, flag;
char buf[1024];
fd_set fds;
struct timeval tv;
struct sockaddr_in client_addr;
int sockfd, fd, sin_size;
int port;
struct sockaddr_in addr;
int fdstd = STDIN;
if(argc != 3)
{
fprintf(stderr,"Usage:%s ipaddr port\a\n",argv[0]);
return -1;
}
if((port = atoi(argv[2])) < 0)
{
fprintf(stderr,"Usage:%s ipaddr port\a\n",argv[0]);
return -1;
}
bzero(&addr,sizeof(struct sockaddr_in));
addr.sin_family=AF_INET;
addr.sin_addr.s_addr=inet_addr(argv[1]);//htonl(INADDR_ANY);
addr.sin_port=htons(port);
if((sockfd=socket(AF_INET,SOCK_STREAM,0)) == -1)
{
fprintf(stderr,"Socket error:%s\n\a",strerror(errno));
return -1;
}
if(bind(sockfd,(struct sockaddr *)(&addr),sizeof(struct sockaddr)) == -1)
{
fprintf(stderr,"Bind error:%s\n\a",strerror(errno));
return -1;
}
if(listen(sockfd,5) == -1)
{
fprintf(stderr,"Listen error:%s\n\a",strerror(errno));
return -1;
}
sin_size=sizeof(struct sockaddr_in);
fd = accept(sockfd,(struct sockaddr *)(&client_addr),&sin_size);
if(fd != -1)
{
printf("connection from %s, fd = %d\n", inet_ntoa(client_addr.sin_addr), fd);
}else
{
fprintf(stderr,"Accept error:%s\n\a",strerror(errno));
close(sockfd);
return 0;
}
printf("recv \"eXit\" to exit.\n");
flag = 1;
while(1 == flag)
{
tv.tv_sec=10;
tv.tv_usec=0;
FD_ZERO(&fds);
FD_SET(fd,&fds);
// switch(select(fd+1, &fds, NULL, NULL, &tv))
switch(select(FD_SETSIZE, &fds, NULL, NULL, &tv))
{
case -1: // select错误
printf("返回错误。\n");
flag = -1;
break;
case 0: //再次轮询
printf("超时。\n");
break;
default:
if(FD_ISSET(fd, &fds))
{
// 接收TCP数据。
n = recv(fd, buf, sizeof(buf), MSG_DONTWAIT); //非阻塞模式接收
buf[n] = '\0';
printf("from client[fd = %d]: %s\n", fd, buf);
if(0 == strcmp(buf, "eXit")) //退出程序?
{
flag = 0;
break;
}
}
break;
}
}
close(fd);
close(sockfd);
return 0;
}
服务端代码(Linux系统,UDP协议)
#include
#include
#include
#include
#include
#include
int main(int argc, char *argv[])
{
int len;
int sockfd, port, sin_size;
struct sockaddr_in addr; //服务器网络地址结构体
struct sockaddr_in remote_addr; //客户端网络地址结构体
char buf[1024]; //数据传送的缓冲区
if(argc != 3)
{
fprintf(stderr,"Usage:%s ipaddr port\a\n",argv[0]);
return -1;
}
if((port = atoi(argv[2])) < 0)
{
fprintf(stderr,"Usage:%s ipaddr port\a\n",argv[0]);
return -1;
}
bzero(&addr,sizeof(struct sockaddr_in));
addr.sin_family=AF_INET;
addr.sin_addr.s_addr=inet_addr(argv[1]);//htonl(INADDR_ANY);
addr.sin_port=htons(port);
/*创建服务器端套接字--IPv4协议,面向无连接通信,UDP协议*/
if((sockfd=socket(PF_INET, SOCK_DGRAM, 0)) < 0)
{
perror("socket");
return -1;
}
/* 将套接字绑定到网络地址上 */
if (bind(sockfd,(struct sockaddr *)&addr,sizeof(struct sockaddr)) < 0)
{
perror("bind");
return -1;
}
sin_size=sizeof(struct sockaddr_in);
printf("waiting for a packet...\n");
if((len = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&remote_addr,&sin_size)) < 0)
{
perror("recvfrom");
return -1;
}
printf("received packet from %s:\n", inet_ntoa(remote_addr.sin_addr));
buf[len]='\0';
printf("contents: %s\n",buf);
close(sockfd);
return 0;
}
客户端代码(Linux系统):
/****** client.c for Linux ******/
#include
#include
#include
#include
#include
int main(int argc, char *argv[])
{
int n, sockfd;
char buf[1024];
struct sockaddr_in server_addr;
struct hostent *host;
int port;
if(argc!=3)
{
fprintf(stderr,"Usage:%s serverIPaddr portNumber\a\n",argv[0]);
return -1;
}
if((host=gethostbyname(argv[1]))==NULL)
{
fprintf(stderr,"Gethostname error\n");
return -1;
}
if((port=atoi(argv[2]))<0)
{
fprintf(stderr,"Usage:%s serverIPaddr portNumber\a\n",argv[0]);
return -1;
}
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
fprintf(stderr,"Socket Error:%s\a\n",strerror(errno));
return -1;
}
bzero(&server_addr,sizeof(server_addr));
server_addr.sin_family=AF_INET;
server_addr.sin_port=htons(port);
server_addr.sin_addr=*((struct in_addr *)host->h_addr);
if(connect(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1)
{
fprintf(stderr,"Connect Error:%s\a\n",strerror(errno));
}else
{
printf("type \"eXit\" to exit.\n");
while(1)
{
// 接收标准输入数据。
fgets(buf, sizeof(buf), stdin);
n = strlen(buf);
if('\n' == buf[n-1])
buf[n-1] = '\0';
if(send(sockfd, buf, strlen(buf), MSG_NOSIGNAL) < 0)
{
fprintf(stderr,"send error:%s\n", strerror(errno));
break;
}
if(0 == strcmp(buf, "eXit")) //退出程序?
break;
}
}
close(sockfd);
return 0;
}
/****** client.c for Windows ******/
#define WIN32_LEAN_AND_MEAN
#include
#include
#include
#include
int main(int argc, char **argv)
{
int n;
char buf[1024];
char *ipaddr;
unsigned short port;
struct sockaddr_in server;
WSADATA wsaData;
SOCKET conn_socket;
if(argc!=3)
{
fprintf(stderr,"Usage:%s serverIPaddr portNumber\a\n",argv[0]);
return -1;
}
if((port = atoi(argv[2])) <=0 )
{
fprintf(stderr,"Usage:%s serverIPaddr portNumber\a\n",argv[0]);
return -1;
}
if (WSAStartup(0x202,&wsaData) == SOCKET_ERROR)
{
fprintf(stderr,"WSAStartup failed with error %d\n",WSAGetLastError());
WSACleanup();
return -1;
}
ipaddr = argv[1];
memset(&server, 0, sizeof(server));
server.sin_family=AF_INET;
server.sin_port=htons(port);
server.sin_addr.s_addr=inet_addr(ipaddr);
conn_socket = socket(AF_INET, SOCK_STREAM, 0); /* Open a socket */
if (conn_socket < 0 )
{
fprintf(stderr,"Client: Error Opening socket: Error %d\n", WSAGetLastError());
WSACleanup();
return -1;
}
if (connect(conn_socket,(struct sockaddr*)&server,sizeof(server)) == SOCKET_ERROR)
{
fprintf(stderr,"connect() failed: %d\n",WSAGetLastError());
WSACleanup();
return -1;
}
printf("type \"eXit\" to exit.\n");
while(1)
{
//fgets(buf, sizeof(buf), stdin);
gets(buf);
n = strlen(buf);
if('\n' == buf[n-1])
buf[n-1] = '\0';
if(send(conn_socket, buf, strlen(buf), 0) < 0)
{
fprintf(stderr,"send error:%s\n", strerror(errno));
break;
}
if(0 == strcmp(buf, "eXit"))
break;
}
closesocket(conn_socket);
WSACleanup();
return 0;
}
执行结果示例:
--- 服务器端 ---
[root@localhost ~]# ./server 192.168.0.19 3560
connection from 192.168.0.19, fd = 4
recv "eXit" to exit.
from client[fd = 4]: sdf
超时。
超时。
from client[fd = 4]: 1234abc
超时。
from client[fd = 4]: eXit
[root@localhost ~]#
--- 客户端 ---
[root@localhost ~]# ./client 192.168.0.19 3560
type "eXit" to exit.
sdf
1234abc
eXit
[root@localhost ~]#