Linux网络编程



如果你想进入Linux神奇的网络编程世界,请跟笔者来,在学习之前,笔者只需要你拥有一定的C语言编程知识,就足够了。笔者会讲述编写网络程序需要的基本知识。

  所谓网络,在软件人员的观点来看,就是很多的用物理链路(比如,以太网,无线网络)连在一起的计算机,并且安装有网络程序。就像打电话,我们需要知道对方的号码一样,网络程序也需要知道要和那台计算机通讯,在这里,就是计算机的网络接口所拥有的IP地址。其实,一个完整的网络程序拥有两个独立的程序,他们分别运行在两个计算机上,一个是网络通讯的服务器端,一个是网络通讯的客户端,就像打电话,需要一个打电话的,还要一个接电话的是一样的,所以,我们需要编写两个程序,才是完整的网络通讯程序,我们熟悉的OutLook,FOXMAIL等都是网络程序中的客户端程序,而Apache,QMail等便是服务器端程序。只是往往,网络程序的客户端和服务器端之间有一定的通讯交互协议,比如SMTP,POP3,HTTP,FTP等,对于我们网络程序的编写者来说,他们就规定了通用的交互协议,这些协议规定了客户端,服务器端应该完成的工作,所以,编写好网络程序还需要理解好协议,不过,一般说来,我们用不着自己写协议,有很多的协议,我们可以使用的,都有RFC文档来说明了,你可以在网络上找到各种协议的RFC.

  当然,我们现在将要开始编写的第一个网络程序,虽然非常简单,但是却可以很清楚的说明大部分编写网络程序需要的基本概念,好了先让我们看看网络程序的TCP服务器端的编写步骤:
1. 首先,你需要创建一个用于通讯的套接口,一般使用socket调用来实现。这等于你有了一个用于通讯的电话:)

2. 然后,你需要给你的套接口设定端口,相当于,你有了电话号码。这一步 一般通过设置网络套接口地址和调用bind函数来实现。

3. 调用listen函数使你的套接口成为一个监听套接字。 以上三个步骤是TCP服务器的常用步骤。

4. 调用accept函数来启动你的套接字,这时你的程序就可以等待客户端的连接了。

5. 处理客户端的连接请求。

6. 终止连接。

  现在让我们来看看网络程序客户端的编程步骤:
1. 和服务器的步骤一样。

2. 通过设置套接口地址结构,我们说明,客户端要与之通讯的服务器的IP地址和端口。

3. 调用connect函数来连接服务器。

4. 发送或者接收数据,一般使用send和recv函数调用来实现。

5. 终止连接。

  以上的步骤,是比较普遍的,我们可以从中看出,编写网络程序是很有意思的,同时,也不是非常复杂,当然,这不包括,高难度的东西:-),下次,我会给出一个简单的服务器和一个客户机程序。
今天,我给出的代码包括一个服务器,和一个客户机程序,但是省略了很多代码, 比如说错误处理代码,这样做主要是为了使网络编程的主线清楚,所以,这两个程序谈不上网络安全性,和稳定性,这些是以后的话题。但是对于基本理解 网络编程已经足够了。我会在下次给出一个完整可运行的程序。下面我会详细 解释程序的步骤:
先要包括一部分网络编程必须的头部文件:
#include
#include
#include
#include
int main(int argc,char *argv[])
{
int listensock,connsock; /定义两个socket套接字,一个用于监听,一个用于通讯
struct sockaddr_in serveraddr; /定义网络套接字地址结构
const char buff[] = "Hello! Welcome here!
"; /定义要发送的数据缓冲区;
listensock = socket(AF_INET,SOCK_STREAM,0); /创建一个套接字,用于监听
bzero(&serveraddr,sizeof(servaddr)); /地址结构清零
serveraddr.sin_family = AF_INET; /指定使用的通讯协议族
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); /指定接受任何连接,因为服务器不知道谁会要求连接
serveraddr.sin_port = htons(5000); /指定监听的端口
bind(listensock,(sockaddr *)&serveraddr,sizeof(serveraddr)); /给套接口邦定地址
listen(listensock,1024); /开始监听
connsock = accept(listensock,(sockaddr *)NULL, NULL); /建立通讯的套接字,accept函数,等待客户端程序使用connect函数的连接
send(connsock,buff,sizeof(buff), 0); /向客户端发送数据
close(connsock); /关闭通讯套接字
close(listensock); /关闭监听套接字
}
这是客户端的程序:
int main(int argc,char **argv)
{
 char recvbuff[100]; /定义要接收的数据缓冲区
 int sockfd; /定义一个socket套接字,用于通讯
 struct sockaddr_in serveraddr;/定义网络套接字地址结构
 if(argc != 2){
  printf("Usage: echo ip地址");
 exit(0);
}
sockfd = socket(AF_INET,SOCK_STREAM,0); /创建一个套接字
 bzero(&serveraddr,sizeof(serveraddr));
 serveraddr.sin_family = AF_INET; /指定使用的通讯协议族
 serveraddr.sin_port = htons(5000);/指定要连接的服务器的端口
 inet_pton(AF_INET, argv[1], &serveraddr.sin_addr);
 connect(sockfd,(sockaddr *)&serveraddr,sizeof(serveraddr)); /连接服务器
 recv(sockfd,recvbuff,sizeof(recvbuff),0); /接收服务器的数据
 printf("%s
",recvbuff); /打印接收到的数据
  close(sockfd); /关闭套接字
}
这两个程序运行后,当客户端连接到服务器后,将接收到服务器传来的字符串Hello! Welcome here!,不过,程序调试的任务还得又你自己要完成。
你想知道著名的oicq使用的是什么技术来收发消息的吗?今天,我给出的两个程序,一个服务器 和一个客户端程序,便能告诉你,其中的基本技术,当然,我指的不包括,它的界面是怎样做的:)
  这两个程序使用的是UDP套接字编程,上一次给出的其实是使用TCP套接字编程,你自己可以先分析 一下,他们的异同点,我会在下一次,分析这两种编程的区别。
