linux系统socket通信编程1
Linux下的Socket编程大体上包括Tcp Socket、Udp Socket即Raw Socket这三种,其中TCP和UDP方式的Socket编程用于编写应用层的socket程序,是我们用得比较多的,而Raw Socket则用得相对较少,不在本文介绍范围之列。
TCP Socket
基于TCP协议的客户端/服务器程序的一般流程一般如下:

它基本上可以分为三个部分:
一、建立连接:
- 服务器调用socket()、bind()、listen()完成初始化后,调用accept()阻塞等待,处于监听端口的状态
- 客户端调用socket()初始化后,调用connect()发出SYN段并阻塞等待服务器应答
- 服务器应答一个SYN-ACK段,客户端收到后从connect()返回,同时应答一个ACK段,服务器收到后从accept()返回。
二、传输数据:
建立连接后,TCP协议提供全双工的通信管道,服务器端和客户端根据协议可以通过read和write的反复调用实现数据的传输
三、关闭连接:
当数据传输已经完成后,服务器和客户端可以调用Close关闭连接,一端关闭连接后,另一端read函数则会返回0,可以根据这个特征来感应另一端的退出。
下面就以一个简单的EchoServer演示一下如何创建服务器端和客户端代码,其中和socket相关api都会高亮显示。
服务器端示例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define MAXLINE 80
#define SERV_PORT 8000
int main(void)
{
char buf[MAXLINE];
int listenfd = 0;
listenfd = socket(AF_INET, SOCK_STREAM, 0);
sockaddr_in servaddr = {0};
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
bind(listenfd, (sockaddr *)&servaddr, sizeof(servaddr));
listen(listenfd, 20);
printf("Accepting connections ...\n");
while (1)
{
sockaddr_in cliaddr = {0};
socklen_t cliaddr_len = sizeof(cliaddr);
int connfd = accept(listenfd, (sockaddr *)&cliaddr, &cliaddr_len);
char str[INET_ADDRSTRLEN];
printf("connected from %s at PORT %d\n",
inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)),
ntohs(cliaddr.sin_port));
while(true)
{
int count = read(connfd, buf, MAXLINE);
if (count == 0)
break;
write(connfd, buf, count);
}
close(connfd);
printf("closed from %s at PORT %d\n",
inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)),
ntohs(cliaddr.sin_port));
}
}
PS:这里需要注意的一下的是sock函数的第二个参数SOCK_STREAM,它表示是一个TCP连接,后面我们会介绍通过传入SOCK_DGRAM打开udp连接。
服务器端主体流程就是一个死循环,它接受一个socket连接,然后将其原封不动的返回给客户端,待客户端退出后,关闭socket连接,再次接受下一个socket连接。
客户端代码如下:
#include <stdio.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define MAXLINE 80
#define SERV_PORT 8000
#define MESSAGE "hello world"
int main(int argc, char *argv[])
{
char buf[MAXLINE];
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
sockaddr_in servaddr = {0};
servaddr.sin_family = AF_INET;
inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);
servaddr.sin_port = htons(SERV_PORT);
if (0 != connect(sockfd, (sockaddr *)&servaddr, sizeof(servaddr)))
{
printf("connected failed");
return 1;
}
write(sockfd, MESSAGE, sizeof(MESSAGE));
int count = read(sockfd, buf, MAXLINE);
printf("Response from server: %s\n",buf);
close(sockfd);
return 0;
}
客户端代码比较简单,这里就不多介绍了。
UDP Socket
典型的UDP客户端/服务器通讯过程如下图所示:

