今天继续对socket编程进行研究,这里会真正开如用socket写一个小例子,进入正题:

TCP客户/服务器模型:
 
关于这个模型的流程这里就不多说了,比较容易理解,下面则利用这种模型来编写一个实际的例子。
回射客户/服务器:
这个例子的效果就是:客户端从命令行获取一行命令,然后发送给服务器端,当服务端接收到这行命令之后,不做任何操作,将其又回送给客户端,然后客户端进行回显,下面则开始一步步来实现这样的效果,来初步感受下Socket编程:
首先编写服务端:echosrv.c
第一步:创建套接字:
关于第一个参数domain,man帮助中也有说明:
但是,AF_INET等价于PF_INET,这里推荐用后者,因为刚好代表protocol family含义,下面代码如下:
 
第二步:绑定一个地址到套接字上:
 首先准备一下第二个参数,也就是要绑定的地址:
其中绑定地址还有其它两种方式:
另外,其实"servaddr.sin_addr.s_addr = htonl(INADDR_ANY);"这种写法是可以省略掉的,因为它是全0,但这里为了显示说明所以保留。
【提示】:关于上面的写法,可以参考博文:http://www.cnblogs.com/webor2006/p/3905799.html 中的地址转换函数
下面开始进行绑定:
第三步:则开始进行监听:
 
具体代码如下:
其中SOMAXCONN可以从man帮助中查看到:
它代表了socket的并发最大连接个数。
另外还得注意,套接字有被动套接字和主动套接字之分,当调用listen之后,该socket就变动被动套接字了,需要由主动套接字来发起连接,主动套接字是用connect函数来发起连接的。
 
第四步:从已完成连接队列中返回第一个连接:
 
接下来,则进行数据的接收,并将数据回显给客户端:
accept函数会返回一个新的套接字,注意:此时的套接字不再是被动套接字,而变为了主动:
可以通过accept的man手册来得知:
下面,则开始从该套接字中读取客户端发过来的数据:
至此,服务端的代码都已经编写完了,下面则先编译一下:
查看man帮助:
于是在代码中加入头:
再次编译:
还是出错,那IPPPOTO_TCP是在哪定义的呢?
可以通过以下命令进行查找:
于是乎,加上该头文件后再编译:
用同样的办法来进行查找:
于是加入它:
再次编译:
还是报错,对于这里面对应的头文件这里就不具体一个个查找了,不然有点充数的嫌疑,将所有头文件加上再次编译:
 
接下来,开始编写客户端的代码:echocli.c
首先创建一个socket:
第二步开始与服务器进行连接:
 
【说明】:用connect发起连接的套接字是主动套接字。
连接成功之后,就可以向服务器发送数据了:
另外,服务端在使用资源之后,最后也得关闭掉,所以修改服务端程序如下:
这时,客户端程序也已经编写完成,下面编译运行看一下效果:
也就是第一次客户端输入很长的字符串,而第二次输入很短的字符串时,这时就会输出有问题,照理应该是客户端输入什么,服务端就会回显给客户端,也就是打印两条一模一样的语句,产生这样的问题原因是什么呢?
下面来用图来分析一下:
 
所以,解决该问题的思路就是每次循环时将值初始化一下既可,修改代码如下:
 再次编译运行:
关于这个原因,之后会来解决,先占且不关心,等一会就会正常了,正常运行的效果如下:
这样,就实现了客户端与服务器端的socket通讯了,最终的代码如下:
echosrv.c【服务端】:
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h> #include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h> #define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while() int main(void)
{
int listenfd;
if ((listenfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < )
/* if ((listenfd = socket(PF_INET, SOCK_STREAM, 0)) < 0)*/
ERR_EXIT("socket"); struct sockaddr_in servaddr;
memset(&servaddr, , sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons();
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
/*servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");*/
/*inet_aton("127.0.0.1", &servaddr.sin_addr);*/ if (bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < )
ERR_EXIT("bind");
if (listen(listenfd, SOMAXCONN) < )
ERR_EXIT("listen"); struct sockaddr_in peeraddr;
socklen_t peerlen = sizeof(peeraddr);
int conn;
if ((conn = accept(listenfd, (struct sockaddr*)&peeraddr, &peerlen)) < )
ERR_EXIT("accept"); char recvbuf[];//用来存储客户端发来的数据
while ()
{
memset(recvbuf, , sizeof(recvbuf));
int ret = read(conn, recvbuf, sizeof(recvbuf));//从套接字中读取数据
fputs(recvbuf, stdout);//打印到屏幕上
write(conn, recvbuf, ret);//并且将其又回显给客户端,其第三个参数的长度正好是我们接收到的长度
}
close(conn);
close(listenfd); return ;
}

echocli.c【客户端】:

#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h> #include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h> #define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while() int main(void)
{
int sock;
if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < )
ERR_EXIT("socket"); struct sockaddr_in servaddr;
memset(&servaddr, , sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons();
servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); if (connect(sock, (struct sockaddr*)&servaddr, sizeof(servaddr)) < )
ERR_EXIT("connect"); char sendbuf[] = {};
char recvbuf[] ={};
while (fgets(sendbuf, sizeof(sendbuf), stdin) != NULL)
{
write(sock, sendbuf, strlen(sendbuf));
read(sock, recvbuf, sizeof(recvbuf)); fputs(recvbuf, stdout);
memset(sendbuf, , sizeof(sendbuf));
memset(recvbuf, , sizeof(recvbuf));
} close(sock); return ;
}

好了,今天的内容学到这,下回见~

linux网络编程之socket编程(二)的更多相关文章

  1. linux网络编程之socket编程(十二)

    今天继续学习socket编程,期待的APEC会议终于在京召开了,听说昨晚鸟巢那灯火通明,遍地礼花,有点08年奥运会的架势,有种冲动想去瞅见一下习大大的真容,"伟大的祖国,我爱你~~~&quo ...

  2. linux网络编程之socket编程(四)

    经过两周的等待,终于可以回归我正常的学习之旅了,表哥来北京了在我这暂住,晚上回家了基本在和他聊天,周末带他在北京城到处乱转,几乎剥夺了我自由学习的时间了,不过,亲人之情还是很难得的,工作学习并不是生活 ...

  3. linux网络编程之socket编程(一)

    今天开始,继续来学习linux编程,这次主要是研究下linux下的网络编程,而网络编程中最基本的需从socket编程开始,下面正式开始学习: 什么是socket: 在学习套接口之前,先要回顾一下Tcp ...

  4. linux网络编程之socket编程(六)

    经过一个国庆长假,又有一段时间没有写博文了,今天继续对linux网络编程进行学习,如今的北京又全面进入雾霾天气了,让我突然想到了一句名句:“真爱生活,珍惜生命”,好了,言归正传. 回顾一下我们之间实现 ...

  5. linux网络编程之socket编程(八)

    学习socket编程继续,今天要学习的内容如下: 先来简单介绍一下这五种模型分别是哪些,偏理论,有个大致的印象就成,做个对比,因为最终只会研究一个I/O模型,也是经常会用到的, 阻塞I/O: 先用一个 ...

  6. linux网络编程之socket编程(十六)

    继续学习socket编程,今天的内容会有些难以理解,一步步来分解,也就不难了,正入正题: 实际上sockpair有点像之前linux系统编程中学习的pipe匿名管道,匿名管道它是半双工的,只能用于亲缘 ...

  7. linux网络编程之socket编程(十五)

    今天继续学习socket编程,这次主要是学习UNIX域协议相关的知识,下面开始: [有个大概的认识,它是来干嘛的] ①.UNIX域套接字与TCP套接字相比较,在同一台主机的传输速度前者是后者的两倍. ...

  8. linux网络编程之socket编程(三)

    今天继续对socket编程进行学习,在学习之前,需要回顾一下上一篇中编写的回射客户/服务器程序(http://www.cnblogs.com/webor2006/p/3923254.html),因为今 ...

  9. linux网络编程之socket编程(十一)

    今天继续学习socket编程,这次主要是学习超时方法的封装,内容如下: ①.alarm[不常用,了解既可] 它的实现思路是这样的: 但是这种方案有一定的问题,因为闹钟可能会作为其它的用途,这时所设置的 ...

随机推荐

  1. Jenkins - 安装并启动Jenkins

    1 - 关于Jenkins 构建流水线(build pipeline)工具Jenkins可以轻松地定义和管理各种各样的操作(构建.测试等),并将这些操作像管道pipe一样自由地进行组合,从而自动.流畅 ...

  2. ue4 优化建议与经验

    转自:https://dawnarc.com/2016/12/ue4%E4%BC%98%E5%8C%96%E5%BB%BA%E8%AE%AE%E4%B8%8E%E7%BB%8F%E9%AA%8C/ 内 ...

  3. mongoDB主从和集群

    主从(windows下的配置) 主服务器设置 mongod --dbpath=F:\mongoDB\db --master \\dbpath是设定数据存放路径 --master是指定为主库 从服务器设 ...

  4. centos 安装 swoole_framework 框架

    composer require "matyhtf/swoole_framework" 运行以上命令 Using version ^1.20 for matyhtf/swoole_ ...

  5. LeetCode 1047. 删除字符串中的所有相邻重复项(Remove All Adjacent Duplicates In String)

    1047. 删除字符串中的所有相邻重复项 1047. Remove All Adjacent Duplicates In String 题目描述 LeetCode1047. Remove All Ad ...

  6. Arduino硬件之NCF技术(近场通信技术)

    Arduino硬件之NCF技术(近场通信技术) 版权转载:https://blog.csdn.net/import_sadaharu/article/details/52437488 Android硬 ...

  7. 阿里云最新Maven仓库地址 从此 我的maven依赖下载666~

    配置指南 maven配置指南 打开maven的配置文件(windows机器一般在maven安装目录的conf/settings.xml),在<mirrors></mirrors> ...

  8. c#连接Access数据库及增删改查作

    access:版本2003(后缀.mdb,新版access可另存为2003兼容版) using: using System;using System.Data;using System.Windows ...

  9. C# vb .net实现对比度调整特效滤镜效果

    在.net中,如何简单快捷地实现Photoshop滤镜组中的对比度效果呢?答案是调用SharpImage!专业图像特效滤镜和合成类库.下面开始演示关键代码,您也可以在文末下载全部源码: 设置授权 第一 ...

  10. PowerShell命令批量添加、导出AD用户

    导入单个AD用户命令 New-ADUser -Name "周八" -Surname "周" -GivenName "八"-SamAccoun ...