Simple proxy program development process (1)

Source: Internet
Author: User
Tags signal handler socket error
Article title: simple proxy program development process (1 ). Linux is a technology channel of the IT lab in China. Includes basic categories such as desktop applications, Linux system management, kernel research, embedded systems, and open source.
Abstract: A simple proxy program development process. This example mainly uses some programming technologies, such as socket programming, signals, processes, and some advanced unix socket programming topics. Of course, none of these are the main ones. what's important is to experience the market development method.
  
1. Introduction
  
Many people have read this article titled The Cathedral and the Bazaar written by Eric Steven Raymond. This article describes the differences between traditional development group development methods and Internet-based distributed development methods (linux development and GNU software development, based on a program development example, The author describes several important principles of The Bazaar development method.
  
However, many programmers in China still adopt traditional development methods when working, and it is difficult to experience these principles at work. This example gives you another process to experience these principles.
  
This example mainly uses some programming technologies, such as socket programming, signals, processes, and some advanced unix socket programming topics. Of course, none of these are the main ones. the important thing is to experience the market development method.
  
2. background for developing this proxy program
  
I am working in a closed network environment. My machine is in the LAN and connected to the external Internet using proxy. There are several unix servers as proxy servers and run squid as the http proxy, run socks as the socks 5 proxy. It should be said that this kind of treatment is not bad, :-). to browse the website, squid is enough. to run programs such as ICQ and OICQ, socks is enough. However, I encountered a very troublesome problem. in such a network environment, I could not use Outlook or other tools to receive emails from non-company email servers (for example, @ linuxaid.com.cn, @ 163.net, @ sina.com.cn, etc.); there is no way to use tools such as Gravity to collect discussions on USENET. Of course, there are some compromise methods. I can use socks-supported mail client software and newsgroup reading software in linux. However, this will inevitably cause some trouble (as I have done in fact). when I need to receive emails or read newsgroups, I must restart the machine to switch to the linux operating system, when I want to work, I have to restart the machine and switch it to the windows operating system. (I have to say that linux is not as good as windows as the office desktop, although this sentence will certainly annoy many linux fans :-)). As a programmer, I certainly cannot endure such troubles. I must try to solve this problem. After consideration, I have a good idea.
  
This reflects The Bazaar Principle 1:
  
Every good work of software starts by scratching a developer's personal itch.
Every software development has its own brand.
3. Initial design
  
What I need is a program that can be used as a "two-handed" job. He is in the position where he can connect the external target server and my machine at the same time. My machine sent the request to him. he accepted the request and copied the request to the external target server. the external target server responded to the request and sent the response to him, then he accepted the answer and copied the answer to my machine. In this way, my machine actually regards it as the target server (because it is a copy, the request and answer are not modified ). He is the client of the external target server (the request and answer are not modified because it is an unfrozen copy ). I call this kind of proxy service program "passer ".
  
The schematic diagram is as follows:
  
| ---------- | -------------- | ------------ |
| -------> | ------> |
| My machine | proxy service program | target server |
| <------- | <------ |
| ---------- | -------------- | ------------ |
  
4. reuse example
  
The Bazaar Principle 2:
  
Good programmers know what to write. Great ones know what to rewrite (and reuse ).
Good programmers know what to write. Great programmers know what to rewrite and reuse.
Based on this principle, I certainly won't write this program from the beginning (in fact, this program is a very small program and there is no need to do so. However, in order to provide you with a market-based development experience, I still did this, I first wrote a simple program-attached to the end of this article-and then remembered to find a similar program:-), the result wasted a lot of time ).
  
I searched for the program on the internet and found the program in about half an hour (which is similar to the time it took for me to write the first simple program.
  
The procedure is as follows:
  
(This program comes from Shuimu Tsinghua BBS excellent edition)
  
After reading this program, I refined my preliminary design: The program listens to the service port, accepts the client connection, derives the sub-process processing connection, and connects to the service port of the remote machine at the same time, then begin to complete the "second-handed" work.
  
Of course, this small program also has some shortcomings:
  
It can only listen to one service port and can only connect to the service port of one remote machine.
It adopts the sub-process method. if the client has many connections, it will put a lot of pressure on the server.
He can only listen to tcp, but cannot act as a udp proxy server (the majority of OICQ users know that this program cannot be used as an OICQ proxy ).
It can only read service ports through command lines, remote server addresses and ports, and cannot use configuration files.
Therefore, I decided to continue to improve my own program, instead of using him.
  
The Bazaar Principle 3:
  
Plan to throw one away; you will, anyhow.
5. The first version of code
  
The first version of my applet is as follows:
  
The following is a simple explanation of the program. If you are familiar with socket network programming, do not read it. :-)
  
