经典的在同一台主机上两个进程或线程之间的通信通过以下三种方法
这里有许多其他的方法,但是上面三中是非常经典的进程间通信。
但是你有曾想过怎样跨越两台主机进行通信呢?
例如,当你浏览一个网站时,在你的主机上,运行的是你的浏览器,而在远程的系统上,运行的是网络服务器。因此这也是一个进程间的交流,他们彼此之间是通过套接字进行通信的,这也是本文的重点。
从外行的角度来看,一个套接字是一个网络上的通信系统的终点。再精确的说就是套接字是一个系统的地址和端口的组合。因此,在每个系统中,存在一个套接字与套接字在网络上的其他系统交互。本地系统的socket和远程系统的socket的组合又称“四元”或“四元组(four tuple)”。两个进程运行在不同的系统间的连接可以通过他们的四元组唯一标识。
有两种类型的网络通信模型:
而OSI是一个理论模型,TCP/IP网络模型才是最流行和用的最广的模型。
在我们的TCP/IP基础文章中解释说,在TCP/IP网络模型下发生的通信在形式上表现为客户端-服务器架构形式。即客户端开始通信和服务器建立一个连接。
套接字可以使用在许多语言中,如Java、C++等,但在这篇文章中,我们将了解在其在最纯净的形式下的套接字通信(C语言下的)。
让我们创建一个连续运行的服务器,并在客户端连接到它的时候发送日期和时间。
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
int main(int argc, char *argv[])
{
int listenfd = 0, connfd = 0;
struct sockaddr_in serv_addr;
char sendBuff[1025];
time_t ticks;
listenfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&serv_addr, '0', sizeof(serv_addr));
memset(sendBuff, '0', sizeof(sendBuff));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(5000);
bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
listen(listenfd, 10);
while(1)
{
connfd = accept(listenfd, (struct sockaddr*)NULL, NULL);
ticks = time(NULL);
snprintf(sendBuff, sizeof(sendBuff), "%.24s\r\n", ctime(&ticks));
write(connfd, sendBuff, strlen(sendBuff));
close(connfd);
sleep(1);
}
}
在上述代码中,我们创建了一个服务器,在代码中:
三次握手是用来创建远程TCP连接的过程,我将会很快发一个关于TCP协议理论层面的帖子。
最终,我们完成了运行服务器的例子。
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
int sockfd = 0, n = 0;
char recvBuff[1024];
struct sockaddr_in serv_addr;
if(argc != 2)
{
printf("\n Usage: %s <ip of server> \n",argv[0]);
return 1;
}
memset(recvBuff, '0',sizeof(recvBuff));
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("\n Error : Could not create socket \n");
return 1;
}
memset(&serv_addr, '0', sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(5000);
if(inet_pton(AF_INET, argv[1], &serv_addr.sin_addr)<=0)
{
printf("\n inet_pton error occured\n");
return 1;
}
if( connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
printf("\n Error : Connect Failed \n");
return 1;
}
while ( (n = read(sockfd, recvBuff, sizeof(recvBuff)-1)) > 0)
{
recvBuff[n] = 0;
if(fputs(recvBuff, stdout) == EOF)
{
printf("\n Error : Fputs error\n");
}
}
if(n < 0)
{
printf("\n Read error \n");
}
return 0;
}
在上述的程序中,我们创建了客户端来连接到服务器端并且从服务器端接收日期和时间。在上述的代码中:
现在执行客户机如下:
$ ./newsc 127.0.0.1
Sun Dec 18 22:22:14 2011
可以看到,我们成功的从服务器端得到了日期和时间。我们需要把服务器端的IP地址当参数发送过去来运行这个例子。如果你在一台机器上运行了客户机端和服务器端来测试,使用上述例子中的loop back ip。
本人英语水平有限,翻译有所偏差,请查看原文。
原文地址:
C Socket Programming for Linux with a Server and Client Example Code