前言:

为什么会有如题的概念呢,我想对于没有主动听说过socket网络编程的人来说读到题目可能就已经蒙头了,为了很好的让大家进入场景,首先说一下一个需要用到这点东西的业务需求。

首先大家应该明确的是socket网络编程是以CS的模式下才有的,比如机房收费系统,在机房收费系统中可能会遇到不同的机房使用的收费系统是使用同一个数据库的。但是对于一些显示的信息,只有每次查询数据库的时候才能更新到窗体中,拿最简单的主界面的当前上机的人数来说,有机房A和机房B两个机房,并且他们是使用同一个数据库的,然后两个值班教师在同一时间工作,但机房A增加或减少上机的人数,机房B的值班教师是不能实时的接到消息并更新自己的窗体的。这就会导致窗体显示的信息暂时性的错误。这时就用到了我们的socket网络编程。

一、官方的解释socket机制:

在网络编程中最常用的方案便是Client/Server(客户机/服务器)模型。在这种方案中客户应用程序向服务器程序请求服务。一个服务程序通常在一个众所周知的地址监听对服务的请求,也就是说,服务进程一 直处于休眠状态,直到一个客户向这个服务的地址提出了连接请求。在这个时刻,服务程序被"惊醒"并且为客户提供服务-对客户的请求作出适当的反应。

为了方便这种Client/Server模型的网络编程,90年代初,由Microsoft联合了其他几家公司共同制定了一套WINDOWS下的网络编程接口,即WindowsSockets规范,它不是一种网络协议,而是一套开放的、支持多种协议的Windows下的网络编程接口。现在的Winsock已经基本上实现了与协议无关,你可以使用Winsock来调用多种协议的功能,但较常使用的是TCP/IP协议。Socket实际在计算机中提供了一个通信端口,可以通过这个端口与任何一个具有Socket接口的计算机通信。应用程序在网络上传输,接收的信息都通过这个Socket接口来实现。

二、通俗的理解socket

我们可以简单的把Socket理解为一个可以连通网络上不同计算机程序之间的管道,把一堆数据从管道的A端扔进去,则会从管道的B端(也许同时还可以从C、D、E、F……端冒出来)。管道的端口由两个因素来唯一确认,即机器的IP地址和程序所使用的端口号。IP地址的含义所有人都知道,所谓端口号就是程序员指定的一个数字,许多著名的木马程序成天在网络上扫描不同的端口号就是为了获取一个可以连通的端口从而进行破坏。比较著名的端口号有http的80端口,当然,建议大家自己写程序不要使用太小的端口号,它们一般被系统占用了,也不要使用一些著名的端口,一般来说使用1000~5000之内的端口比较好。

Socket可以支持数据的发送和接收,它会定义一种称为套接字的变量,发送数据时首先创建套接字,然后使用该套接字的send等方法对准某个IP/端口进行数据发送;接收端也首先创建套接字,然后将该套接字绑定到一个IP/端口上,所有发向此端口的数据会被该套接字的recv等函数读出。如同读出文件中的数据一样。

三、例子:

说了这么多我想大家对于socket 有了简单的认识,当然还是要在代码中深入的理解。

在看代码之前,还要做最后的解释,socket编程一定使用客户端和服务器的,虽然接下来的例子中只是一对一的通信,但其实和一对多的通信是一个原理的。

1.服务器代码

首先看服务器代码:

/*********************************************************
* 开发人员:韩义
* 创建时间:2013/9/27 13:51:48
* 描述说明:socket网络变成实例服务器
* 版本:1.0
* 版权所有:信息技术提高班
* *******************************************************/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets; namespace Server
{
public partial class server : Form
{ Socket s = null;
IPEndPoint iep = null;
byte[] buf = new byte[1024];
Socket worker = null; public server()
{
InitializeComponent();
Control.CheckForIllegalCrossThreadCalls = false;
}
//启动服务器。--韩义
private void button1_Click_1(object sender, EventArgs e)
{
//创建一个通道
s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //创建一个侦听点
iep = new IPEndPoint(IPAddress.Any, 20000); //绑定到通道上
s.Bind(iep); //侦听
s.Listen(6);
//通过异步来处理,开启监听连接,并交给Accept函数处理连接
s.BeginAccept(new AsyncCallback(Accept), s);
this.button1.Visible = false;
} //接收到连接的动作--韩义
void Accept(IAsyncResult ia)
{
//获取用户定义的对象,它限定或包含关于异步操作的信息。
s = ia.AsyncState as Socket;//此属性返回一个对象,该对象是启动异步操作的方法的最后一个参数。
worker = s.EndAccept(ia);//返回一个 Socket,它处理与远程主机的通信。
s.BeginAccept(new AsyncCallback(Accept), s);//重新接收链接,并制定回掉函数 try
{
//开始接受数据
worker.BeginReceive(buf, 0, buf.Length, SocketFlags.None, new AsyncCallback(Receive), worker);
}
catch
{ throw; }
} //收到消息的动作--韩义
void Receive(IAsyncResult ia)
{
//获取用户定义的对象,它限定或包含关于异步操作的信息。
worker = ia.AsyncState as Socket;
//获取数据长度
int count = worker.EndReceive(ia);
//自己开始接收数据。
worker.BeginReceive(buf, 0, buf.Length, SocketFlags.None, new AsyncCallback(Receive), worker);
//按GB2312的标准取出数据
string context = Encoding.GetEncoding("gb2312").GetString(buf, 0, count);
this.textBox1.Text += Environment.NewLine;
this.textBox1.Text += context;
}
//发送消息--韩义
private void button2_Click_1(object sender, EventArgs e)
{
string context = "管理员:" + this.textBox2.Text.Trim(); if (context != "")
{
this.textBox1.Text += Environment.NewLine;//换行
this.textBox1.Text += context;
this.textBox2.Text = "";
worker.Send(Encoding.GetEncoding("gb2312").GetBytes(context));
}
}
}
}

