[转]C#网络编程(同步传输字符串) - Part.2

本文转自:http://www.tracefact.net/CSharp-Programming/Network-Programming-Part2.aspx

服务端客户端通信

在与服务端的连接建立以后,我们就可以通过此连接来发送和接收数据。端口与端口之间以流(Stream)的形式传输数据,因为几乎任何对象都可以保存到流中,所以实际上可以在客户端与服务端之间传输任何类型的数据。对客户端来说,往流中写入数据,即为向服务器传送数据;从流中读取数据,即为从服务端接收数据。对服务端来说,往流中写入数据,即为向客户端发送数据;从流中读取数据,即为从客户端接收数据。

同步传输字符串

1.客户端发送,服务端接收并输出

1.1服务端程序

我们可以在TcpClient上调用GetStream()方法来获得连接到远程计算机的流。注意这里我用了远程这个词,当在客户端调用时,它得到连接服务端的流;当在服务端调用时,它获得连接客户端的流。接下来我们来看一下代码,我们先看服务端(注意这里没有使用do/while循环):

class Server {
     static void Main(string[] args) {
         const int BufferSize = 8192;    // 缓存大小,8192字节

         Console.WriteLine("Server is running ... ");
         IPAddress ip = new IPAddress(new byte[] { 127, 0, 0, 1 });
         TcpListener listener = new TcpListener(ip, 8500);

         listener.Start();           // 开始侦听
        Console.WriteLine("Start Listening ...");

         // 获取一个连接,中断方法
        TcpClient remoteClient = listener.AcceptTcpClient();
         // 打印连接到的客户端信息
        Console.WriteLine("Client Connected!{0} <-- {1}",
             remoteClient.Client.LocalEndPoint, remoteClient.Client.RemoteEndPoint);

         // 获得流,并写入buffer中
        NetworkStream streamToClient = remoteClient.GetStream();
         byte[] buffer = new byte[BufferSize];
         int bytesRead = streamToClient.Read(buffer, 0, BufferSize);
         Console.WriteLine("Reading data, {0} bytes ...", bytesRead);

         // 获得请求的字符串
        string msg = Encoding.Unicode.GetString(buffer, 0, bytesRead);
         Console.WriteLine("Received: {0}", msg);

         // 按Q退出
    }
 }

这段程序的上半部分已经很熟悉了,我就不再解释。remoteClient.GetStream()方法获取到了连接至客户端的流,然后从流中读出数据并保存在了buffer缓存中,随后使用Encoding.Unicode.GetString()方法,从缓存中获取到了实际的字符串。最后将字符串打印在了控制台上。这段代码有个地方需要注意:在能够读取的字符串的总字节数大于BufferSize的时候会出现字符串截断现象,因为缓存中的数目总是有限的,而对于大对象,比如说图片或者其它文件来说,则必须采用“分次读取然后转存”这种方式,比如这样:

// 获取字符串
byte[] buffer = new byte[BufferSize];
int bytesRead;          // 读取的字节数
MemoryStream msStream = new MemoryStream();
do {
     bytesRead = streamToClient.Read(buffer, 0, BufferSize);
     msStream.Write(buffer, 0, bytesRead);
 } while (bytesRead > 0);

 buffer = msStream.GetBuffer();
string msg = Encoding.Unicode.GetString(buffer);

这里我没有使用这种方法,一个是因为不想关注在太多的细节上面,一个是因为对于字符串来说,8192字节已经很多了,我们通常不会传递这么多的文本。当使用Unicode编码时,8192字节可以保存4096个汉字和英文字符。使用不同的编码方式,占用的字节数有很大的差异,在本文最后面,有一段小程序,可以用来测试Unicode、UTF8、ASCII三种常用编码方式对字符串编码时,占用的字节数大小。

