进程间的七种通信方式之-----(七)套接字( socket )

套接字( socket )

套接字( socket )也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同机器间的进程通信。

(1)服务器:server
创建套接字 socket( )
填充服务器网络信息结构体 sockaddr_in
将套接字与服务器网络信息结构体绑定 bind( )
将套接字设置为被动监听模式 listen( )
阻塞等待客户端的连接请求 accept( )
进行通信 recv( )/send( ) (read( )/write( ))

#include  //printf
#include  //inet_addr htons
#include 
#include  //socket bind listen accept connect
#include  //sockaddr_in
#include  //exit
#include  //close
#include 

#define N 128
#define errlog(errmsg) do{perror(errmsg);\
						  printf("%s -- %s -- %d\n", __FILE__, __func__, __LINE__);\
						  exit(1);\
						 }while(0)

int main(int argc, const char *argv[])
{
	int sockfd, acceptfd;
	struct sockaddr_in serveraddr, clientaddr;
	socklen_t addrlen = sizeof(serveraddr);
	char buf[N] = {};
	ssize_t bytes;

	if(argc < 3)
	{
		fprintf(stderr, "Usage: %s  \n", argv[0]);
		exit(1);
	}

	//第一步:创建套接字
	if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
	{
		errlog("fail to socket");
	}

	//第二步:填充服务器网络信息结构体
	//inet_addr:将点分十进制ip地址转化为网络字节序的整型数据
	//htons:将主机字节序转化为网络字节序
	//atoi:将数字型字符串转化为整型数据
	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, sizeof(serveraddr)) < 0)
	{
		errlog("fail to bind");
	}
	
	//第四步:将套件字设置为被动监听状态 
	if(listen(sockfd, 5) < 0)
	{
		errlog("fail to listen");
	}

	//第五步:阻塞等待客户端的连接请求
	if((acceptfd = accept(sockfd, (struct sockaddr *)&clientaddr, &addrlen)) < 0)
	{
		errlog("fail to accept");
	}

	//服务器知道客户端的信息
	printf("%s --> %d\n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));

	while(1)
	{
		if((bytes = recv(acceptfd, buf, N, 0)) < 0)
		{
			errlog("fail to recv");
		}
		else if(bytes == 0)
		{
			printf("NO DATA\n");
			exit(1);
		}
		else 
		{
			if(strncmp(buf, "quit", 4) == 0)
			{
				printf("The client is quited\n");
				break;
			}

			printf("client: %s\n", buf);

			strcat(buf, " *_*");
			
			if(send(acceptfd, buf, N, 0) < 0)
			{
				errlog("fail to send");
			}
		}
	}

	close(acceptfd);
	close(sockfd);
	
	return 0;
}

(2)客户端:client
创建套接字 socket( )
填充服务器网络信息结构体 sockaddr_in
发送客户端的连接请求 connect( )
进行通信 send( )/recv( )

#include  //printf
#include  //inet_addr htons
#include 
#include  //socket bind listen accept connect
#include  //sockaddr_in
#include  //exit
#include  //close
#include 

#define N 128
#define errlog(errmsg) do{perror(errmsg);\
						  printf("%s -- %s -- %d\n", __FILE__, __func__, __LINE__);\
						  exit(1);\
						 }while(0)

int main(int argc, const char *argv[])
{
	int sockfd;
	struct sockaddr_in serveraddr;
	socklen_t addrlen = sizeof(serveraddr);
	char buf[N] = {};

	if(argc < 3)
	{
		fprintf(stderr, "Usage: %s  \n", argv[0]);
		exit(1);
	}

	//第一步:创建套接字
	if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
	{
		errlog("fail to socket");
	}

	//第二步:填充服务器网络信息结构体
	//inet_addr:将点分十进制ip地址转化为网络字节序的整型数据
	//htons:将主机字节序转化为网络字节序
	//atoi:将数字型字符串转化为整型数据
	serveraddr.sin_family = AF_INET;
	serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
	serveraddr.sin_port = htons(atoi(argv[2]));

#if 0
	//客户端可以自己指定信息
	struct sockaddr_in clientaddr;
	clientaddr.sin_family = AF_INET;
	clientaddr.sin_addr.s_addr = inet_addr(argv[3]);
	clientaddr.sin_port = htons(atoi(argv[4]));

	if(bind(sockfd, (struct sockaddr *)&clientaddr, addrlen) < 0)
	{
		errlog("fail to bind");
	}
#endif
	//第三步:发送客户端的连接请求
	if(connect(sockfd, (struct sockaddr *)&serveraddr, addrlen) < 0)
	{
		errlog("fail to connect");
	}

	while(1)
	{
		fgets(buf, N, stdin);
		buf[strlen(buf) - 1] = '\0';

		if(send(sockfd, buf, N, 0) < 0)
		{
			errlog("fail to send");
		}

		if(strncmp(buf, "quit", 4) == 0)
		{
			printf("The client is quited\n");
			break;
		}

		if(recv(sockfd, buf, N, 0) < 0)
		{
			errlog("fail to recv");
		}

		printf("server: %s\n", buf);

	}

	close(sockfd);
	
	return 0;
}

你可能感兴趣的:(进程间通信,网络,socket,网络通信)