这是发送数据的程序:
/*头部文件包括网络需要的和基本输入输出需要的*/
#include #include
#include
#include
#include
int port = 5500;
void main()
{
 int sockfd;
 int count = 0;
 int flag;
 char buf[80];
 struct sockaddr_in address;
 sockfd = socket(AF_INET, SOCK_DGRAM, 0); //看到不同的地方了吗?
 memset(&address, 0, sizeof(address));
 address.sin_family = AF_INET;
 address.sin_addr.s_addr = inet_addr("127.0.0.1");
 address.sin_port = htons(port);
 flag = 1;
 do{
  sprintf(buf,"Packet %d
", count);
  if(count > 30){
  sprintf(buf,"over
");
  flag = 0;
  }
  sendto(sockfd,buf,sizeof(buf),0,(struct sockaddr *)&address, sizeof(address)); // 发现了吗使用的函数不一样,它也是发送数据
  count++;
 }while (flag);
}
这是接收数据的程序:
#include
#include
#include
#include
#include
char *hostname = "127.0.0.1"; //这个特殊的ip表示本的计算机
void main()
{
  int sinlen;
  int port = 8080;
  char message[256];
  int sockfd;
  struct sockaddr_in sin;
  struct hostent *server_host_name; // hostent结构有着机器的名字等信息
  server_host_name = gethostbyname("127.0.0.1"); // 这个函数用来得到“127.0.0.1”的主机名字,也就是本机的名字
  bzero(&sin,sizeof(sin));
  sin.sin_family = AF_INET;
  sin.sin_addr.s_addr = htonl(INADDR_ANY);
  sin.sin_port = htons(port);
  sockfd = socket(PF_INET,SOCK_DGRAM,0); //这里也不一样
  bind(sockfd,(struct sockaddr *)&sin,sizeof(sin));
    while(1){
     sinlen = sizeof(sin);
     recvfrom(sockfd,message,256,0, (struct sockaddr *)&sin,&sinlen);// 它是接受数据的函数
     printf("
Data come from server:
%s
",message);
     if(strncmp(message,"over",4) ==0)break;
    }
    close(sockfd);
}
  
      当你编译调试通过了后,在一个窗口,运行接收程序,一个窗口运行发送程序,你就可以看到数据被创送了。网络程序是可以在本地机器上,使用两个不同的窗口来运行,模拟客户端和服务器的
今天,笔者会解释网络编程中非常重要的两个概念:TCP编程和UDP编程,这是真真进入网络编程的灿烂世界必须深入理解的部分。

  首先,我们必须明白,一般操作系统包括Windows,Linux,UNIX,他们提供的供应用程序员使用的编程接口,一般的函数名字都差不多。不同的是,他们的操作系统对这些函数(也可以说是系统调用)的实现细节不尽相同,因此各种操作系统,在提供网络服务的时候,就存在着诸如速度、效率及稳定性的差别。
  那么,就网络编程的套接口字的选则来看,一样存在着以上的差别。也就是说,你选择TCP套接字和选择UDP编程,在传输数据时,一样有着速度、效率及稳定性的差别。首先,明白这一点,对于开始网络编程是非常重要的。

  TCP套接字,操作系统向你提供的是一个稳定的数据通路,从程序员的角度来看,你只需要明白,当你使用TCP编程时,如果你调用 的发送数据函数,比如send()函数,它的返回成功,那么表示,系统发送出的数据肯定被通讯的对方准确接收到了。而UDP套接字,操作系统给你提供的是一个不稳定的,无连接的数据通路,所以当你

相关内容

    暂无相关文章