现在对客户端不做任何修改,然后运行先运行服务端,再运行客户端。结果我们会发现这样一件事:服务端再打印完“Client Connected!127.0.0.1:8500 <-- 127.0.0.1:xxxxx”之后,再次被阻塞了,而没有输出“Reading data, {0} bytes ...”。可见,与AcceptTcpClient()方法类似,这个Read()方法也是同步的,只有当客户端发送数据的时候,服务端才会读取数据、运行此方法,否则它便会一直等待。

1.2 客户端程序

接下来我们编写客户端向服务器发送字符串的代码,与服务端类似,它先获取连接服务器端的流,将字符串保存到buffer缓存中,再将缓存写入流,写入流这一过程,相当于将消息发往服务端。

class Client {
     static void Main(string[] args) {
         Console.WriteLine("Client Running ...");
         TcpClient client;

         try {
             client = new TcpClient();
             client.Connect("localhost", 8500);      // 与服务器连接
        } catch (Exception ex) {
             Console.WriteLine(ex.Message);
             return;
         }
         // 打印连接到的服务端信息
        Console.WriteLine("Server Connected!{0} --> {1}",
             client.Client.LocalEndPoint, client.Client.RemoteEndPoint);

         string msg = "\"Welcome To TraceFact.Net\"";
         NetworkStream streamToServer = client.GetStream();

         byte[] buffer = Encoding.Unicode.GetBytes(msg);     // 获得缓存
        streamToServer.Write(buffer, 0, buffer.Length);     // 发往服务器
        Console.WriteLine("Sent: {0}", msg);

         // 按Q退出
    }
 }

现在再次运行程序,得到的输出为:

// 服务端
Server is running ...
 Start Listening ...
 Client Connected!127.0.0.1:8500 <-- 127.0.0.1:7847
 Reading data, 52 bytes ...
 Received: "Welcome To TraceFact.Net"
输入"Q"键退出。
// 客户端
Client Running ...
 Server Connected!127.0.0.1:7847 --> 127.0.0.1:8500
 Sent: "Welcome To TraceFact.Net"
输入"Q"键退出。

再继续进行之前,我们假设客户端可以发送多条消息,而服务端要不断的接收来自客户端发送的消息,但是上面的代码只能接收客户端发来的一条消息,因为它已经输出了“输入Q键退出”,说明程序已经执行完毕,无法再进行任何动作。此时如果我们再开启一个客户端,那么出现的情况是:客户端可以与服务器建立连接,也就是netstat-a显示为ESTABLISHED,这是操作系统所知道的;但是由于服务端的程序已经执行到了最后一步,只能输入Q键退出,无法再采取任何的动作。

回想一个上面我们需要一个服务器对应多个客户端时,对AcceptTcpClient()方法的处理办法,将它放在了do/while循环中;类似地,当我们需要一个服务端对同一个客户端的多次请求服务时,可以将Read()方法放入到do/while循环中。

现在,我们大致可以得出这样几个结论:
•如果不使用do/while循环,服务端只有一个listener.AcceptTcpClient()方法和一个TcpClient.GetStream().Read()方法,则服务端只能处理到同一客户端的一条请求。
•如果使用一个do/while循环,并将listener.AcceptTcpClient()方法和TcpClient.GetStream().Read()方法都放在这个循环以内,那么服务端将可以处理多个客户端的一条请求。
•如果使用一个do/while循环,并将listener.AcceptTcpClient()方法放在循环之外,将TcpClient.GetStream().Read()方法放在循环以内,那么服务端可以处理一个客户端的多条请求。
•如果使用两个do/while循环,对它们进行分别嵌套,那么结果是什么呢?结果并不是可以处理多个客户端的多条请求。因为里层的do/while循环总是在为一个客户端服务,因为它会中断在TcpClient.GetStream().Read()方法的位置,而无法执行完毕。即使可以通过某种方式让里层循环退出,比如客户端往服务端发去“exit”字符串时,服务端也只能挨个对客户端提供服务。如果服务端想执行多个客户端的多个请求,那么服务端就需要采用多线程。主线程,也就是执行外层do/while循环的线程,在收到一个TcpClient之后,必须将里层的do/while循环交给新线程去执行,然后主线程快速地重新回到listener.AcceptTcpClient()的位置,以响应其它的客户端。

