首页 > 代码库 > 网络编程--大杂烩
网络编程--大杂烩
网络编程本质上就是不同机器上的程序之间的通信。
常见的tcp/ip命令配置,socket编程,更高级的封装好的server API等等,都是是网络编程的一部分。
自己也把见过的这些大杂烩理一下。
1. tcp/ip
常见的配置命令在tcp/ip详解第一卷有详细的原理解释和应用实例,而在第二卷中,是代码实现的解释。
linux几个常见的tcp/ip命令: ping, ifconfig, traceroute, netstat, route, ip, host等等
根据类型划分:
网络参数配置类:
ifconfig, ip, route, 这几个命令需要根据需要了解每个参数的含义。
网络侦测类:
ping,netstat, traceroute, host
ping: 是通过icmp包来测试两部主机间的回声和判断状况
traceroute:就是更进一步,诊断追踪两部主机之间通过的各个节点 (node) 通讯状况的好坏
netstat: 就是在观察网络的联机状态了,而网络联机状态中, 又以观察『我目前开了多少的 port 在等待客户端的联机』以及 『目前我的网络联机状态中,有多少联机已创建或产生问题』最常见.
host: 查询某主机的ip
2. socket api及概念
linux c代码里,客户端和服务端编程流程:
服务端:
socket()建立套接字
bind()套接字与地址(IP和端口)的绑定
listen()服务器监听客户端的连接
accept()接收客户端连接
send(), recv()接收和发送数据
close()关闭套接字
客户端:
socket()建立套接字
connect()连接服务器
send(),recv()读写网络数据
close()关闭套接字
从socket的数据结构,就可以看出socket编程,需要设置哪些参数?
IPV4的地址参数:
typedef uint32_t in_addr_t; typedef uint16_t in_port_t; typedef unsigned short sa_family_t; struct in_addr { in_addr_t s_addr; //32位IPv4地址,网络字节序 }; struct sockaddr_in { uint8_t sin_len; sa_family_t sin_family; //协议族类型 in_port_t sin_port; //端口号 struct in_addr sin_addr; //IP地址 char sin_zero[8]; //保留使用 };
而socketaddr_in又有通用的表示方式
struct sockaddr { uint8_t s_len; sa_family_t sa_family; char sa_data[14]; };
而java的实现是客户端使用一个Socket类,服务端使用ServerSocket类
客户端的socket类只需初始化IP和端口,然后发送消息,如
Socket s = new Socket ("198.163.227.6", 13); InputStream is = s.getInputStream (); // Read from the stream. is.close (); s.close ();
而服务端ServerSocket的初始化只需指明端口,然后便可以监听和接收数据。
而对于UDP编程,也有很多应用场景,比较嵌入式编程中,只需负责发出控制消息,不需要建立稳定链接的场景,可以设置UDP的通信方式,只需在socket协议族和端口类型指明为udp方式。
网上找来的一个例子,java版本:
服务端代码:
package Server; import java.io.*; import java.net.*; import java.util.*; import java.awt.*; import javax.swing.*; public class Server extends JFrame { // Text area for displaying contents private JTextArea jta = new JTextArea(); public static void main(String[] args) { new Server(); } public Server() { // Place text area on the frame getContentPane().setLayout(new BorderLayout()); getContentPane().add(new JScrollPane(jta), BorderLayout.CENTER); setTitle("Server"); setSize(500, 300); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); // It is necessary to show the frame here! try { // Create a server socket ServerSocket serverSocket = new ServerSocket(8000); jta.append("Server started at " + new Date() + ‘\n‘); // Listen for a connection request Socket socket = serverSocket.accept(); // Create data input and output streams DataInputStream inputFromClient = new DataInputStream( socket.getInputStream()); DataOutputStream outputToClient = new DataOutputStream( socket.getOutputStream()); while (true) { // Receive radius from the client double radius = inputFromClient.readDouble(); // Compute area double area = radius * radius * Math.PI; // Send area back to the client outputToClient.writeDouble(area); jta.append("Radius received from client: " + radius + ‘\n‘); jta.append("Area found: " + area + ‘\n‘); } } catch(IOException ex) { System.err.println(ex); } } }
客户端代码:
package Client; import java.io.*; import java.net.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; public class Client extends JFrame implements ActionListener { // Text field for receiving radius private JTextField jtf = new JTextField(); // Text area to display contents private JTextArea jta = new JTextArea(); // IO streams private DataOutputStream outputToServer; private DataInputStream inputFromServer; public static void main(String[] args) { new Client(); } public Client() { // Panel p to hold the label and text field JPanel p = new JPanel(); p.setLayout(new BorderLayout()); p.add(new JLabel("Enter radius"), BorderLayout.WEST); p.add(jtf, BorderLayout.CENTER); jtf.setHorizontalAlignment(JTextField.RIGHT); getContentPane().setLayout(new BorderLayout()); getContentPane().add(p, BorderLayout.NORTH); getContentPane().add(new JScrollPane(jta), BorderLayout.CENTER); jtf.addActionListener(this); // Register listener setTitle("Client"); setSize(500, 300); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); // It is necessary to show the frame here! try { // Create a socket to connect to the server Socket socket = new Socket("localhost", 8000); // Socket socket = new Socket("130.254.204.36", 8000); // Socket socket = new Socket("drake.Armstrong.edu", 8000); // Create an input stream to receive data from the server inputFromServer = new DataInputStream( socket.getInputStream()); // Create an output stream to send data to the server outputToServer = new DataOutputStream(socket.getOutputStream()); } catch (IOException ex) { jta.append(ex.toString() + ‘\n‘); } } public void actionPerformed(ActionEvent e) { String actionCommand = e.getActionCommand(); if (e.getSource() instanceof JTextField) { try { // Get the radius from the text field double radius = Double.parseDouble(jtf.getText().trim()); // Send the radius to the server outputToServer.writeDouble(radius); outputToServer.flush(); // Get area from the server double area = inputFromServer.readDouble(); // Display to the text area jta.append("Radius is " + radius + "\n"); jta.append("Area received from the server is " + area + ‘\n‘); } catch (IOException ex) { System.err.println(ex); } } } }
3. httpserver编程
HTTP连接最显著的特点是客户端发送的每次请求都需要服务器回送响应,在请求结束后,会主动释放连接。从建立连接到关闭连接的过程称为“一次连接”。”
一个简单的例子,对外提供静态目录下的文件服务:
#include "mongoose.h" int main(void) { struct mg_server *server = mg_create_server(NULL, NULL); mg_set_option(server, "document_root", "."); // Serve current directory mg_set_option(server, "listening_port", "8080"); // Open port 8080 for (;;) { mg_poll_server(server, 1000); // Infinite loop, Ctrl-C to stop } mg_destroy_server(&server); return 0; }
对客户端请求进行响应的例子:
#include <string.h> #include "mongoose.h" static int event_handler(struct mg_connection *conn, enum mg_event ev) { if (ev == MG_AUTH) { return MG_TRUE; // Authorize all requests } else if (ev == MG_REQUEST && !strcmp(conn->uri, "/hello")) { mg_printf_data(conn, "%s", "Hello world"); return MG_TRUE; // Mark as processed } else { return MG_FALSE; // Rest of the events are not processed } } int main(void) { struct mg_server *server = mg_create_server(NULL, event_handler); mg_set_option(server, "document_root", "."); mg_set_option(server, "listening_port", "8080"); for (;;) { mg_poll_server(server, 1000); // Infinite loop, Ctrl-C to stop } mg_destroy_server(&server); return 0; }
更多例子:
http://cesanta.com/docs/Embed.shtml
在java中,jdk提供了httpserver的API,HttpServer会调用HttpHandler实现类的回调方法来处理客户端请求。一个Http请求和它的响应称为一个交换,抽象出HttpExchange类, HttpServer负责将HttpExchange传给HttpHandler实现类的回调功能。