加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Linux > 正文

Linux Socket 编程简介

发布时间:2020-12-13 14:11:37 所属栏目:Linux 来源:网络整理
导读:"IP地址+端口号" 就称为 socket 。本文以一个简单的 TCP 协议为例,介绍如何创建基于 TCP 协议的网络程序。 #include .h> .h> span style="color: #0000ff"#define MAXLINE 80 span style="color: #0000ff"#define SERV_PORT 8000 span style="color: #0000f

"IP地址+端口号" 就称为 socket。本文以一个简单的 TCP 协议为例,介绍如何创建基于 TCP 协议的网络程序。

#include <.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() 打开一个网络通讯端口,如果成功的话,
</span><span style="color: #008000"&gt;//</span><span style="color: #008000"&gt; 就像 open() 一样返回一个文件描述符,
</span><span style="color: #008000"&gt;//</span><span style="color: #008000"&gt; 应用程序可以像读写文件一样用 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 这个用于网络通讯的文件描述符监听 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; 当有客户端发起连接时,服务器调用的 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 %s at PORT %dn</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);
}

}

$ server.c -o server

$ ./server

socket( family, type, protocol);

bind( sockfd, sockaddr *myaddr,socklen_t addrlen);

bzero(&servaddr,=== htons(SERV_PORT);

listen( sockfd, backlog);

accept( sockfd, sockaddr *cliaddr,socklen_t *addrlen);

(= = sockaddr *)&cliaddr,&=

#include <.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">int argc,<span style="color: #0000ff">char <span style="color: #000000">argv[])
{
<span style="color: #0000ff">struct<span style="color: #000000"> sockaddr_in servaddr;
<span style="color: #0000ff">char<span style="color: #000000"> buf[MAXLINE];
<span style="color: #0000ff">int<span style="color: #000000"> sockfd,n;
<span style="color: #0000ff">char
<span style="color: #000000">str;

</span><span style="color: #0000ff"&gt;if</span> (argc != <span style="color: #800080"&gt;2</span><span style="color: #000000"&gt;)
{
    fputs(</span><span style="color: #800000"&gt;"</span><span style="color: #800000"&gt;usage: ./client messagen</span><span style="color: #800000"&gt;"</span><span style="color: #000000"&gt;,stderr);
    exit(</span><span style="color: #800080"&gt;1</span><span style="color: #000000"&gt;);
}
str </span>= argv[<span style="color: #800080"&gt;1</span><span style="color: #000000"&gt;];

sockfd </span>= socket(AF_INET,<span style="color: #0000ff"&gt;sizeof</span><span style="color: #000000"&gt;(servaddr));
servaddr.sin_family </span>=<span style="color: #000000"&gt; AF_INET;
inet_pton(AF_INET,</span><span style="color: #800000"&gt;"</span><span style="color: #800000"&gt;127.0.0.1</span><span style="color: #800000"&gt;"</span>,&amp;<span style="color: #000000"&gt;servaddr.sin_addr);
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(),客户端的端口号由内核自动分配。
</span><span style="color: #008000"&gt;//</span><span style="color: #008000"&gt; 注意,客户端不是不允许调用 bind(),只是没有必要调用 bind() 固定一个端口号,
</span><span style="color: #008000"&gt;//</span><span style="color: #008000"&gt; 服务器也不是必须调用 bind(),但如果服务器不调用 bind(),内核会自动给服务器分配监听端口,
</span><span style="color: #008000"&gt;//</span><span style="color: #008000"&gt; 每次启动服务器时端口号都不一样,客户端要连接服务器就会遇到麻烦。</span>
connect(sockfd,<span style="color: #0000ff"&gt;sizeof</span><span style="color: #000000"&gt;(servaddr));

write(sockfd,strlen(str));

n </span>=<span style="color: #000000"&gt; read(sockfd,MAXLINE);
printf(</span><span style="color: #800000"&gt;"</span><span style="color: #800000"&gt;Response from server:n</span><span style="color: #800000"&gt;"</span><span style="color: #000000"&gt;);
write(STDOUT_FILENO,n);
printf(</span><span style="color: #800000"&gt;"</span><span style="color: #800000"&gt;n</span><span style="color: #800000"&gt;"</span><span style="color: #000000"&gt;);
close(sockfd);
</span><span style="color: #0000ff"&gt;return</span> <span style="color: #800080"&gt;0</span><span style="color: #000000"&gt;;

}

$ client.c -o client

$ ./client hello

listenfd = (== (n == - (n == (

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读