对于第四种情况,实际上是构建一个服务端更为通常的情况,所以需要专门开辟一个章节讨论,这里暂且放过。而我们上面所做的,即是列出的第一种情况,接下来我们再分别看一下第二种和第三种情况。

对于第二种情况,我们按照上面的叙述先对服务端进行一下改动:

do {
     // 获取一个连接,中断方法
    TcpClient remoteClient = listener.AcceptTcpClient();
     // 打印连接到的客户端信息
    Console.WriteLine("Client Connected!{0} <-- {1}",
         remoteClient.Client.LocalEndPoint, remoteClient.Client.RemoteEndPoint);

     // 获得流,并写入buffer中
    NetworkStream streamToClient = remoteClient.GetStream();
     byte[] buffer = new byte[BufferSize];
     int bytesRead = streamToClient.Read(buffer, 0, BufferSize);
     Console.WriteLine("Reading data, {0} bytes ...", bytesRead);

     // 获得请求的字符串
    string msg = Encoding.Unicode.GetString(buffer, 0, bytesRead);
     Console.WriteLine("Received: {0}", msg);
 } while (true);

然后启动多个客户端,在服务端应该可以看到下面的输出(客户端没有变化):

Server is running ...
 Start Listening ...
 Client Connected!127.0.0.1:8500 <-- 127.0.0.1:8196
 Reading data, 52 bytes ...
 Received: "Welcome To TraceFact.Net"
 Client Connected!127.0.0.1:8500 <-- 127.0.0.1:8199
 Reading data, 52 bytes ...
 Received: "Welcome To TraceFact.Net"

由第2种情况改为第3种情况,只需要将do向下挪动几行就可以了:

// 获取一个连接,中断方法
TcpClient remoteClient = listener.AcceptTcpClient();
// 打印连接到的客户端信息
Console.WriteLine("Client Connected!{0} <-- {1}",
     remoteClient.Client.LocalEndPoint, remoteClient.Client.RemoteEndPoint);
// 获得流,并写入buffer中
NetworkStream streamToClient = remoteClient.GetStream();

do {
     byte[] buffer = new byte[BufferSize];
     int bytesRead = streamToClient.Read(buffer, 0, BufferSize);
     Console.WriteLine("Reading data, {0} bytes ...", bytesRead);

     // 获得请求的字符串
    string msg = Encoding.Unicode.GetString(buffer, 0, bytesRead);
     Console.WriteLine("Received: {0}", msg);
 } while (true);

然后我们再改动一下客户端,让它发送多个请求。当我们按下S的时候,可以输入一行字符串,然后将这行字符串发送到服务端;当我们输入X的时候则退出循环:

NetworkStream streamToServer = client.GetStream();
ConsoleKey key;
Console.WriteLine("Menu: S - Send, X - Exit");
do {
     key = Console.ReadKey(true).Key;

     if (key == ConsoleKey.S) {
         // 获取输入的字符串
        Console.Write("Input the message: ");
         string msg = Console.ReadLine();

         byte[] buffer = Encoding.Unicode.GetBytes(msg);     // 获得缓存
        streamToServer.Write(buffer, 0, buffer.Length);     // 发往服务器
        Console.WriteLine("Sent: {0}", msg);
     }
 } while (key != ConsoleKey.X);

接下来我们先运行服务端,然后再运行客户端,输入一些字符串,来进行测试,应该能够看到下面的输出结果:

// 服务端
Server is running ...
 Start Listening ...
 Client Connected!127.0.0.1:8500 <-- 127.0.0.1:11004
 Reading data, 44 bytes ...
 Received: 欢迎访问我的博客:TraceFact.Net
