TCP应用编程

    言归正卷,在WCF出来之后,可能我们玩这些原始的TCP越来越少了,我们知道WCF对TCP进行了再一次的包装,第一反应给我们的或许是

同构系统用TCP,异构系统用HTTP,那么问题来了,异构系统到底可不可以用TCP呢?至少WCF是玩不了的,因为其他语言没有针对.net的“服务

引用”,也没有什么ChannelFactory给你去玩,如果你是一定要追求性能的话,原始的TCP会助你一臂之力的。

   我们知道最最原始的是玩Socket,由于Socket比较复杂,但是最灵活,C#里面提供了两个简化的包装类:TcpListener和TcpClient。

一:TcpListener

   这个是作为服务器端程序而存在的,我们来看看如何使用这服务端。

1: 开启监听地址

1 TcpListener listener = new TcpListener(new System.Net.IPAddress(new byte[] { 127, 0, 0, 1 }), 2222);
2
3 listener.Start(); 

2:好了,已经开启了,服务端程序开始监听该端口的客户端请求了,那么如何获取该请求呢?简单,listener的AcceptTcpClient属性搞定。

1 var myclient = listener.AcceptTcpClient();
 3:我们知道TCP传的是字节流,通过myclient.GetStream()就可以获取一个NetworkStream,利用这个Stream就可以进行收发信息了。

 <1> 收操作:

1 BinaryReader sr = new BinaryReader(client.GetStream());
2
3  //客户端数据
4  var data = sr.ReadString();
<2>发操作:也就是所谓的返回值

1 //处理完了之后要返回数据给客户端
2 BinaryWriter sw = new BinaryWriter(client.GetStream());
3
4 sw.Write(string.Format("当前时间:{0},服务端已经处理完毕!", DateTime.Now)); 

  这里要注意的地方就是AcceptTcpClient是阻塞线程的,直到收到客户端请求才算建立了一个TCP连接,在服务端处理的过程中,后续的客户端的请求将

会处理等待直到前一个请求处理完,说了这么多,就是每一个请求我们都建议开一个线程专门为其服务,类似这样。

 1 //接受客户端的连接请求
 2 var myclient = listener.AcceptTcpClient();
 3
 4 //用工作线程执行用户的请求
 5 Task.Factory.StartNew((obj) =>
 6 {
 7     var client = obj as TcpClient;
 8
 9     client.Close();
10
11 }, myclient);
好了,服务器端大概就是这个样子,再有的就是一些相关属性配置了,像wcf那样什么opentime,sendtime啥的。

二:TcpClient

     客户端也很简单,只要我们Connect一下端口,然后通过NetworkStream再Send一些数据就OK了。

1 TcpClient client = new TcpClient();
2
3 client.Connect(new System.Net.IPAddress(new byte[] { 127, 0, 0, 1 }), 2222);
4
5 BinaryWriter bw = new BinaryWriter(client.GetStream());
6
7 bw.Write(string.Format("你好,我来请求你! {0},当前线程:{1}", j, Thread.CurrentThread.ManagedThreadId));
三:模拟

     最后我们模拟下,客户端开启100个线程,每个线程请求100次,服务器端对每个线程都用工作线程去处理,是不是找到了netTcpBinding的

感觉,最后一个大家都懂的道理就是线程多了不是好事情。

服务端:

按 Ctrl+C 复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.IO;
using System.Threading.Tasks;
using System.Threading;
using System.Net;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            TcpListener listener = new TcpListener(new System.Net.IPAddress(new byte[] { 127, 0, 0, 1 }), 2222);

            listener.Start();

            //用专门的线程来接受请求
            Task.Factory.StartNew(() =>
            {
                //不间断的接受客户端请求
                while (true)
                {
                    //接受客户端的连接请求
                    var myclient = listener.AcceptTcpClient();

                    //用工作线程执行用户的请求
                    Task.Factory.StartNew((obj) =>
                    {
                        var client = obj as TcpClient;

                        BinaryReader sr = new BinaryReader(client.GetStream());

                        //客户端数据
                        var data = sr.ReadString();

                        //客户端ip
                        var ip = (IPEndPoint)client.Client.RemoteEndPoint;

                        Console.WriteLine("当前时间:{0},接受到了来自IP:{1}:{2},的请求,发来的数据为:{3}", DateTime.Now,
                                                                                                ip.Address, ip.Port, data);

                        Thread.Sleep(1000 * 5);

                        //处理完了之后要返回数据给客户端
                        BinaryWriter sw = new BinaryWriter(client.GetStream());

                        sw.Write(string.Format("当前时间:{0},服务端已经处理完毕!", DateTime.Now));

                        client.Close();

                    }, myclient);
                }
            });

            Console.WriteLine("服务端已经启动...");

            Console.Read();
        }
    }
}
按 Ctrl+C 复制代码
客户端:

 

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Net.Sockets;
 6 using System.IO;
 7 using System.Threading;
 8 using System.Threading.Tasks;
 9
10 namespace ConsoleApplication2
11 {
12     class Program
13     {
14         static void Main(string[] args)
15         {
16             for (int i = 0; i < 100; i++)
17             {
18                 Task.Factory.StartNew(() =>
19                 {
20                     for (int j = 0; j < 100; j++)
21                     {
22                         TcpClient client = new TcpClient();
23
24                         client.Connect(new System.Net.IPAddress(new byte[] { 127, 0, 0, 1 }), 2222);
25
26                         BinaryWriter bw = new BinaryWriter(client.GetStream());
27
28                         bw.Write(string.Format("你好,我来请求你! {0},当前线程:{1}", j, Thread.CurrentThread.ManagedThreadId));
29
30                         BinaryReader sr = new BinaryReader(client.GetStream());
31
32                         var s = sr.ReadString();
33
34                         Console.WriteLine("接受到数据:{0}", s);
35                     }
36                 });
37             }
38
39             Console.Read();
40         }
41     }
42 }
时间: 2024-11-03 21:15:31

