精华内容
下载资源
问答
  • 计算机网络socket编程

    千次阅读 2017-03-30 15:03:20
    ...Linux Socket编程(不限Linux) 2010-12-12 21:58 by 吴秦, 238665 阅读, 66 评论, 收藏, 编辑 “一切皆Socket!” 话虽些许夸张,但是事实也是,现在的网络编程几乎都是用的sock
    转自:http://www.cnblogs.com/skynet/archive/2010/12/12/1903949.html 
    

    Linux Socket编程(不限Linux)

    2010-12-12 21:58 by 吴秦, 238665 阅读, 66 评论, 收藏, 编辑

    “一切皆Socket!”

    话虽些许夸张,但是事实也是,现在的网络编程几乎都是用的socket。

    ——有感于实际编程和开源项目研究。

    我们深谙信息交流的价值,那网络中进程之间如何通信,如我们每天打开浏览器浏览网页时,浏览器的进程怎么与web服务器通信的?当你用QQ聊天时,QQ进程怎么与服务器或你好友所在的QQ进程通信?这些都得靠socket?那什么是socket?socket的类型有哪些?还有socket的基本函数,这些都是本文想介绍的。本文的主要内容如下:

    • 1、网络中进程之间如何通信?
    • 2、Socket是什么?
    • 3、socket的基本操作
      • 3.1、socket()函数
      • 3.2、bind()函数
      • 3.3、listen()、connect()函数
      • 3.4、accept()函数
      • 3.5、read()、write()函数等
      • 3.6、close()函数
    • 4、socket中TCP的三次握手建立连接详解
    • 5、socket中TCP的四次握手释放连接详解
    • 6、一个例子(实践一下)
    • 7、留下一个问题,欢迎大家回帖回答!!!

    1、网络中进程之间如何通信?

    本地的进程间通信(IPC)有很多种方式,但可以总结为下面4类:

    • 消息传递(管道、FIFO、消息队列)
    • 同步(互斥量、条件变量、读写锁、文件和写记录锁、信号量)
    • 共享内存(匿名的和具名的)
    • 远程过程调用(Solaris门和Sun RPC)

    但这些都不是本文的主题!我们要讨论的是网络中进程之间如何通信?首要解决的问题是如何唯一标识一个进程,否则通信无从谈起!在本地可以通过进程PID来唯一标识一个进程,但是在网络中这是行不通的。其实TCP/IP协议族已经帮我们解决了这个问题,网络层的“ip地址可以唯一标识网络中的主机,而传输层的“协议+端口可以唯一标识主机中的应用程序(进程)。这样利用三元组(ip地址,协议,端口)就可以标识网络的进程了,网络中的进程通信就可以利用这个标志与其它进程进行交互。

    使用TCP/IP协议的应用程序通常采用应用编程接口:UNIX  BSD的套接字(socket)和UNIX System V的TLI(已经被淘汰),来实现网络进程之间的通信。就目前而言,几乎所有的应用程序都是采用socket,而现在又是网络时代,网络中进程通信是无处不在,这就是我为什么说“一切皆socket”。

    2、什么是Socket?

    上面我们已经知道网络中的进程是通过socket来通信的,那什么是socket呢?socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,都可以用“打开open –> 读写write/read –> 关闭close”模式来操作。我的理解就是Socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭),这些函数我们在后面进行介绍。

    socket一词的起源

    在组网领域的首次使用是在1970年2月12日发布的文献IETF RFC33中发现的,撰写者为Stephen Carr、Steve Crocker和Vint Cerf。根据美国计算机历史博物馆的记载,Croker写道:“命名空间的元素都可称为套接字接口。一个套接字接口构成一个连接的一端,而一个连接可完全由一对套接字接口规定。”计算机历史博物馆补充道:“这比BSD的套接字接口定义早了大约12年。”

    3、socket的基本操作

    既然socket是“open—write/read—close”模式的一种实现,那么socket就提供了这些操作对应的函数接口。下面以TCP为例,介绍几个基本的socket接口函数。

    3.1、socket()函数

    int socket(int domain, int type, int protocol);

    socket函数对应于普通文件的打开操作。普通文件的打开操作返回一个文件描述字,而socket()用于创建一个socket描述符(socket descriptor),它唯一标识一个socket。这个socket描述字跟文件描述字一样,后续的操作都有用到它,把它作为参数,通过它来进行一些读写操作。

    正如可以给fopen的传入不同参数值,以打开不同的文件。创建socket的时候,也可以指定不同的参数创建不同的socket描述符,socket函数的三个参数分别为:

    • domain:即协议域,又称为协议族(family)。常用的协议族有,AF_INETAF_INET6AF_LOCAL(或称AF_UNIX,Unix域socket)、AF_ROUTE等等。协议族决定了socket的地址类型,在通信中必须采用对应的地址,如AF_INET决定了要用ipv4地址(32位的)与端口号(16位的)的组合、AF_UNIX决定了要用一个绝对路径名作为地址。
    • type:指定socket类型。常用的socket类型有,SOCK_STREAMSOCK_DGRAMSOCK_RAWSOCK_PACKETSOCK_SEQPACKET等等(socket的类型有哪些?)。
    • protocol:故名思意,就是指定协议。常用的协议有,IPPROTO_TCPIPPTOTO_UDPIPPROTO_SCTPIPPROTO_TIPC等,它们分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议(这个协议我将会单独开篇讨论!)。

    注意:并不是上面的type和protocol可以随意组合的,如SOCK_STREAM不可以跟IPPROTO_UDP组合。当protocol为0时,会自动选择type类型对应的默认协议。

    当我们调用socket创建一个socket时,返回的socket描述字它存在于协议族(address family,AF_XXX)空间中,但没有一个具体的地址。如果想要给它赋值一个地址,就必须调用bind()函数,否则就当调用connect()listen()时系统会自动随机分配一个端口。

    3.2、bind()函数

    正如上面所说bind()函数把一个地址族中的特定地址赋给socket。例如对应AF_INETAF_INET6就是把一个ipv4或ipv6地址和端口号组合赋给socket。

    int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

    函数的三个参数分别为:

    • sockfd:即socket描述字,它是通过socket()函数创建了,唯一标识一个socket。bind()函数就是将给这个描述字绑定一个名字。
    • addr:一个const struct sockaddr *指针,指向要绑定给sockfd的协议地址。这个地址结构根据地址创建socket时的地址协议族的不同而不同,如ipv4对应的是:
      struct sockaddr_in {
          sa_family_t    sin_family; /* address family: AF_INET */
          in_port_t      sin_port;   /* port in network byte order */
          struct in_addr sin_addr;   /* internet address */
      };
      
      /* Internet address. */
      struct in_addr {
          uint32_t       s_addr;     /* address in network byte order */
      };
      ipv6对应的是:
      struct sockaddr_in6 { 
          sa_family_t     sin6_family;   /* AF_INET6 */ 
          in_port_t       sin6_port;     /* port number */ 
          uint32_t        sin6_flowinfo; /* IPv6 flow information */ 
          struct in6_addr sin6_addr;     /* IPv6 address */ 
          uint32_t        sin6_scope_id; /* Scope ID (new in 2.4) */ 
      };
      
      struct in6_addr { 
          unsigned char   s6_addr[16];   /* IPv6 address */ 
      };
      Unix域对应的是:
      #define UNIX_PATH_MAX    108
      
      struct sockaddr_un { 
          sa_family_t sun_family;               /* AF_UNIX */ 
          char        sun_path[UNIX_PATH_MAX];  /* pathname */ 
      };
    • addrlen:对应的是地址的长度。

    通常服务器在启动的时候都会绑定一个众所周知的地址(如ip地址+端口号),用于提供服务,客户就可以通过它来接连服务器;而客户端就不用指定,有系统自动分配一个端口号和自身的ip地址组合。这就是为什么通常服务器端在listen之前会调用bind(),而客户端就不会调用,而是在connect()时由系统随机生成一个。

    网络字节序与主机字节序

    主机字节序就是我们平常说的大端和小端模式:不同的CPU有不同的字节序类型,这些字节序是指整数在内存中保存的顺序,这个叫做主机序。引用标准的Big-Endian和Little-Endian的定义如下:

      a) Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。

      b) Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。

    网络字节序:4个字节的32 bit值以下面的次序传输:首先是0~7bit,其次8~15bit,然后16~23bit,最后是24~31bit。这种传输次序称作大端字节序。由于TCP/IP首部中所有的二进制整数在网络中传输时都要求以这种次序,因此它又称作网络字节序。字节序,顾名思义字节的顺序,就是大于一个字节类型的数据在内存中的存放顺序,一个字节的数据没有顺序的问题了。

    所以:在将一个地址绑定到socket的时候,请先将主机字节序转换成为网络字节序,而不要假定主机字节序跟网络字节序一样使用的是Big-Endian。由于这个问题曾引发过血案!公司项目代码中由于存在这个问题,导致了很多莫名其妙的问题,所以请谨记对主机字节序不要做任何假定,务必将其转化为网络字节序再赋给socket。

    3.3、listen()、connect()函数

    如果作为一个服务器,在调用socket()bind()之后就会调用listen()来监听这个socket,如果客户端这时调用connect()发出连接请求,服务器端就会接收到这个请求。

    int listen(int sockfd, int backlog);
    int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

    listen函数的第一个参数即为要监听的socket描述字,第二个参数为相应socket可以排队的最大连接个数。socket()函数创建的socket默认是一个主动类型的,listen函数将socket变为被动类型的,等待客户的连接请求。

    connect函数的第一个参数即为客户端的socket描述字,第二参数为服务器的socket地址,第三个参数为socket地址的长度。客户端通过调用connect函数来建立与TCP服务器的连接。

    3.4、accept()函数

    TCP服务器端依次调用socket()bind()listen()之后,就会监听指定的socket地址了。TCP客户端依次调用socket()connect()之后就想TCP服务器发送了一个连接请求。TCP服务器监听到这个请求之后,就会调用accept()函数取接收请求,这样连接就建立好了。之后就可以开始网络I/O操作了,即类同于普通文件的读写I/O操作。

    int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

    accept函数的第一个参数为服务器的socket描述字,第二个参数为指向struct sockaddr *的指针,用于返回客户端的协议地址,第三个参数为协议地址的长度。如果accpet成功,那么其返回值是由内核自动生成的一个全新的描述字,代表与返回客户的TCP连接。

    注意:accept的第一个参数为服务器的socket描述字,是服务器开始调用socket()函数生成的,称为监听socket描述字;而accept函数返回的是已连接的socket描述字。一个服务器通常通常仅仅只创建一个监听socket描述字,它在该服务器的生命周期内一直存在。内核为每个由服务器进程接受的客户连接创建了一个已连接socket描述字,当服务器完成了对某个客户的服务,相应的已连接socket描述字就被关闭。

    3.5、read()、write()等函数

    万事具备只欠东风,至此服务器与客户已经建立好连接了。可以调用网络I/O进行读写操作了,即实现了网咯中不同进程之间的通信!网络I/O操作有下面几组:

    • read()/write()
    • recv()/send()
    • readv()/writev()
    • recvmsg()/sendmsg()
    • recvfrom()/sendto()

    我推荐使用recvmsg()/sendmsg()函数,这两个函数是最通用的I/O函数,实际上可以把上面的其它函数都替换成这两个函数。它们的声明如下:

           #include <unistd.h>
    
           ssize_t read(int fd, void *buf, size_t count);
           ssize_t write(int fd, const void *buf, size_t count);
    
           #include <sys/types.h>
           #include <sys/socket.h>
    
           ssize_t send(int sockfd, const void *buf, size_t len, int flags);
           ssize_t recv(int sockfd, void *buf, size_t len, int flags);
    
           ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
                          const struct sockaddr *dest_addr, socklen_t addrlen);
           ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                            struct sockaddr *src_addr, socklen_t *addrlen);
    
           ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
           ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
    

    read函数是负责从fd中读取内容.当读成功时,read返回实际所读的字节数,如果返回的值是0表示已经读到文件的结束了,小于0表示出现了错误。如果错误为EINTR说明读是由中断引起的,如果是ECONNREST表示网络连接出了问题。

    write函数将buf中的nbytes字节内容写入文件描述符fd.成功时返回写的字节数。失败时返回-1,并设置errno变量。 在网络程序中,当我们向套接字文件描述符写时有俩种可能。1)write的返回值大于0,表示写了部分或者是全部的数据。2)返回的值小于0,此时出现了错误。我们要根据错误类型来处理。如果错误为EINTR表示在写的时候出现了中断错误。如果为EPIPE表示网络连接出现了问题(对方已经关闭了连接)。

    其它的我就不一一介绍这几对I/O函数了,具体参见man文档或者baidu、Google,下面的例子中将使用到send/recv。

    3.6、close()函数

    在服务器与客户端建立连接之后,会进行一些读写操作,完成了读写操作就要关闭相应的socket描述字,好比操作完打开的文件要调用fclose关闭打开的文件。

    #include <unistd.h>
    int close(int fd);

    close一个TCP socket的缺省行为时把该socket标记为以关闭,然后立即返回到调用进程。该描述字不能再由调用进程使用,也就是说不能再作为read或write的第一个参数。

    注意:close操作只是使相应socket描述字的引用计数-1,只有当引用计数为0的时候,才会触发TCP客户端向服务器发送终止连接请求。

    4、socket中TCP的三次握手建立连接详解

    我们知道tcp建立连接要进行“三次握手”,即交换三个分组。大致流程如下:

    • 客户端向服务器发送一个SYN J
    • 服务器向客户端响应一个SYN K,并对SYN J进行确认ACK J+1
    • 客户端再想服务器发一个确认ACK K+1

    只有就完了三次握手,但是这个三次握手发生在socket的那几个函数中呢?请看下图:

    image

    图1、socket中发送的TCP三次握手

    从图中可以看出,当客户端调用connect时,触发了连接请求,向服务器发送了SYN J包,这时connect进入阻塞状态;服务器监听到连接请求,即收到SYN J包,调用accept函数接收请求向客户端发送SYN K ,ACK J+1,这时accept进入阻塞状态;客户端收到服务器的SYN K ,ACK J+1之后,这时connect返回,并对SYN K进行确认;服务器收到ACK K+1时,accept返回,至此三次握手完毕,连接建立。

    总结:客户端的connect在三次握手的第二个次返回,而服务器端的accept在三次握手的第三次返回。

    5、socket中TCP的四次握手释放连接详解

    上面介绍了socket中TCP的三次握手建立过程,及其涉及的socket函数。现在我们介绍socket中的四次握手释放连接的过程,请看下图:

    image

    图2、socket中发送的TCP四次握手

    图示过程如下:

    • 某个应用进程首先调用 close主动关闭连接,这时TCP发送一个FIN M;
    • 另一端接收到FIN M之后,执行被动关闭,对这个FIN进行确认。它的接收也作为文件结束符传递给应用进程,因为FIN的接收意味着应用进程在相应的连接上再也接收不到额外数据;
    • 一段时间之后,接收到文件结束符的应用进程调用 close关闭它的socket。这导致它的TCP也发送一个FIN N;
    • 接收到这个FIN的源发送端TCP对它进行确认。

    这样每个方向上都有一个FIN和ACK。

    6、一个例子(实践一下)

    说了这么多了,动手实践一下。下面编写一个简单的服务器、客户端(使用TCP)——服务器端一直监听本机的6666号端口,如果收到连接请求,将接收请求并接收客户端发来的消息;客户端与服务器端建立连接并发送一条消息。

    服务器端代码:

    服务器端
            
    展开全文
  • 计算机网络-实验报告5tcpip socket 高级编程。观看视频来自小破站。
  • 计算机网络Socket编程

    2008-06-06 11:18:50
    服务器和客户端的Socket 编程
  • 实 验 报 告 课程名称 实验项目名称 实验时间日期及节次 专业 计算机网络 Socket通信 4.16-4.30 第 1节-第 2节 计算机科学与技术 学生所在学院 计算机学院 年级 姓名 实验室名称 实验成绩 教师签字 2011级 学号 ...
  • 本课程源于天津大学开设的计算机网络,使用JAVA实现了一个简易微信,主要功能包括(局域网聊天,添加好友,群发消息,局域网搜索,注册新用户,修改密码等功能),资源包括源代码,exe文件和文档。大作业得分100分,...
  • 计算机写的网络套接字,希望对你有所帮助!!!
  • 实 验 报 告 课程名称 计算机网络 实验项目名称 Socket通信 4.16-4.30 实验时间 第 1 节-第 2 节 日期及节次 计算机学院 专业 计算机科学与技术 学生所在学院 年级 2011级 学号 20111913 陈声晓 战扬 姓名 指导教师 ...
  • 支持如下功能: 新用户的注册、登录以及密码找回功能;在线点到点文本聊天功能;点到点离线文本聊天功能;点到点可靠文件传输功能;传输消息加密功能。 内部包含可运行的客户端和服务端软件
  • 实 验 报 告 课程名称 计算机网络 实验项目名称 Socket通信 4.16-4.30 实验时间 第 1 节-第 2 节 日期及节次 计算机学院 专业 计算机科学与技术 学生所在学院 年级 2011级 学号 20111913 陈声晓 战扬 姓名 指导教师 ...
  • 计算机网络socket编程实验,包括TCP和UDP两种连接方式
  • 计算机网络Socket网络编程实验 写在开头 :实验写完好久了,一直没抽出时间写这个博客 还是太懒了啊 注:这次实验代码仅供参考学习,照搬抄袭不可取,有可能实验0分 5-1 Socket网络编程 题目: 1.使用InetAddress类的...

    计算机网络Socket网络编程实验

    写在开头 :实验写完好久了,一直没抽出时间写这个博客 还是太懒了啊

    注:这次实验代码仅供参考学习,照搬抄袭不可取,有可能实验0分


    5-1 Socket网络编程

    题目:
    1.使用InetAddress类的方法获取本地机的名称和IP地址。
    2.使用InetAddress类的方法获取网站www.csdn.net的IP地址,如果存在多个IP地址,要求全部返回。
    3.使用URL类下载深圳大学首页http://www.szu.edu.cn,并统计下载得到网页文件的大小


    代码实现

    1. 创建 InetAddress对象getHostAddress() 和getHostName()即可

    public class get_IP {
    	public static void main(String[] args) throws UnknownHostException {
    		// TODO 自动生成的方法存根
    		InetAddress i_Address=InetAddress.getLocalHost();
    		System.out.println("本机ip地址为: "+i_Address.getHostAddress());
    		System.out.println("本机名为 : "+i_Address.getHostName());
    	}
    }
    

    实验截图:
    在这里插入图片描述


    2.同理 创建InetAddress对象 采用getByName方法
    然后getHostAddress()

    代码实现:

    InetAddress CS_Address=InetAddress.getByName("www.csdn.com");
                System.out.println("CSDN的IP地址为:"+CS_Address.getHostAddress());
    

    实验截图:
    在这里插入图片描述


    3. 以网址创建url对象 写入即可

    代码实现:

    try{
    //下载指定URL的资源文件
    String urlString="http://www.szu.edu.cn";
    URL url=new URL(urlString);
    InputStream in=url.openStream();
    FileOutputStream fout=new FileOutputtream(newFile("深大首页.htm"));int byteNum=0;
    for(int i=0;i>-1;byteNum++t){
    i=in.read();
    fout.write(i);
    System.out.print("下载的网页文件大小:"+Integer.toString(byteNum));catch(MalformedURLException e)
    System.out.printIn("创建URL类对家失败"+e);
    catch(Exception e)
    System.out.printlIn("其他异常"+e);
    
    

    实验截图:
    在这里插入图片描述
    至此 5-1实验结束


    实验5-2 Socket网络编程

    习题1

    利用Socket类和ServerSocket类编写一个C/S程序,实现C/S通信。
    客户端向服务器端发送Time命令,服务器端接受到该字符串后将服务器端当前时间返回给客户端;客户端向服务器端发送Exit命令,服务器端向客户端返回“Bye”后退出。
    编写完整程序;一个服务器端程序,一个客户端程序。服务器端和客户端都需要打印出接受到的消息和发出的命令。
    下图为运行结果示例
    在这里插入图片描述


    习题2
    编写一数据报通信程序,实现简单的聊天功能。
    “聊天内容”和“输入文本”分别为当前聊天的历史信息和当前要传送出去的聊天文本。“确定”、“清空”、“退出”三个按钮分别实现发送当前聊天文本、清空当前聊天文本和退出系统的功能。
    界面可参考如下格式
    在这里插入图片描述


    这两道题其实是考察Socket类的使用

    先说习题1

    客户端部分创建socket对象 利用OutputStream传递消息
    服务器部分创建相同套接字socket 利用InputStream读取,字符串判断输出数据

    代码实现:

    //服务器部分
    			ServerSocket server = new ServerSocket(12345);
    			System.out.println("服务器启动完毕");
    			Socket socket = server.accept();
    			System.out.println("创建客户连接");
    			InputStream input = socket.getInputStream();
    			InputStreamReader isreader = new InputStreamReader(input);
    			BufferedReader reader = new BufferedReader(isreader);
    			while (true) {
    				String str = reader.readLine();
    				if (str.equals("exit")) {
    
    					System.out.println("Bye");
    					break;
    				}
    				if (str.equals("Time")) {
    					 SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
    			          System.out.println("服务器当前的时间为: "+ df.format(new Date()));// new Date()为获取当前系统时间
    				}
    			}
    
    //客户端部分
    	Socket socket = new Socket("localhost", 12345);
    			OutputStream out = socket.getOutputStream();
    			out.write("Time\n".getBytes());
    			out.write("exit\n".getBytes());
    

    实验截图:
    在这里插入图片描述


    接下来习题2

    在写习题2之前需要简单学习 图形化编程 学会 JFrame布局
    然后涉及的计算机网络知识是UDP数据传输
    由于为开放图形化编程 这里不给出具体实现代码
    仅作简单指示
    1.界面布局部分:
    聊天界面采用JFrame布局 BorderLayout() 东西南北布局

    	private JTextArea text; //聊天界面
    	private	JTextField ipText; //ip地址显示
    	private	JTextField sendText; //输入行
    	private	JButton sendbutton; //发送按钮
    	private	JButton clearbutton; //清空按钮
    

    发送与清空按钮对应写的函数
    发送调用UDP传输
    清空调用 text的 clear函数清空聊天界面

    2.UDP传输部分
    这里给出简单的UDP连接例子 通过如下代码变形即可

    //接收方
    	public static void main(String[] args) throws IOException {
    			// TODO 自动生成的方法存根
    			DatagramSocket mysocket=new DatagramSocket(6666); //建立socket端口
    			while(true){
    			System.out.println("请输入");
    			Scanner IN=new Scanner(System.in);
    	        String msg = IN.nextLine();
    	        //发送信息到客户端B
    	        System.out.println("开始发送数据:"+msg);
    	        byte[] buf = msg.getBytes();	        
    	        InetAddress toIp = InetAddress.getLocalHost();
    	        // 构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。
    	        DatagramPacket dp = new DatagramPacket(buf,buf.length,toIp,7777);	        
    	        //用数据报包的套接字,通过7777端口发送数据包
    	        mysocket.send(dp);    
    	        //接收客户端B的信息
    	        byte[] recBuf = new byte[1024];
    	        DatagramPacket recDp = new DatagramPacket(recBuf,recBuf.length);
    	        //信息接收
    	        mysocket.receive(recDp);        
    	        String recMsg = new String(recBuf,0,recDp.getLength());
    	        System.out.println("用户B说: "+recMsg);			
    			}
    		}
    
    //发送方
    		DatagramSocket mysocket=new DatagramSocket(7777);
    		while(true) {
    		byte[] data=new byte[1024];
    		DatagramPacket pack=new DatagramPacket(data,data.length);
    		mysocket.receive(pack);
    		String Mesg= new String(data,0,pack.getLength());
    		System.out.println("用户A说"+Mesg);
    		//发送返回消息
    		System.out.println("请输入信息");
    		Scanner IN=new Scanner(System.in);
    		String msg=IN.nextLine(); //输入
    		System.out.println("开始发送信息: "+msg);
    		InetAddress toIp = InetAddress.getLocalHost();
    		byte[] buf = msg.getBytes();
    		DatagramPacket dp = new DatagramPacket(buf,buf.length,toIp,6666);
    		mysocket.send(dp);
    	}
    

    启动两个 开始简单交互
    在这里插入图片描述

    3.合并图形界面与UDP交流并添加view函数循环输出接受到的信息到text
    在这里插入图片描述


    实验5-3 Socket网络编程

    利用Socket类和ServerSocket类,编写一个C/S程序,实现网络文件传输。
    客户端向服务器端发送请求,服务器端当接受到客户端的请求之后,先向其传输文件名,当客户端接受完毕之后,向客户端传输文件
    客户端连上服务器后接收传输文件,并进行改名(文件名可自行定义)存在本地。
    编写完整程序;一个服务器端程序,一个客户端程序。服务器端和客户端都需要打印出交互过程。
    下图为运行结果示例
    在这里插入图片描述
    在这里插入图片描述

    实验3要求掌握Socket类和ServerSocket类传输文件
    通过OutputStream BufferedInputStream BufferedOutputStream即可实现传输
    仅附上客户端简单实现代码

    Socket Client=new Socket("localhost",7777);
    		System.out.println("连接服务器成功!");
    		BufferedInputStream In_buf =new BufferedInputStream(Client.getInputStream());
    		BufferedOutputStream Out_buf = new BufferedOutputStream(new FileOutputStream("D:\\c++\\dev-cpp_gr.zip"));
    		byte [] buf = new byte[2048];
    		int len = 0;
    		while( (len = In_buf.read(buf)) != -1 ) {
    			Out_buf.write(buf, 0, len);
    		}
    		Out_buf.flush();
    

    实验截图:
    在这里插入图片描述


    好了 完成了 王者荣耀冲冲冲!!!

    展开全文
  • C++实现,MFC应用程序。客户端与服务器之间进行数据传输,源码打包了,直接运行就行,绝对满足老师的要求,代码部分有注释,容易看懂。
  •   通过实验,使学生熟悉并掌握计算机Windows 编程的基本知识,进一步加深学生对课堂所学基本内容的理解,掌握基本的Windows编程技巧,通过实验使得学生能够进行一些简单的网络程序设计。 二、实验内容 了解基本的...

    实验2《Windows Socket编程》

    一、实验目的

      通过实验,使学生熟悉并掌握计算机Windows 编程的基本知识,进一步加深学生对课堂所学基本内容的理解,掌握基本的Windows编程技巧,通过实验使得学生能够进行一些简单的网络程序设计。

    二、实验内容
    1. 了解基本的Socket知识
    2. 基于java完成Socket编程,设计并实现一个简单的聊天系统,包括客户端及服务器端。
      2.1 完成服务端使用telnet与服务器通信
      2.2 完成客户端与服务端通信
      2.3 完成基于多线程的实现服务端可以与多个客户端通信
    3. 可选,重构现有代码完成带界面的软件。实现各客户端之间聊天,以及多人聊天室。
    三、实验方法

      实验方法为利用Intellij IDEA开发工具,JAVA编程语言实现,参考过往实验资料与网络资料之后自己实现完成。

    四、实验步骤
    1. 开启本机的telnet服务,在终端输入telnet可进行连接,输入?可查看帮助信息。
      在这里插入图片描述
      在这里插入图片描述
    2. 打开Intellij IDEA开发工具进行项目程序编写;
      2.1 实现了一个简单的服务端: start函数负责建立服务端,等待连接,stop函数负责关闭连接以及相关的io流。Serversocket对象创建以后accept函数等待客户端连接。若没有客户端连接上,则会一直轮询,直到有客户端连接上,继续执行下面逻辑。当建立连接以后,双方建立通信管道,io流读取与写入数据。完成socket通信。
    //sampleServer.java
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.io.PrintWriter;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class sampleServer {
        private ServerSocket serverSocket;
        private Socket clientSocket;
        private PrintWriter out;
        private BufferedReader in;
    
        //建立服务端,等待连接
        public void start(int port) throws Exception{
            serverSocket = new ServerSocket(port);
            clientSocket = serverSocket.accept();
            out = new PrintWriter(clientSocket.getOutputStream(), true);
            in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
            String inputLine;
            while ((inputLine = in.readLine()) != null){
                if(".".equals(inputLine)){
                    out.println("good bye");
                    stop();
                    break;
                }else{
                    out.println("server got msg: "+inputLine);
                }
            }
        }
    
        //关闭连接以及相关的io流
        public void stop() throws Exception{
            in.close();
            out.close();
            clientSocket.close();
            serverSocket.close();
        }
    
        public static void main(String[] args){
            try {
                sampleServer server = new sampleServer();
                server.start(23);
            }catch (Exception ex){
                ex.printStackTrace();
            }
        }
    }
    

      此时,可以使用telnet连接,输入信息,即可发送给服务端。服务端接收到处理后返回。
    在这里插入图片描述
    在这里插入图片描述

      2.2 完成客户端与服务端通信
      在完成了可以使用telnet连接,并与之通信的服务器以后,我们编写自己的客户端代码与服务器进行通信。代码很简单。
      StartConnection函数指定ip与端口,若与服务器成功建立连接,则获取建立的通道的io流,out与in输入输出流,来实现后续与服务端的消息接收与发送。
      sendMessage函数基于io流发送消息。
      StopConnection关闭与服务端的连接。
      主函数获得用户在命令行的输入,发送给服务端。

    //sampleClient.java
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.io.PrintWriter;
    import java.net.Socket;
    import java.util.Scanner;
    
    public class sampleClient {
        private Socket clientSocket;
        private PrintWriter out;
        private BufferedReader in;
    
        //指定ip和端口
        public void startConnection(String ip, int port)throws Exception{
            clientSocket = new Socket(ip, port);
            out = new PrintWriter(clientSocket.getOutputStream(),true);
            in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
        }
    
        //基于IO流发消息
        public String sendMessage(String msg)throws Exception{
            out.println(msg);
            String resp = in.readLine();
            return resp;
        }
    
        //关闭与服务端的连接
        public void stopConnection(){
            try {
                in.close();
                out.close();
                clientSocket.close();
            }catch (Exception ex){
                ex.printStackTrace();
            }
        }
    
        public static void main(String[] args){
            try{
                //bulid the connection
                sampleClient client = new sampleClient();
                client.startConnection("127.0.0.1",23);
                //recevice the input string from termnal and send it to server
                Scanner sc = new Scanner((System.in));
                while (true){
                    String response = client.sendMessage(sc.nextLine());
                    System.out.println(response);
                    if(response.equals("good bye")){
                        client.stopConnection();
                        break;
                    }
                }
            }catch (Exception ex){
                ex.printStackTrace();
            }
        }
    }
    

      2.3 完成基于多线程的实现服务端可以与多个客户端通信
      完成以上实验,即可使用socket实现客户端与服务端之间的交互,进行简单的消息发送与接收。接下来我们可以实现多线程技术。
      将上面服务器代码的获取io流,收发消息代码移植到clientHandler类中,该类继承自thread类。
      修改start函数,依然是在本地的一个端口进行监听,但是我们这里使用一个循环来将每一个连接上来的client交给clientHandler来进行处理,这样主进程就不会阻塞,可以继续接收新客户端的连接,从而实现一个服务端连接多个客户端并与之通信的功能。
      同时需要注意,我们使用一个clientList来维护所有的客户端。代码如下所示:

    //clientList.java
    import java.util.ArrayList;
    
    public class clientList {
        public static ArrayList clientList;
    
        static {
            clientList = new ArrayList<multiServer.clientHandler>();
        }
    }
    
    //multiServer.java
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.io.PrintWriter;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class multiServer {
        private ServerSocket serverSocket;
    
        public void start(int port)throws Exception{
            serverSocket = new ServerSocket(port);
            while (true){
                clientHandler client = new clientHandler(serverSocket.accept());
                clientList.clientList.add(client);
                client.start();
            }
        }
    
        public void stop() throws Exception{
            serverSocket.close();
        }
    
        public static class clientHandler extends Thread{
            private Socket clientSocket;
            private PrintWriter out;
            private BufferedReader in;
    
            public clientHandler(Socket socket){
                this.clientSocket = socket;
            }
    
            public void run(){
                try{
                    out = new PrintWriter(clientSocket.getOutputStream(),true);
                    in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
                    String inputLine;
                    while ((inputLine = in.readLine()) != null){
                        if(".".equals(inputLine)){
                            out.println("good bye");
                            break;
                        }
                        out.println("msg from client" + clientList.clientList.indexOf(this) + "--msg:" + inputLine);
                    }
                    in.close();
                    out.close();
                    clientSocket.close();
                }catch (Exception ex){
                    ex.printStackTrace();
                }
            }
        }
    }
    
    //main.java
    public class main {
        public static void main(String[] args){
            try{
                new multiServer().start(23);
            }catch (Exception ex){
                ex.printStackTrace();
            }
        }
    }
    
    五、实验结果

      实验运行步骤及结果如下所示:

    1. 在Intellij IDEA中运行main函数;
    2. 运行命令行,输入telnet,连接telnet服务,再输入o,输入连接主机 localhost;
      在这里插入图片描述
    3. 接下来便可以运行第一个客户端,客户端即可输入信息,服务端可以反馈;
      在这里插入图片描述
    4. 重复第二步第三步即可开启多个客户端;
      在这里插入图片描述
      在这里插入图片描述
    六、实验小结

      本次实验是要是了解socket编程知识,客户端与服务端的交互,多阅读相关资料熟悉实验中需使用的方法就会轻松很多。

    展开全文
  • 计算机网络 socket编程实现服务器端与客户端连接 服务器端 #include <stdio.h> #include <stdlib.h> #include <winsock2.h> int main() { WSADATA wsaData; WSAStartup(MAKEWORD(2,2),&...

    计算机网络 socket编程实现服务器端与客户端连接

    服务器端

    #include <stdio.h>
    #include <stdlib.h>
    #include <winsock2.h>
    
    int main()
    {
        WSADATA wsaData;
        WSAStartup(MAKEWORD(2,2),&wsaData);
        if(LOBYTE(wsaData.wVersion)!=2 || HIBYTE(wsaData.wVersion)!=2)
        {
            printf("fail");
            return -1;
        }
    
        SOCKET serverSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
        SOCKADDR_IN serverAddr;     //声明一个SOCKADDR_IN变量,表示服务器
        serverAddr.sin_family = AF_INET;  //必须和创建socket的IP协议一致
        serverAddr.sin_port=htons(8888);  // //服务器端口,客户端通过这个端口连接
        serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); //ip用宏INADDR_ANY代替,代表0.0.0.0,表明所有地址
    
       if(SOCKET_ERROR == bind(serverSocket , (SOCKADDR*)&serverAddr , sizeof(serverAddr))) //绑定
        {
            printf("绑定失败\n");
            closesocket(serverSocket);  //释放socket
            WSACleanup();  //关闭套接字
            return -1;
    	}
    
         printf("绑定成功\n");
    
        listen(serverSocket, 10);//置socket为被动方式
        //等待客户连接
        SOCKADDR_IN clientAddr;
        int len = sizeof(clientAddr);
    
        //接受连接
        SOCKET clientSocket = accept(serverSocket,(SOCKADDR*)&clientAddr, &len);    //阻塞函数
        if(clientSocket == INVALID_SOCKET)
        {
          printf("连接失败");
         closesocket(serverSocket);    //释放socket
         WSACleanup();   //关闭套接字
          return -1 ;
        }
        printf("连接成功\n");
        printf("客户端地址为: %s\n" , inet_ntoa(clientAddr.sin_addr));
    
        char recvBuff[128] = {};
        //开始通讯
        while(1)
        {
          memset(recvBuff, 0 , sizeof(recvBuff));  //初始化recvBuff
          if(recv(clientSocket , recvBuff, sizeof(recvBuff)-1 , 0) >0)  //阻塞函数
          {
               printf("我是服务器,我收到客户端的信息为:  %s\n" , recvBuff);
          }
          else printf("我是服务器,未收到客户端信息");
    
          if(strcmp(recvBuff,"exit")==0) break; //客户端发送exit时,结束通信
    
          char sendBuff[128] = {};
          memset(sendBuff, 0 , sizeof(sendBuff)); //初始化sendBuff
          printf("\n服务器准备向客户端发送信息......\n");
          printf("请输入要发送的信息:\n");
          scanf("%s" , sendBuff);
          if(strcmp(sendBuff,"exit")==0) break; //服务器发送exit时结束通信
          //一次收发
          send(clientSocket , sendBuff, strlen(sendBuff), 0);
        }
        //关闭socket
        closesocket(clientSocket);
        closesocket(serverSocket);
        WSACleanup();
        return 0;
    }
    
    

    客户端

    #include <stdio.h>
    #include <stdlib.h>
    #include <winsock2.h>
    int main()
    {
        WSADATA wsaData;
        WSAStartup(MAKEWORD(2,2),&wsaData);
        if(LOBYTE(wsaData.wVersion)!=2 || HIBYTE(wsaData.wVersion)!=2)
        {
          printf("请求版本失败");
          return -1;
        }
    
        SOCKET clientSocket= socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
        if(INVALID_SOCKET == clientSocket)
        {
           printf("套接字创建失败");
           return -1;
         }
        SOCKADDR_IN clientAddr; //初始化协议地址
        clientAddr.sin_family = AF_INET;//必须和创建socket的IP协议一致
        clientAddr.sin_port = htons(8888);    //服务器端口,客户端通过这个端口连接
    
        //ip地址是点分格式的字符串 , 用inet_addr来转换整数
        clientAddr.sin_addr.S_un.S_addr =inet_addr("127.0.0.1");
     if( connect(clientSocket , (SOCKADDR *)&clientAddr , sizeof(clientAddr))<0)
        {
          printf("连接失败");
          closesocket(clientSocket);    //释放socket
          WSACleanup();   //关闭套接字
          return -1 ;
        }
        printf("连接成功\n\n");
        char sendBuff[128] = {};
        //开始通讯
        while(1)
        {
          memset(sendBuff, 0 , sizeof(sendBuff)); //初始化sendBuff
          printf("请输入客户端向服务器发送的信息:\n");
          scanf("%s" , sendBuff);
          //一次收发
          send(clientSocket , sendBuff, strlen(sendBuff), 0);
    
          char recvBuff[128] = {};
          memset(recvBuff, 0 , sizeof(recvBuff)); //初始化recvBuff
          if(recv(clientSocket , recvBuff, sizeof(recvBuff)-1 , 0) >0)  //阻塞函数
          {
               printf("我是客户端,收到的服务器信息为:%s\n" , recvBuff);
          }
          else printf("客户端未收到服务器信息");
        }
        return 0;
    }
    
    

    使用cmd运行即可

    展开全文
  • socket网络编程大作业

    2014-12-21 16:55:03
    这是有关用户与服务器之间的传输,里面含有tcp协议的,对网络应用有很多的帮助
  • 计算机网络实验——基于TCP协议的socket编程

    万次阅读 多人点赞 2018-06-15 16:44:03
    2. 熟悉c++、Java等高级编程语言网络编程的基本操作。3. 基本了解对话框应用程序的编写过程。4. 实现TCP套接字编程。 二、实验内容(一)实验思路1、学习理解TCP协议。2、实现TCP客户端之间多线程通信以及聊天...
  • 计算机网络课程实际,基于soket编程的网络聊天室
  • 这个是计算机网络原理的实验一的内容,基于Windows Socket编程,设计并实现一个简单的聊天系统,包括客户端及服务器端。
  • 利用C++语言,分别基于TCP和UDP编写一个简单的Client/Server网络应用程序。要求实现客户向服务器传输任意一个字符串,服务器将收到的字符串变换成大写后传回客户。修改上述程序,实现服务器根据客户请求,将服务器端...
  • socket编程原理

    2018-11-22 11:22:21
    第二章socket 编程原理 2.1 问题的引入 UNIX 系统的 I/O 命令集,是从 Maltics 和早期系统中的命令演变出来的,其模式为打开一读/写一 ...在 UNIX 系统中,网络应用编程界面有两类:UNIX BSD 的套接字(socket)和 UNIX
  • 基于安卓客户端与服务器的之间的socket通讯
  • C# 网络编程socket 编程

    千次阅读 2016-12-22 20:49:44
    一、C# .NET 网络编程相关类 IPAddress 类 用于表示一个 IP 地址,常用构造方法: IPAddress address = IPAddress.Parse("192.168.1.1"); IPAddress 类还有其他的一些共用方法,具体可以在 IPAddress类 查询。 DNS ...
  • 计算机网络中,数据传输通过的是协议。又一个概念——协议。我不想说的太官方,搜索了解下。这里我简单谈理解,协议——就是“规则”。两台机器之间通信,我们要指定规则,举个例子,比如A给B发消息,B接收到了。...
  • 计算机网络课程实验及课程设计内容,基于Socket编程,实现文件传输。
  • 基于TCP/IP协议的聊天程序,利用C#中的socket编程实现,代码分为用户端和客户端,有聊天界面
  • 简单的安卓客户端与服务器端的socket通信
  • 计算机网络课程设计(物联网课程设计)《智能家居协议设计》,使用socket编程,python实现,附规范报告及python源码
  • 网络组建与实施、SOCKET编程(包括MFC SOCKET编程和JAVA SOCKET编程)等编程实例

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 68,438
精华内容 27,375
关键字:

计算机网络socket编程