client 和 server 通讯实例(TCP协议使用 select 函数)

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; 
} 

客户端代码(Windows系统,需要 ws2_32.lib 库文件):

/****** 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 ~]#




你可能感兴趣的:(Linux,网络编程)