欢迎光临
我们一直在努力

Linux Socket 编程简介

本站教程收集整理的这篇文章主要介绍了Linux Socket 编程简介,本站教程本站觉得挺不错的,现在分享给大家,也给大家做个参考。

TCP/IP 协议中,”IP地址 + TCP或UDP端口号” 可以唯一标识网络通讯中的一个进程,“IP地址+端口号” 就称为 socket。本文以一个简单的 TCP 协议为例,介绍如何创建基于 TCP 协议的网络程序。

@H_197_23@

调用 socket()、bind()、listen() 函数完成初始化后,调用 accept() 阻塞等待,处于监听端口的状态,客户端调用 socket() 初始化后,调用 connect() 发出 SYN 段并阻塞等待服务器应答,服务器应答一个SYN-ACK 段,客户端收到后从 connect() 返回,同时应答一个 ACK 段,服务器收到后从 accept() 返回。

调用 read(),读 socket 就像读管道一样,如果没有数据到达就阻塞等待,这时客户端调用 write() 发送请求给服务器,服务器收到后从 read() 返回,对客户端的请求进行处理,在此期间客户端调用 read() 阻塞等待服务器的应答,服务器调用 write() 将处理结果发回给客户端,再次调用 read() 阻塞等待下一条请求,客户端收到后从 read() 返回,发送下一条请求,如此循环下去。

关闭 TCP 连接的过程:

调用 close() 关闭连接,就像写端关闭的管道一样,服务器的 read() 返回 0,这样服务器就知道客户端关闭了连接,也调用 close() 关闭连接。注意,任何一方调用 close() 后,连接的两个传输方向都关闭,不能再发送数据了。如果一方调用 shutdown() 则连接处于半关闭状态,仍可接收对方发来的数据。

  • 调用某个 socket 函数时 TCP 协议层完成什么动作,比如调用 connect() 会发出 SYN 段
  • 函数返回就表明 TCP 协议收到了某些段,再比如 read() 返回 0 就表明收到了 FIN 段

一个简单的 TCP 网络程序来理解相关概念。程序分为服务器端和客户端两部分,它们之间通过 socket 进行通信。

一个非常简单的服vps云服务器务器端程序,它从客户端读字符,然后将每个字符转换为大写并回送给客户端:

#include @H_673_100@.h>.h>

<span style="color: #0000ff">#define MAXLINE 80
<span style="color: #0000ff">#define SERV_PORT 8000

