红联Linux门户
Linux帮助

Linux套接字实现服务器和客户端通信

发布时间:2016-09-25 09:07:24来源:linux网站作者:Blank_CN
套接字是一种进程间通信的方法,不同于以往介绍的进程间通信方法的是,它并不局限于同一台计算机的资源,例如文件系统空间、共享内存或者消息队列。
套接字(socket)是一种通信机制,客户/服务器系统既可以在本地单机上运行,也可以在网络中运行。
 
套接字工作过程(服务器端)
首先,服务器应用程序通过socket系统调用创建一个套接字,它是系统分配给该服务器进程的类似文件描述符的资源,不能与其他进程共享。
其次,服务器进程使用bind系统调用给套接字命名。本地套接字的名字是linux文件系统的文件名,一般放在/tmp或者/usr/tmp目录下。
网络套接字的名字是与客户相连接的特定网络有关的服务标识符。此标识符允许linux将进入的针对特定端口号的连接转到正确的服务器进程。
接下来,服务器进程开始等待客户连接到这个命名套接字,调用listen创建一个等待队列以便存放来自客户的进入连接。
最后,服务器通过accept系统调用来接受客户的连接。此时,会产生一个与原有的命名套接字不同的新套接字,
它仅用于与这个特定的客户通信,而命名套接字则被保留下来继续处理来自其他客户的连接。
 
套接字工作过程(客户端)
调用socket创建一个未命名套接字,将服务器的命名套接字作为一个地址来调用connect与服务器建立连接。
一旦建立了连接,就可以像使用底层文件描述符那样来用套接字进行双向的数据通信。
套接字的特性由三个属性决定:
1.域(domain):指定套接字通信中使用的网络介质,包括地址格式。
最常用的有以下两种:
AF_INET,即互联网络,基于IP协议,并且每个服务对应一个端口号,套接字地址由IP地址+端口号决定;
AF_UNIX,基于本地机器,底层协议使用文件输入/输出,地址为绝对路径的文件名。
2.类型(type):一个套接字域可能有不同的通信方式,每种通信方式有不同的特性。
AF_UNIX域的套接字没有通信方面的问题,因为其基于文件系统,提供了一个可靠的双向通信路径。
AF_INET域中,需要注意底层网络的特性
流套接字:由类型SOCK_STREAM指定,基于TCP/IP实现,提供一个有序、可靠、双向字节流的连接,发送的数据不会丢失、乱序、重复。大的消息会被分块、传输、重组,很像一个文件流。
数据报套接字:由SOCK_DGRAM指定,基于UDP/IP协议,不建立和维持可靠连接,开销小,服务器崩溃不需要
客户端重启,因为基于数据报的服务器不保留连接信息。
3.协议(protocol):我们重点讨论UNIX网络套接字和文件系统套接字,不需要选择特定协议,只要默认值(0)即可。
 
下面的程序实现了服务器和单客户端的通信:
 
服务器端程序:
#include <sys/types.h>  
#include <sys/socket.h>  
#include <stdio.h>  
#include <netinet/in.h>  
#include <arpa/inet.h>  
#include <sys/un.h>  
#include <unistd.h>  
int main()  
{  
int server_sockfd, client_sockfd;  
int server_len, client_len;  
struct sockaddr_in server_address;  
struct sockaddr_in client_address;  
server_sockfd = socket(AF_INET, SOCK_STREAM, 0);  
server_address.sin_family = AF_INET;  
server_address.sin_addr.s_addr = inet_addr("127.0.0.1");  
server_address.sin_port = 3333;  
server_len = sizeof(server_address);  
bind(server_sockfd, (struct sockaddr*)&server_address, server_len);  
listen(server_sockfd, 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);  
}  
}  
 
客户端程序:
#include <sys/types.h>  
#include <sys/socket.h>  
#include <stdio.h>  
#include <netinet/in.h>  
#include <arpa/inet.h>  
#include <sys/un.h>  
#include <unistd.h>  
int main()  
{  
int sockfd;  
int len;  
struct sockaddr_in address;  
int result;  
char ch = '0';  
sockfd = socket(AF_INET, SOCK_STREAM, 0);  
address.sin_family = AF_INET;  
address.sin_addr.s_addr = inet_addr("127.0.0.1");  
address.sin_port = 3333;   
len = sizeof(address);  
result = connect(sockfd, (struct sockaddr*)&address, len);  
if(result== -1)   
{  
perror("oops: client1");  
exit(1);  
}  
while(ch != '#')  
{  
printf("input a char sent to server('#' to end):\n");  
scanf("%c", &ch);  
write(sockfd, &ch, 1);  
read(sockfd, &ch, 1);  
printf("char from server = %c\n", ch);  
}  
close(sockfd);  
exit(0);  
}  
 
运行结果如下:
Linux套接字实现服务器和客户端通信
 
本文永久更新地址:http://www.linuxdiyf.com/linux/24456.html