2.服务器界面:

3.客户端代码

/*********************************************************
* 开发人员:韩义
* 创建时间:2013/9/27 13:51:48
* 描述说明:socket网络变成实例客户端
* 版本:1.0
* 版权所有:信息技术提高班
* *******************************************************/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets; namespace Client
{
public partial class client : Form
{
Socket s = null;
IPEndPoint iep = null;
byte[] buf = new byte[1024]; public client()
{
InitializeComponent();
Control.CheckForIllegalCrossThreadCalls = false;
}
//连接服务器--韩义
private void button1_Click_1(object sender, EventArgs e)
{
s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
iep = new IPEndPoint(IPAddress.Parse("127.0.0.1"),20000);
try
{
s.Connect(iep); //建立与远程主机的连接
this.label1.Text = "连接成功";//连接成功提示
this.button1.Visible = false;//隐藏连接按钮
}
catch
{ throw; }
try
{
//开始接收连接。
s.BeginReceive(buf, 0, buf.Length, SocketFlags.None, new AsyncCallback(Receive), s);
}
catch
{ throw; }
}
//发送消息--韩义
private void button2_Click_1(object sender, EventArgs e)
{
string context = iep.ToString() + ":" + this.textBox2.Text.Trim();
if (context != "")
{
this.textBox1.Text += Environment.NewLine;
this.textBox1.Text += context;
this.textBox2.Text = "";
//发送消息
s.Send(Encoding.GetEncoding("gb2312").GetBytes(context));
}
} //收到消息的动作--韩义
void Receive(IAsyncResult ia)
{
s = ia.AsyncState as Socket;
int count = s.EndReceive(ia);
//自己开始接收数据
s.BeginReceive(buf, 0, buf.Length, SocketFlags.None, new AsyncCallback(Receive), s);
string context = Encoding.GetEncoding("gb2312").GetString(buf, 0, count);
this.textBox1.Text += Environment.NewLine;
this.textBox1.Text += context;
}
}
}

4.客户端界面:

当然大家会发现其实这就是一个聊天工具,和一个好友聊天就是一对一,群聊天就是一对多。这又进一步的帮助理解网络编程的含义。

四、总结:

通过以上的代码,我们可以大概的总结一下socket编程的几个步骤:

  1. 建立Socket

在服务器端建立一个监听的Socket,为此可以调用Socket()函数用来建立这个监听的Socket,并定义此Socket所使用的通信协议。此函数调用成功返回Socket对象,失败则返回INVALID_SOCKET

初始化调用的socket的构造函数,MSDN上共有三种构造函数重载,这里我们用的是第三种

Socket(AddressFamily, SocketType, ProtocolType)

使用指定的地址族、套接字类型和协议初始化 Socket 类的新实例。

  1. 绑定端口

接下来要为服务器端定义的这个监听的Socket指定一个地址及端口(Port),这样客户端才知道待会要连接哪一个地址的哪个端口,为此我们要调用bind()函数,该函数调用成功返回0,否则返回SOCKET_ERROR。

  1. 监听

当服务器端的Socket对象绑定完成之后,服务器端必须建立一个监听的队列来接收客户端的连接请求。listen()函数使服务器端的Socket进入监听状态,并设定可以建立的最大连接数(目前最大值限制为 6, 最小值为1)。该函数调用成功返回0,否则返回SOCKET_ERROR。

  1. 服务器端接受客户端的连接请求

当Client提出连接请求时,Server端监听视窗会收到客户端送来我们自定义的一个消息,这时,我们可以分析lParam,然后调用相关的函数来处理此事件。为了使服务器端接受客户端的连接请求,就要使用accept()函数,该函数新建一Socket与客户端的Socket相通,原先监听之Socket继续进入监听状态,等待他人的连接要求。该函数调用成功返回一个新产生的Socket对象,否则返回INVALID_SOCKET。

以上可以说是socket网络编程的核心内容。其实真的没有那么难理解

特别说明:

  1. 本实例只是一对一的通信,一对多的通信或多对多的通信只需在此基础上略加改动。
  2. 本实例只是很简单的小例子,有需要复用的代码请注意命名规范。

