发布时间:2019-02-18责任编辑:满帅 浏览:1486
Linux因为其稳定性,内存泄漏较少,因此适合长期运行,通常定位为服务器系统,作为服务器少不了与客户端的交互通信,本文将介绍下Linux下的网络编程.
说到网络编程就少不了TCP/IP模型

通信过程

TCP协议作为传输层协议,通讯时需要经过几个步骤,俗称三次握手,断开时也需要几个步骤,俗称四次握手.
所谓的三次握手就是
1客户端发送一个带SYN标志的TCP报文到服务器。这是三次握手过程中的报文1。
2服务器端回应客户端的,这是三次握手中的第2个报文,这个报文同时带ACK标志 和SYN标志。因此它表示对刚才客户端SYN报文的回应;同时又标志SYN给客户端,询问客户端是否准备好进行数据通讯。
3客户必须再次回应服务段一个ACK报文,这是报文段3。
此步骤过后,客户端与服务端就正式建立起了连接,TCP是面向连接的协议,因为三次握手的目的就是确保客户端与服务器连接正常,正因为如此TCP协议也是安全可靠的,是不会丢失数据包的.
断开连接时,与连接时类似,不过是需要四次握手,
由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。这原则是当一方完 成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个 FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方 将执行主动关闭,而另一方执行被动关闭。
(1) TCP客户端发送一个FIN,用来关闭客户到服务器的数据传送(报文段4)。
(2) 服务器收到这个FIN,它发回一个ACK,确认序号为收到的序号加1(报文段5)。 和SYN一样,一个FIN将占用一个序号。
(3) 服务器关闭客户端的连接,发送一个FIN给客户端(报文段6)。
(4) 客户段发回ACK报文确认,并将确认序号设置为收到序号加1(报文段7)。
当某一方不需要发送数据时,就可以发起断开连接,断开连接后这一方就不会在发送数据了,但是可以接收数据,这也是为什么会是四次握手的原因,只有另一方也断开后,连接才是真正的断开.
那么简答的介绍了TCP协议,就正式的说一下网络编程,LINUX下的网络编程与windows下类似,只不过因为系统原因写法上有些区别但是原理是一样的.而说到网络编程,那么就少不了网络编程中非常重要的SOCKET套接字.
socket这个词可以表示很多概念:
在TCP/IP协议中,“IP地址+TCP或UDP端口号”唯一标识网络通讯中的一个进程,“IP 地址+端口号”就称为socket。
在TCP协议中,建立连接的两个进程各自有一个socket来标识,那么这两个socket组成 的socket pair就唯一标识一个连接。socket本身有“插座”的意思,因此用来描述网络连接的一对一关系。
TCP/IP协议最早在BSD UNIX上实现,为TCP/IP协议设计的应用层编程接口称为socket API。
Socket通信流程如上图所示,废话不多说直接贴一段代码.
服务端:

#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)
{
struct sockaddr_in servaddr, cliaddr; socklen_t cliaddr_len;
int listenfd, connfd; char buf[MAXLINE];
char str[INET_ADDRSTRLEN]; int i, n;
listenfd = socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(SERV_PORT);
bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); listen(listenfd, 20);
printf("Accepting connections ... "); while (1) {
cliaddr_len = sizeof(cliaddr);
connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len);
n = read(connfd, buf, MAXLINE); printf("received from %s at PORT %d ",
inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)), ntohs(cliaddr.sin_port));
for (i = 0; i < n; i++) buf[i] = toupper(buf[i]);
write(connfd, buf, n); close(connfd);
}
}
客户端:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h>
#include <sys/socket.h> #include <netinet/in.h>
#define MAXLINE 80
#define SERV_PORT 8000
int main(int argc, char *argv[])
{
struct sockaddr_in servaddr; char buf[MAXLINE];
int sockfd, n; char *str;
if (argc != 2) {
fputs("usage: ./client message ", stderr); exit(1);
}
str = argv[1];
sockfd = socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET;
inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr); servaddr.sin_port = htons(SERV_PORT);
connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
write(sockfd, str, strlen(str));
n = read(sockfd, buf, MAXLINE); printf("Response from server: "); write(STDOUT_FILENO, buf, n);
close(sockfd); return 0;
}
通过上述代码,简单的通讯就建立起来了,然而实际应用中是绝对不会这么简单的,往往网络编程需要与多线程结合使用,并且用到一些高并发服务器模型.篇幅有限,这里就不一一介绍了.
游戏开发组 供稿