Reading data, 14 bytes ...
 Received: 我们一起进步!
//客户端
Client Running ...
 Server Connected!127.0.0.1:11004 --> 127.0.0.1:8500
 Menu: S - Send, X - Exit
 Input the message: 欢迎访问我的博客:TraceFact.Net
 Sent: 欢迎访问我的博客:TraceFact.Net
 Input the message: 我们一起进步!
Sent: 我们一起进步!

这里还需要注意一点,当客户端在TcpClient实例上调用Close()方法,或者在流上调用Dispose()方法,服务端的streamToClient.Read()方法会持续地返回0,但是不抛出异常,所以会产生一个无限循环;而如果直接关闭掉客户端,或者客户端执行完毕但没有调用stream.Dispose()或者TcpClient.Close(),如果服务器端此时仍阻塞在Read()方法处,则会在服务器端抛出异常:“远程主机强制关闭了一个现有连接”。因此,我们将服务端的streamToClient.Read()方法需要写在一个try/catch中。同理,如果在服务端已经连接到客户端之后,服务端调用remoteClient.Close(),则客户端会得到异常“无法将数据写入传输连接: 您的主机中的软件放弃了一个已建立的连接。”;而如果服务端直接关闭程序的话,则客户端会得到异常“无法将数据写入传输连接: 远程主机强迫关闭了一个现有的连接。”。因此,它们的读写操作必须都放入到try/catch块中。

2.服务端回发,客户端接收并输出

2.2服务端程序

我们接着再进行进一步处理,服务端将收到的字符串改为大写,然后回发,客户端接收后打印。此时它们的角色和上面完全进行了一下对调:对于服务端来说,就好像刚才的客户端一样,将字符串写入到流中;而客户端则同服务端一样,接收并打印。除此以外,我们最好对流的读写操作加上lock,现在我们直接看代码,首先看服务端:

class Server {
     static void Main(string[] args) {
         const int BufferSize = 8192;    // 缓存大小,8192Bytes
        ConsoleKey key;

         Console.WriteLine("Server is running ... ");
         IPAddress ip = new IPAddress(new byte[] { 127, 0, 0, 1 });
         TcpListener listener = new TcpListener(ip, 8500);

         listener.Start();           // 开始侦听
        Console.WriteLine("Start Listening ...");

         // 获取一个连接,同步方法,在此处中断
        TcpClient remoteClient = listener.AcceptTcpClient();

         // 打印连接到的客户端信息
        Console.WriteLine("Client Connected!{0} <-- {1}",
             remoteClient.Client.LocalEndPoint, remoteClient.Client.RemoteEndPoint);

         // 获得流
        NetworkStream streamToClient = remoteClient.GetStream();

         do {
             // 写入buffer中
            byte[] buffer = new byte[BufferSize];
             int bytesRead;
             try {
                 lock(streamToClient){
                     bytesRead = streamToClient.Read(buffer, 0, BufferSize);
                 }
                 if (bytesRead == 0) throw new Exception("读取到0字节");
                 Console.WriteLine("Reading data, {0} bytes ...", bytesRead);

                 // 获得请求的字符串
                string msg = Encoding.Unicode.GetString(buffer, 0, bytesRead);
                 Console.WriteLine("Received: {0}", msg);

                 // 转换成大写并发送
                msg = msg.ToUpper();
                 buffer = Encoding.Unicode.GetBytes(msg);
                 lock(streamToClient){
                     streamToClient.Write(buffer, 0, buffer.Length);
                 }
                 Console.WriteLine("Sent: {0}", msg);
             } catch (Exception ex) {
                 Console.WriteLine(ex.Message);
                 break;
             }
         } while (true);

         streamToClient.Dispose();
         remoteClient.Close();

         Console.WriteLine("\n\n输入\"Q\"键退出。");
         do {
             key = Console.ReadKey(true).Key;
         } while (key != ConsoleKey.Q);
     }
 }