项目总结——深入浅出socket网络编程的更多相关文章

  1. 循序渐进Socket网络编程(多客户端、信息共享、文件传输)

    循序渐进Socket网络编程(多客户端.信息共享.文件传输) 前言:在最近一个即将结束的项目中使用到了Socket编程,用于调用另一系统进行处理并返回数据.故把Socket的基础知识总结梳理一遍. 1 ...

  2. windows socket 网络编程

    样例代码就在我的博客中,包含六个UDP和TCP发送接受的cpp文件,一个基于MFC的局域网聊天小工具project,和此小工具的全部执行时库.资源和执行程序.代码的压缩包位置是http://www.b ...

  3. Linux Socket 网络编程

    Linux下的网络编程指的是socket套接字编程,入门比较简单.在学校里学过一些皮毛,平时就是自学玩,没有见识过真正的socket编程大程序,比较遗憾.总感觉每次看的时候都有收获,但是每次看完了之后 ...

  4. Python Socket 网络编程

    Socket 是进程间通信的一种方式,它与其他进程间通信的一个主要不同是:它能实现不同主机间的进程间通信,我们网络上各种各样的服务大多都是基于 Socket 来完成通信的,例如我们每天浏览网页.QQ ...

  5. Python全栈【Socket网络编程】

    Python全栈[socket网络编程] 本章内容: Socket 基于TCP的套接字 基于UDP的套接字 TCP粘包 SocketServer 模块(ThreadingTCPServer源码剖析) ...

  6. python之Socket网络编程

    什么是网络? 网络是由节点和连线构成,表示诸多对象及其相互联系.在数学上,网络是一种图,一般认为专指加权图.网络除了数学定义外,还有具体的物理含义,即网络是从某种相同类型的实际问题中抽象出来的模型.在 ...

  7. Python之路【第七篇】python基础 之socket网络编程

    本篇文章大部分借鉴 http://www.cnblogs.com/nulige/p/6235531.html python socket  网络编程 一.服务端和客户端 BS架构 (腾讯通软件:ser ...

  8. 【深入浅出Linux网络编程】 "开篇 -- 知其然,知其所以然"

    [深入浅出Linux网络编程]是一个连载博客,内容源于本人的工作经验,旨在给读者提供靠谱高效的学习途径,不必在零散的互联网资源中浪费精力,快速的掌握Linux网络编程. 连载包含4篇,会陆续编写发出, ...

  9. Socket网络编程-基础篇

    Socket网络编程 网络通讯三要素: IP地址[主机名] 网络中设备的标识 本地回环地址:127.0.0.1 主机名:localhost 端口号 用于标识进程的逻辑地址 有效端口:0~65535 其 ...

随机推荐

  1. 分页技术之PageDataSource类

    之前给大家介绍了分页技术之Gridview控件,今天给大家介绍另外一种分页技术,采用PageDataSource类 + Repeater控件来实现. 前台只需要拖出一个Repeater控件来绑定要显示 ...

  2. 关于mtk Android打开串口权限问题

    最近在做一个测试串口读写回路的APK,jni代码部分遇到一个小小问题: fd = open(path_utf, O_RDWR);返回值是-1,要么就是权限问题,要么就是文件不存在所以需要打印错误信息, ...

  3. 关于Core Data的一些整理(五)

    关于Core Data的一些整理(五) 在Core Data中使用NSFetchedResultsController(以下简称VC)实现与TableView的交互,在实际中,使用VC有很多优点,其中 ...

  4. 为什么struts2 ajax 方法执行两次

    struts2中使用json插件执行ajax处理时,如果方法名是get方法的时候,方法会莫名其妙的执行两次. 原因: struts2 中JSON的原理是在ACTION中的get方法都会序列化,所以前面 ...

  5. 09_linux下安装Nvidia显卡驱动

    下载驱动 去官网找去,哈哈o(^▽^)o 安装kernel source [root@localhost ~]# yum install kernel-devel 如果还不行,试试下面的 [root@ ...

  6. 9个最新的手机/移动设备jQuery插件

    随着互联网的流行,移动网站开始急速增加,在2014年手机网站将会出现很多,所以手机网站是必须要学会制作的.手机网站不像桌面平台一样制作,否则会影响显示效果,目前大部分手机网站使用响应式设计技术,而且也 ...

  7. [Python笔记]第四篇:内置函数

    本篇主要内容:内置函数 函数 参考:https://docs.python.org/3.5/library/functions.html 内置函数列表 一.数学运算类 abs(x)求绝对值 >& ...

  8. debian小巧好看的桌面

    先看完,不然,你一定会后悔的..不好看,你打我.. sudo apt-get install xfce4 sudo apt-get install xfce4-goodies sudo apt-get ...

  9. Xcode can't verify the identity of the server

    当升级了苹果系统到 OS X El Captain 之后  ,打开Xcode 有时候会报错 如图 而且打开 svn  也会出类似错误  点击continue  了  下次 还会 出现 .这个很好解决 ...

  10. 构建高可用web站点学习(三)

    分布式的构建 做为网站访问的生命线(数据访问),当然也可以采用分布式的方法来减轻单台服务器的访问压力.之前有讲过Memcached的分布式,但是Memcached服务器互不通信,所以我们也提过redi ...