网络编程--大杂烩
Posted viewcode
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网络编程--大杂烩相关的知识,希望对你有一定的参考价值。
网络编程本质上就是不同机器上的程序之间的通信。
常见的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编程
IP协议对应于网络层,TCP协议对应于传输层,而HTTP协议对应于应用层。socket编程是对tcp/ip协议栈的封装,而http是应用层协议,主要是解决如何封装数据。 而对http协议的书面描述是这样的: “HTTP协议即超文本传送协议(Hypertext Transfer Protocol ),是Web联网的基础,也是手机联网常用的协议之一,HTTP协议是建立在TCP协议之上的一种应用。
HTTP连接最显著的特点是客户端发送的每次请求都需要服务器回送响应,在请求结束后,会主动释放连接。从建立连接到关闭连接的过程称为“一次连接”。” httpserver编程是对socket编程进一步封装。
mongoose是httpserver/web server编程的一种极其方便的实现,常用在嵌入式平台上,能用于restful服务,rpc进程间通信等场景。 更详细的描述见: http://code.google.com/p/mongoose/
mongoose的API 接口在mongoose.h声明,而mongoose.c是源码实现。
如何使用mongoose? 常用接口:mg_create_server() 创建服务器 mg_set_option() 配置服务器,如打开端口,设置服务的目录 mg_poll_server() 在循环等待服务完成 mg_destroy_server() 清除服务器
一个简单的例子,对外提供静态目录下的文件服务:
#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实现类的回调功能。
4. DBUS编程
不仅对socket进行封装,也不仅仅是一种分布式进程通信方式,高大上的是它拥有一个独立daemon,负责数据和消息的转发。 它使得进程间通信的使用更加方便、好用,不用关心底层的实现细节。 原理是大概如此,更详细的描述去网上搜搜,很多资料。以上是关于网络编程--大杂烩的主要内容,如果未能解决你的问题,请参考以下文章