<span style="color: #0000ff">int main(<span style="color: #0000ff">void<span style="color: #000000">)
{
<span style="color: #0000ff">struct<span style="color: #000000"> sockaddr_in servaddr,cliaddr;
socklen_t cliaddr_len;
<span style="color: #0000ff">int<span style="color: #000000"> listenfd,connfd;
<span style="color: #0000ff">char<span style="color: #000000"> buf[MAXLINE];
<span style="color: #0000ff">char<span style="color: #000000"> str[INET_ADDRSTRLEN];
<span style="color: #0000ff">int<span style="color: #000000"> i,n;

</span><span style="color: #008000"&gt;//</span><span style="color: #008000"&gt; socket() 打开<a href="http://code.js-code.com/tag/yige/" target="_blank" class="keywords">一个</a>网络通讯端口,如果成功的话,
</span><span style="color: #008000"&gt;//</span><span style="color: #008000"&gt; 就像 <a href="http://code.js-code.com/tag/open/" target="_blank" class="keywords">open()</a> 一样返回<a href="http://code.js-code.com/tag/yige/" target="_blank" class="keywords">一个</a><a href="http://code.js-code.com/tag/wenjian/" target="_blank" class="keywords">文件</a>描述符,
</span><span style="color: #008000"&gt;//</span><span style="color: #008000"&gt; 应用程序可以像读写<a href="http://code.js-code.com/tag/wenjian/" target="_blank" class="keywords">文件</a>一样用 read/write 在网络上收发数据。</span>
listenfd = socket(AF_INET,SOCK_STREAM,<span style="color: #800080"&gt;0</span><span style="color: #000000"&gt;);

bzero(</span>&amp;servaddr,<span style="color: #0000ff"&gt;sizeof</span><span style="color: #000000"&gt;(servaddr));
servaddr.sin_family </span>=<span style="color: #000000"&gt; AF_INET;
servaddr.sin_addr.s_addr </span>=<span style="color: #000000"&gt; htonl(INADDR_ANY);
servaddr.sin_port </span>=<span style="color: #000000"&gt; htons(SERV_PORT);

</span><span style="color: #008000"&gt;//</span><span style="color: #008000"&gt; bind() 的作用是将参数 listenfd 和 servaddr 绑定在一起,
</span><span style="color: #008000"&gt;//</span><span style="color: #008000"&gt; 使 listenfd 这个用于网络通讯的<a href="http://code.js-code.com/tag/wenjian/" target="_blank" class="keywords">文件</a>描述符监听 servaddr 所描述的地址和端口号。</span>
bind(listenfd,(<span style="color: #0000ff"&gt;struct</span> sockaddr *)&amp;servaddr,<span style="color: #0000ff"&gt;sizeof</span><span style="color: #000000"&gt;(servaddr));

</span><span style="color: #008000"&gt;//</span><span style="color: #008000"&gt; listen() 声明 listenfd 处于监听状态,
</span><span style="color: #008000"&gt;//</span><span style="color: #008000"&gt; 并且最多允许有 20 个客户端处于连接待状态,如果接收到更多的连接请求就忽略。</span>
listen(listenfd,<span style="color: #800080"&gt;20</span><span style="color: #000000"&gt;);

printf(</span><span style="color: #800000"&gt;"</span><span style="color: #800000"&gt;AccepTing connections ...\n</span><span style="color: #800000"&gt;"</span><span style="color: #000000"&gt;);
</span><span style="color: #0000ff"&gt;while</span> (<span style="color: #800080"&gt;1</span><span style="color: #000000"&gt;)
{
    cliaddr_len </span>= <span style="color: #0000ff"&gt;sizeof</span><span style="color: #000000"&gt;(cliaddr);
    </span><span style="color: #008000"&gt;//</span><span style="color: #008000"&gt; 典型的服务器程序可以同时服务于多个客户端,
    </span><span style="color: #008000"&gt;//</span><span style="color: #008000"&gt; 当有客户端发起连接时,服务器<a href="http://code.js-code.com/tag/diaoyong/" target="_blank" class="keywords">调用</a>的 accept() 返回并接受这个连接,
    </span><span style="color: #008000"&gt;//</span><span style="color: #008000"&gt; 如果有大量的客户端发起连接而服务器来不及处理,尚未 accept 的客户端就处于连接等待状态。</span>
    connfd = accept(listenfd,(<span style="color: #0000ff"&gt;struct</span> sockaddr *)&amp;cliaddr,&amp;<span style="color: #000000"&gt;cliaddr_len);

    n </span>=<span style="color: #000000"&gt; read(connfd,buf,MAXLINE);
    printf(</span><span style="color: #800000"&gt;"</span><span style="color: #800000"&gt;received from <a href="http://code.js-code.com/tag/s/" target="_blank" class="keywords">%s</a> at PORT %d\n</span><span style="color: #800000"&gt;"</span><span style="color: #000000"&gt;,inet_ntop(AF_INET,</span>&amp;cliaddr.sin_addr,str,<span style="color: #0000ff"&gt;sizeof</span><span style="color: #000000"&gt;(str)),ntohs(cliaddr.sin_port));

    </span><span style="color: #0000ff"&gt;for</span> (i = <span style="color: #800080"&gt;0</span>; i < n; i++<span style="color: #000000"&gt;)
    {
        buf[i] </span>=<span style="color: #000000"&gt; toupper(buf[i]);
    }

    write(connfd,n);
    close(connfd);
}

}

本站总结

以上是本站教程为你收集整理的Linux Socket 编程简介全部内容,希望文章能够帮你解决Linux Socket 编程简介所遇到的程序开发问题。

如果觉得本站教程网站内容还不错,欢迎将本站教程推荐给好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。

赞(0)
【声明】:本博客不参与任何交易,也非中介,仅记录个人感兴趣的主机测评结果和优惠活动,内容均不作直接、间接、法定、约定的保证。访问本博客请务必遵守有关互联网的相关法律、规定与规则。一旦您访问本博客,即表示您已经知晓并接受了此声明通告。