接下来是客户端:

class Client {
     static void Main(string[] args) {
         Console.WriteLine("Client Running ...");
         TcpClient client;
         ConsoleKey key;
         const int BufferSize = 8192;

         try {
             client = new TcpClient();
             client.Connect("localhost", 8500);      // 与服务器连接
        } catch (Exception ex) {
             Console.WriteLine(ex.Message);
             return;
         }

         // 打印连接到的服务端信息
        Console.WriteLine("Server Connected!{0} --> {1}",
             client.Client.LocalEndPoint, client.Client.RemoteEndPoint);

         NetworkStream streamToServer = client.GetStream();
         Console.WriteLine("Menu: S - Send, X - Exit");

         do {
             key = Console.ReadKey(true).Key;

             if (key == ConsoleKey.S) {
                 // 获取输入的字符串
                Console.Write("Input the message: ");
                 string msg = Console.ReadLine();

                 byte[] buffer = Encoding.Unicode.GetBytes(msg);     // 获得缓存
                try {
                     lock(streamToServer){
                         streamToServer.Write(buffer, 0, buffer.Length);     // 发往服务器
                    }
                     Console.WriteLine("Sent: {0}", msg);

                     int bytesRead;
                     buffer = new byte[BufferSize];
                     lock(streamToServer){
                         bytesRead = streamToServer.Read(buffer, 0, BufferSize);
                     }
                     msg = Encoding.Unicode.GetString(buffer, 0, bytesRead);
                     Console.WriteLine("Received: {0}", msg);

                 } catch (Exception ex) {
                     Console.WriteLine(ex.Message);
                     break;
                 }
             }
         } while (key != ConsoleKey.X);

         streamToServer.Dispose();
         client.Close();

         Console.WriteLine("\n\n输入\"Q\"键退出。");
         do {
             key = Console.ReadKey(true).Key;
         } while (key != ConsoleKey.Q);
     }
 }

最后我们运行程序,然后输入一串英文字符串,然后看一下输出:

// 客户端
Client is running ...
 Server Connected!127.0.0.1:12662 --> 127.0.0.1:8500
 Menu: S - Send, X - Exit
 Input the message: Hello, I‘m jimmy zhang.
 Sent: Hello, I‘m jimmy zhang.
 Received: HELLO, I‘M JIMMY ZHANG.

 // 服务端
Server is running ...
 Start Listening ...
 Client Connected!127.0.0.1:8500 <-- 127.0.0.1:12662
 Reading data, 46 bytes ...
 Received: Hello, I‘m jimmy zhang.
 Sent: HELLO, I‘M JIMMY ZHANG.

看到这里,我想你应该对使用TcpClient和TcpListener进行C#网络编程有了一个初步的认识,可以说是刚刚入门了,后面的路还很长。本章的所有操作都是同步操作,像上面的代码也只是作为一个入门的范例,实际当中,一个服务端只能为一个客户端提供服务的情况是不存在的,下面就让我们来看看上面所说的第四种情况,如何进行异步的服务端编程。

附录:ASCII、UTF8、Uncicode编码下的中英文字符大小

private static void ShowCode() {
     string[] strArray = { "b", "abcd", "乙", "甲乙丙丁" };
     byte[] buffer;
     string mode, back;

     foreach (string str in strArray) {

         for (int i = 0; i <= 2; i++) {
             if (i == 0) {
                 buffer = Encoding.ASCII.GetBytes(str);
                 back = Encoding.ASCII.GetString(buffer, 0, buffer.Length);
                 mode = "ASCII";
             } else if (i == 1) {
                 buffer = Encoding.UTF8.GetBytes(str);
                 back = Encoding.UTF8.GetString(buffer, 0, buffer.Length);
                 mode = "UTF8";
             } else {
                 buffer = Encoding.Unicode.GetBytes(str);
                 back = Encoding.Unicode.GetString(buffer, 0, buffer.Length);
                 mode = "Unicode";
             }

             Console.WriteLine("Mode: {0}, String: {1}, Buffer.Length: {2}",
                 mode, str, buffer.Length);

             Console.WriteLine("Buffer:");
             for (int j = 0; j <= buffer.Length - 1; j++) {
                 Console.Write(buffer[j] + " ");
             }

             Console.WriteLine("\nRetrived: {0}\n", back);
         }
     }
 }

