套接字socket--概念和实例

套接字 socket

套接字概念

套接字是一种进程间通信的方法,不同于以往介绍的的进程通信方法的是,它并不局限于同一台计算机的资源,例如共享内容或者消息队列。

一台机器上的进程可以使用套接字与另一台机器上的进程通信。因此客户与服务器可以分散到网络中。

同一台机器的进程间也可以用套接字通信。

套接字的工作过程(服务器端)

首先,服务器应用程序通过socket系统调用创建一个套接字,它是系统分配给该服务器进程的类似文件描述符的资源,不能与其他进程共享。

其次,服务器进程使用bind系统调用个套接字命名。

接下来,服务器进程开始等待客户连接到这个命名套接字,调用listen创建一个等待队列,以使存放来自客户的进入连接。

最后,服务器通过accept系统调用来接受客户的连接。此时,会产生一个与原有的命名套接字不同的新套接字,它仅用于与这个特定的客户端,而命名套接字则被保留下来继续处理来自其他客户的连接。

套接字的工作工程(客户端)

调用socket创建一个未命名套接字,将服务器的命名套接字作为一个地址来调用connect与服务器建立连接。

一旦建立了连接,就可以像使用底层文件描述符那样来用套接字进行双向的数据通信。

套接字的属性

套接字的特性由三个属性决定:

域(domain):指定套接字通信中使用的网络介质,包括地址格式。

  • AF_INET,即互联网络,基于IP协议,并且每个对应一个端口号,套接字地址由IP地址+端口号决定

类型(type)

  • 流套接字:由类型SOCK_STREAM指定,基于TCP/IP实现,提供一个有序、可靠、双向字节流的连接,发送的数据不会丢失、乱序、重复。大的消息会被分块、传输、重组,很像一个文件流。
  • 数据报套接字:由SOCK_DGRAM指定,基于UDP/IP协议,不建立和维持可靠连接,开销小,服务器崩溃不需要客户端重启,因为基于数据报的服务器不保留连接信息

协议(protocol)

套接字举例

客户端程序:创建一个未命名的套接字,然后把它连接到服务器套接字server_socket上,向服务器写一个字符,再读回经服务器处理后的一个字符。

服务器端程序:首先创建一个服务器套接字,绑定一个名字,然后创建一个监听队列,接收来自客户程序的连接。

client1.c

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/un.h>
#include <unistd.h>

int main()
{
	int sockfd;
	int len;
	struct sockaddr_un address;
	int result;
	char ch = 'A';
	sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
	//根据服务器的情况设定连续地址
	address.sun_family = AF_UNIX;
	strcpy(address.sun_path, "server_socket");
	len = sizeof(address);

	result = connect(sockfd, (struct sockaddr *)&address, len);
	if (result == -1)
	{
		perror("oops:client1");
		exit(1);
	}
	write(sockfd, &ch, 1);
	read(sockfd, &ch, 1);
	printf("char from server = %c\n", ch);
	close(sockfd);
	exit(0);
}

server1.c

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <sys/un.h>
#include <unistd.h>

int main()
{
	int server_sockfd, client_sockfd;//定义套接字标识符
	int server_len, client_len;//地址长度
	struct sockaddr_un server_address;
	struct sockaddr_un client_address;
	unlink("server_socket");//如果当前目录有叫做server_socket的文件,则删掉
	server_sockfd = socket(AF_UNIX, SOCK_STREAM, 0);//采用字节流方式,默认协议
	server_address.sun_family = AF_UNIX;
	strcpy(server_address.sun_path, "server_socket");
	server_len = sizeof(server_address);
	bind(server_sockfd, (struct sockaddr *)&server_address, server_len);
	listen(server_sockfd, 5);//创建长度为5的监听队列
	while(1)//等待客户端连接的到来
	{
		char ch;
		printf("server waiting\n");
		client_len = sizeof(client_address);//获取客户端的地址长度
		//服务器进程阻塞自身,知道有客户端请求建立连接,此时生成一个新的套接字,并返回新套接子的描述符,用此新套接字与客户进行通信
		client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_address, &client_len);
		read(client_sockfd, &ch, 1);
		ch++;
		write(client_sockfd, &ch, 1);
		close(client_sockfd);
	} 
}

猜你喜欢

转载自blog.csdn.net/xiaodingqq/article/details/83053990