由于UDP不需要维护连接,程序逻辑简单了很多,但是UDP协议是不可靠的,实际上有很多保证通讯可靠性的机制需要在应用层实现,可能反而会需要更多代码。
典型的示例如下:
/* server.cpp */
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define MAXLINE 80
#define SERV_PORT 8000
int main(void)
{
char buf[MAXLINE];
char str[INET_ADDRSTRLEN];
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
sockaddr_in servaddr = {0};
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
bind(sockfd, (sockaddr *)&servaddr, sizeof(servaddr));
printf("Accepting connections ...\n");
while (1)
{
sockaddr_in cliaddr;
socklen_t cliaddr_len = sizeof(cliaddr);
int count = recvfrom(sockfd, buf, MAXLINE, 0, (sockaddr *)&cliaddr, &cliaddr_len);
if (count < 0)
{
printf("recvfrom error");
continue;
}
printf("received from %s at PORT %d\n",
inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)),
ntohs(cliaddr.sin_port));
sendto(sockfd, buf, count, 0, (sockaddr *)&cliaddr, sizeof(cliaddr));
}
}
/* client.cpp */
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define MAXLINE 80
#define SERV_PORT 8000
int main(int argc, char *argv[])
{
char buf[MAXLINE];
char str[INET_ADDRSTRLEN];
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
sockaddr_in servaddr = {0};
servaddr.sin_family = AF_INET;
inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);
servaddr.sin_port = htons(SERV_PORT);
while (fgets(buf, MAXLINE, stdin) != NULL)
{
int count = sendto(sockfd, buf, strlen(buf), 0, (sockaddr *)&servaddr, sizeof(servaddr));
if (count == -1)
{
printf("sendto error");
return 0;
}
count = recvfrom(sockfd, buf, MAXLINE, 0, NULL, 0);
if (count == -1)
{
printf("recvfrom error");
return 0;
}
write(STDOUT_FILENO, buf, count);
}
close(sockfd);
return 0;
}
linux系统socket通信编程1的更多相关文章
- linux系统socket通信编程详解函数
linux socket编程之TCP与UDP TCP与UDP区别 TCP---传输控制协议,提供的是面向连接.可靠的字节流服务.当客户和服务器彼此交换数据前,必须先在双方之间建立一个TCP连接,之 ...
- linux系统socket通信编程实践
简单介绍并实现了基于UDP(TCP)的windows(UNIX下流程基本一致)下的服务端和客户端的程序,本文继续探讨关于UDP编程的一些细节. 下图是一个简单的UDP客户/服务器模型: 我在这里也实现 ...
- linux系统socket通信编程2
一.概述 TCP(传输控制协议)和UDP(用户数据报协议是网络体系结构TCP/IP模型中传输层一层中的两个不同的通信协议. TCP:传输控制协议,一种面向连接的协议,给用户进程提供可靠的全双工的字节流 ...
- Linux 下socket通信终极指南(附TCP、UDP完整代码)
linux下用socket通信,有TCP.UDP两种协议,网上的很多教程把两个混在了一起,或者只讲其中一种.现在我把自己这两天研究的成果汇总下来,写了一个完整的,适合初学者参考,也方便自己以后查阅. ...
- 【Linux教程】Linux系统零基础编程入门,想当大神?这些你都要学
✍ 文件和文件系统 文件是Linux系统中最重要的抽象,大多数情况下你可以把linux系统中的任何东西都理解为文件,很多的交互操作其实都是通过文件的读写来实现的. 文件描述符 在Linux内核中,文件 ...
- 【转】C# Socket通信编程
https://www.cnblogs.com/dotnet261010/p/6211900.html#undefined 一:什么是SOCKET socket的英文原义是“孔”或“插座”.作为进程通 ...
- linux系统UDP的socket通信编程3
我刚开始接触linux下的socket编程,边抄边理解udp socket编程,我的疑问是server不指定IP地址,client的目标IP地址是127.0.0.1,这样就可以通信吗?在同一主机下是不 ...
- linux系统UDP的socket通信编程2
UDP套接字编程范例: server端代码如下: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 2 ...
- linux系统UDP的socket通信编程
发送方: /* * File: main.c * Author: tianshuai * * Created on 2011年11月29日, 下午10:34 * * 主要实现:发送20个文本消息,然后 ...
随机推荐
- win7语言设置为英语
控制面板,地区和语言 可以设置格式 键盘和语言 安装显示的语言 选择“可选更新包”,选择语言的语言
- HTML5的video虽然可用controls来展示控件
HTML5的video虽然可用controls来展示控件,并进行控制播放暂停等,但是不同的浏览器显示的效果可能不一样,所以很多时候我们需要使用Dom来进行自定义的一些操作和控制.下面是一个小例子. 当 ...
- Mybatis generator 自动生成代码
开发项目的时候,表很多,是不可能一点点的自己去写xml ,dao文件的,这里就需要用到代码的自动生成工具了. 第一步:导入jar包,当然,这之前,基本环境,像mybatis,数据库之类的都得搭建好. ...
- sqlserver被锁的表以及如何解锁
查看sqlserver被锁的表以及如何解锁 查看被锁表: select request_session_id spid,OBJECT_NAME(resource_associated_en ...
- 一站式学习Wireshark(七):Statistics统计工具功能详解与应用
Wireshark一个强大的功能在于它的统计工具.使用Wireshark的时候,我们有各种类型的工具可供选择,从简单的如显示终端节点和会话到复杂的如Flow和IO图表.本文将介绍基本网络统计工具.包括 ...
- [转]ViewPager学习笔记(一)——懒加载
在项目中ViewPager和Fragment接口框架已经是处处可见,但是在使用中,我们肯定不希望用户在当前页面时就在前后页面的数据,加入数据量很大,而用户又不愿意左右滑动浏览,那么这时候ViewPag ...
- C++类的实例化对象的大小之sizeof()
之所以写这篇<C++类的实例化对象的大小之sizeof()>.是由于在參加笔试的时候遇到例如以下这么一道题,当时感觉就是这个一个坑,但.我还是义无反顾的跳了下去,由于存在知识点盲区啊.现, ...
- python 两个字典合并
dict1={1:[1,11,111],2:[2,22,222]}dict2={3:[3,33,333],4:[4,44,444]}合并两个字典得到类似 {1:[1,11,111],2:[2,22,2 ...
- 更改HDFS权限
hdfs dfs -chmod -R 755 / 之前执行过这条语句,但是总是提示: 15/05/21 08:10:18 WARN util.NativeCodeLoader: Unable to l ...
- (转)PS流格式
概念: 将具有共同时间基准的一个或多个PES组合(复合)而成的单一的数据流称为节目流(Program Stream). ES是直接从编码器出来的数据流,可以是编码过的视频数据流,音频数据流,或其他编码 ...