输出为:

Mode: ASCII, String: b, Buffer.Length: 1
 Buffer: 98
 Retrived: b

 Mode: UTF8, String: b, Buffer.Length: 1
 Buffer: 98
 Retrived: b

 Mode: Unicode, String: b, Buffer.Length: 2
 Buffer: 98 0
 Retrived: b

 Mode: ASCII, String: abcd, Buffer.Length: 4
 Buffer: 97 98 99 100
 Retrived: abcd

 Mode: UTF8, String: abcd, Buffer.Length: 4
 Buffer: 97 98 99 100
 Retrived: abcd

 Mode: Unicode, String: abcd, Buffer.Length: 8
 Buffer: 97 0 98 0 99 0 100 0
 Retrived: abcd

 Mode: ASCII, String: 乙, Buffer.Length: 1
 Buffer: 63
 Retrived: ?

 Mode: UTF8, String: 乙, Buffer.Length: 3
 Buffer: 228 185 153
 Retrived: 乙

Mode: Unicode, String: 乙, Buffer.Length: 2
 Buffer: 89 78
 Retrived: 乙

Mode: ASCII, String: 甲乙丙丁, Buffer.Length: 4
 Buffer: 63 63 63 63
 Retrived: ????

 Mode: UTF8, String: 甲乙丙丁, Buffer.Length: 12
 Buffer: 231 148 178 228 185 153 228 184 153 228 184 129
 Retrived: 甲乙丙丁

Mode: Unicode, String: 甲乙丙丁, Buffer.Length: 8
 Buffer: 50 117 89 78 25 78 1 78
 Retrived: 甲乙丙丁