?? Bzero (& servaddr, sizeof (servaddr ));
?? Servaddr. sin_family = AF_INET;
?? Servaddr. sin_port = htons (7000 );
?? Servaddr. sin_addr.s_addr = INADDR_ANY;
  
A sockaddr_in structure is provided, which defines the port number and address of the server.
  
?? Listenfd = socket (AF_INET, SOCK_STREAM, 0 );
  
The socket () function returns a socket-type description, which is AF_INET (IPv4) and SOCK_STREAM (TCP ).
  
?? If (listenfd <0 ){
?? Printf ("socket error ");
?? Exit (-1 );
??}
  
If the return value of the socket () function is less than 0, an error occurs.
  
?? If (bind (listenfd, (struct sockaddr *) & servaddr, sizeof (servaddr) <0 ){
?? Printf ("bind error ");
?? Exit (-1 );
??}
  
Bind the description and server address port. If the return value of the bind () function is less than 0, an error occurs.
  
?? Signal (SIGCHLD, waitchild );
  
The processing function of the SIGCHLD signal is waitchild (). When the child process of the main process fork () ends, the main process receives a SIGCHLD signal, the kernel sends this signal to enable the main process to check the exit status of the sub-process and perform some cleanup (if necessary ). If the main process does not process the SIGCHLD signal, the sub-process will become a zombie process until the main process exits and is taken over by the init process and cleared by the init process.
  
The waitchild () function is as follows:
  
?? Void waitchild (int signo ){
?? Int status;
?? Pid_t childpid;
?? If (childpid = waitpid (-1, & status, WNOHANG) <0 ){
?? Printf ("wait error ");
?? Exit (1 );
??}
?? Printf ("child % d quitted", childpid );
?? Return;
??}
  
Note: The signal handler must be defined in the void func (int) form.
  
Waitpid (-1, & status, WNOHANG) waits for the sub-process to exit and obtains the exit status of the sub-process and saves it to status.
  
?? Printf ("child % d quitted", childpid );
  
Print the process ID of the sub-process.
  
?? If (listen (listenfd, 5) <0 ){
?? Printf ("listen error ");
?? Exit (-1 );
??}
  
Start the listener and specify the length of the waiting queue to 5. If the value returned by the listen () function is less than 0, an error occurs.
  
?? For (;;){
?? Connfd = accept (listenfd, (struct sockaddr *) & clientaddr, & clientlen );
?? If (connfd <0 ){
?? Printf ("accept error ");
?? Exit (-1 );
??}
?? If (chpid = fork () =-1 ){
?? Printf ("fork error ");
?? Exit (-1 );
??}
?? If (chpid = 0 ){
?? Close (listenfd );
?? Do_proxy (connfd );
?? Exit (0 );
??}
?? If (chpid> 0 ){
?? Close (connfd );
??}
??}
  
In the for (;) {} Infinite Loop, the process is blocked by accept.
  
?? Accept (listenfd, (struct sockaddr *) & clientaddr, & clientlen)
  
Wait for the client to connect. if the connection is successful, the client IP address, port number, protocol type, and other information are returned in clientaddr, and the length of clientaddr is stored in clientlen. Accept returns the socket connection description connfd. if the return value of the accept () function is less than 0, it indicates an error.
  
The connection is successful. The main process uses the fork () dispatching process. If the return value of the FORK () function is less than 0, an error occurs.
  
In the main process (chpid> 0), close the connfd description and continue the for (;) {} loop. In the sub-process (chpid = 0), close the listenfd listener socket description and call the do_proxy () function (this will be introduced later to complete proxy work ). Wait for the do_proxy () function to return and exit the sub-process.
  
Note: the fork () function is called once and returns twice. one is returned in the master process and the other is returned in the child process.
  
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.