TCP应用编程的相关文章

一种C# TCP异步编程中遇到的问题

最近在维护公司的一个socket服务端工具,该工具主要是提供两个socket server服务,对两端连接的程序进行数据的透明转发. 程序运行期间,遇到一个问题,程序的一端是GPRS设备,众所周知,GPRS设备的网络连接十分的不问题,由此会产生不少的"奇怪"问题.实际过程中,程序运行几个小时后,无线端的socket server断开就再也无法打开.找了很久都没发现. 通过wireshark抓取通信报文,一般是在TCP的三次握手时出的问题.常规的TCP三次握手,由TCP的标识可简单看作:

Java - TCP网络编程

Java - TCP网络编程 Server 逻辑思路: 创建ServerSocket(port),然后服务器的socket就启动了 循环中调用accept(),此方法会堵塞程序,直到发现用户请求,返回用户的socket 利用多线程对用户socket进行IO操作 注意:对Scoket/File进行创建.关闭,都需要放try catch中,检测 IOException,所以将网络IO部分整体放入try catch中即可. 1. 字符串操作 输出:PrintWriter out=new PrintWr

Go语言TCP Socket编程

Golang的主要 设计目标之一就是面向大规模后端服务程序,网络通信这块是服务端 程序必不可少也是至关重要的一部分.在日常应用中,我们也可以看到Go中的net以及其subdirectories下的包均是"高频+刚需",而TCP socket则是网络编程的主流,即便您没有直接使用到net中有关TCP Socket方面的接口,但net/http总是用到了吧,http底层依旧是用tcp socket实现的. 网络编程方面,我们最常用的就是tcp socket编程了,在posix标准出来后,s

Linux下TCP网络编程与基于Windows下C#socket编程间通信

一.linux下TCP网络编程基础,需要了解相关函数 Socket():用于套接字初始化. Bind():将 socket 与本机上的一个端口绑定,就可以在该端口监听服务请求. Listen():使socket处于被动的监听模式,并为该  socket  建立一个输入数据队列,将到达的服务器, 请求保存在此队列中,直到程序处理他们. Accept():让服务器接收客户的连接请求. Connect():客户端使用connect函数来配置 socket并与远端服务器建立一个 TCP 连接. Clos

TCP/UDP编程中的问题汇总

TCP/UDP编程中的问题汇总 TCP和UDP发送大文件的问题. 答: 发送端: 发送时,先发送文件的名称及大小等信息. 然后,设置一个缓冲区的大小,假设为4K. 再循环读4K的文件内容,并发送,直到发送完成. 最后,再发送完成标记. 接收端: 接收到第一个包时,得到文件的大小等信息. 计算出要接收多少个包. 然后,循环接收包,并将接收到的数据写入到文件中. 直到,接收到的数据长度等于文件的大小. struct package { 文件标识 //GUID 偏移量 //001- 数据段 //Byt

Linux下TCP网络编程与基于Windows下C#socket编程之间通信

一.linux下TCP网络编程基础,需要了解相关函数 Socket():用于套接字初始化. Bind():将 socket 与本机上的一个端口绑定,就可以在该端口监听服务请求. Listen():使socket处于被动的监听模式,并为该  socket  建立一个输入 数据队列,将到达的服务器, 请求保存在此队列中,直到程序处理他们. Accept():让服务器接收客户的连接请求. Connect():客户端使用connect函数来配置 socket并与远端服务器建立一个 TCP 连接. Clo

JAVA学习之TCP网络编程,Socket使用

ServerSocket 此类实现服务器套接字. ServerSocket常用的构造方法有以下几个, ServerSocket() 创建非绑定服务器套接字. ServerSocket(int port) 创建绑定到特定端口的服务器套接字. ServerSocket(int port, int backlog) 利用指定的 backlog 创建服务器套接字并将其绑定到指定的本地端口号. ServerSocket(int port, int backlog, InetAddress bindAddr

Java笔记二十四.TCP网络编程

 TCP网络编程 转载请表明出处:http://blog.csdn.net/u012637501(嵌入式_小J的天空) 从上面一节内容可以知道,利用UDP通信的两个程序是平等的,无主次之分,两个程序代码可以完全一样.但利用TCP协议进行通信的两个应用程序,是有主从之分的,一个称为服务器程序,另外一个称为客户机程序.Java中提供了ServerSocket类用于创建服务器端的socket,Socket类用于创建客户端socket. 一.APIs简介 java.net.ServerSocket (1

nodejs使用tcp协议编程(nodejs服务器端,java客户端)

var net = require ('net'); var HOST = '192.168.1.50'; var PORT = 8809; net.createServer(function(sock){ console.log('CONNECTED:'+sock.remoteAddress + ":"+ sock.remotePort); sock.on('data',function(data){ console.log('DATA'+sock.remoteAddress +&q

戏说TCP网络编程

1.何为TCP? ?? ???既然说到TCP协议网络编程,那么首先来了解下什么是TCP协议.TCP协议的全称叫Transmission Control Protocol 传输控制协议,是一种面向连接的.可靠的.基于字节流的传输层通信协议.在因特网协议族(Internet protocol suite)中,TCP层是位于IP层之上.? ?? ???面向连接是什么呢?面向连接可以理解为指定对象,就好像平时打电话一样,你要打电话需要电话号码,也就是需要指定打电话的对象:可靠就简单了,就是在传输的过程中