大体上可以得出这么几个结论:
•ASCII不能保存中文(貌似谁都知道=_-`)。
•UTF8是变长编码。在对ASCII字符编码时,UTF更省空间,只占1个字节,与ASCII编码方式和长度相同;Unicode在对ASCII字符编码时,占用2个字节,且第2个字节补零。
•UTF8在对中文编码时需要占用3个字节;Unicode对中文编码则只需要2个字节。
时间: 2024-11-05 23:29:26

[转]C#网络编程(同步传输字符串) - Part.2的相关文章

C#网络编程(同步传输字符串)

C#网络编程(同步传输字符串) - Part.2 服务端客户端通信 在与服务端的连接建立以后,我们就可以通过此连接来发送和接收数据.端口与端口之间以流(Stream)的形式传输数据,因为几乎任何对象都可以保存到流中,所以实际上可以在客户端与服务端之间传输任何类型的数据.对客户端来说,往流中写入数据,即为向服务器传送数据:从流中读取数据,即为从服务端接收数据.对服务端来说,往流中写入数据,即为向客户端发送数据:从流中读取数据,即为从客户端接收数据. 同步传输字符串 我们现在考虑这样一个任务:客户端

C#网络编程(异步传输字符串)

C#网络编程(异步传输字符串) - Part.3 这篇文章我们将前进一大步,使用异步的方式来对服务端编程,以使它成为一个真正意义上的服务器:可以为多个客户端的多次请求服务.但是开始之前,我们需要解决上一节中遗留的一个问题. 消息发送时的问题 这个问题就是:客户端分两次向流中写入数据(比如字符串)时,我们主观上将这两次写入视为两次请求:然而服务端有可能将这两次合起来视为一条请求,这在两个请求间隔时间比较短的情况下尤其如此.同样,也有可能客户端发出一条请求,但是服务端将其视为两条请求处理.下面列出了

同步传输字符串

同步传输字符串 接下来考虑着一种情况,完成一个简单的文本通信: (1).客户端将字符串发送到服务端,服务端接受字符串并显示 (2).服务端将字符串由英文的小写转换为大写,然后发回给客户端,客户端接受并显示. 客户端发送,服务端接受并输出 1.服务端程序 可以在TcpClient上调用GetStream()方法来获得连接到远程计算机的网络流NetworkStream.当在客户端调用时,它获得连接服务端的流;当在服务端调用时,它获得连接客户端的流. 先看服务端的代码实现: using System;

9. 网络编程:

网络编程: 端口: 物理端口: 逻辑端口:用于标识进程的逻辑地址,不同进程的标识:有效端口:0~65535,其中0~1024系统使用或保留端口. java 中ip对象:InetAddress. import java.net.*; class  IPDemo{ public static void main(String[] args) throws UnknownHostException{ //通过名称(ip字符串or主机名)来获取一个ip对象. InetAddress ip = InetA

黑马程序员——网络编程篇

------- android培训.java培训.期待与您交流! ---------- 概述   1.网络模型        (1).OSI参考模型        (2).TCP/IP参考模型   2.网络通讯要素         (1).IP地址        (2).端口号         (3).传输协议    3.过程        1,找到对方IP. 2,数据要发送到对方指定的应用程序上.为了标识这些应用程序,所以给这些网络应用程序都用数字进行标识. 为了方便称呼这个数据,叫做端口(逻

网络编程TCP/IP实现客户端与客户端聊天

一.TCP/IP协议 既然是网络编程,涉及几个系统之间的交互,那么首先要考虑的是如何准确的定位到网络上的一台或几台主机,另一个是如何进行可靠高效的数据传输.这里就要使用到TCP/IP协议. TCP/IP协议(传输控制协议)由网络层的IP协议和传输层的TCP协议组成.IP层负责网络主机的定位,数据传输的路由,由IP地址可以唯一的确定Internet上的一台主机.TCP层负责面向应用的可靠的或非可靠的数据传输机制,这是网络编程的主要对象. 二.TCP与UDP TCP是一种面向连接的保证可靠传输的协议

Python笔记8:网络编程

python内置封装了很多常见的网络协议的库,因此python成为了一个强大的网络编程工具,这里是对python的网络方面编程的一个简单描述. urllib 和 urllib2模块 urllib 和urllib2是python标准库中最强的网络工作库.这里简单介绍下urllib模块.本次主要用urllib模块中的常用的几个模块: urlopen parse urlencode quote unquote _safe_quoters unquote_plus GET请求: 使用urllib 进行h

python excel操作及网络编程

python excel操作 一:excel获取值操作 1.导入模块 import xlrd 2.打开Excel文件读取数据 data = xlrd.open_workbook('excelFile.xls') 3.使用技巧 获取一个工作表 table = data.sheets()[0]          #通过索引顺序获取 table = data.sheet_by_index(0) #通过索引顺序获取 table = data.sheet_by_name(u'Sheet1')#通过名称获取

网络编程基础

网络编程基础 1.套接字概念 Linux环境下使用套接字进行进程之间的通信.用过套接字的接口,其他进程的位置对于应用程序来讲是透明的.相互通信双方端点都有一个套接字,双方如果要进行通信,通过套接字建立桥梁,双方就可以通信了. 类似文件一样,套接字也有一个套接字描述符,应用程序可以像操作文件一样操作套接字.在进行网络通信的过程中,用户感觉就是在操作文件一样,这是Linux将外部设备抽象为一个文件的好处. 2.字节序 不同主机的体系结构不同,所采用的数据存储方式不同.网络中,进程之间的通信是跨主机的