Unix网络编程之基本TCP套接字编程(上)

TCP客户/服务器实例

服务器程序

#include "unp.h"
int main(int argc, char **argv)
{
	int listenfd, connfd;
	pid_t childpid;
	socklen_t clilen;
	struct sockaddr_in cliaddr, servaddr;
	listenfd = Socket(AF_INET, SOCK_STREAM, 0); //1
	bzero(&servaddr, sizeof(servaddr));         //2
	servaddr.sin_family = AF_INET;
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);  //3
	servaddr.sin_port = htons(SERV_PORT);
	Bind(listenfd, (SA*) &servaddr, sizeof(servaddr));  //4
	Listen(listenfd, LISTENQ);  //5
	for(;;)
	{
		clilen = sizeof(cliaddr);
		connfd = Accept(listenfd,(SA*) &cliaddr, &clilen);  //6
		if((childpid = Fork())== 0)     //7
		{
			Close(listenfd);
			str_echo(connfd);
			exit(0);
		}
		Close(connfd);             //8
	}
}

客户端程序

#include "unp.h"
int main(int argc, char** argv)
{
	int sockfd;
	struct sockaddr_in servaddr;
	if (argc != 2)
		err_quit("usage:tcpcli<IP>");
	sockfd = Socket(AF_INET, SOCK_STREAM, 0);
	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(SERV_PORT);
	Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);    //9
	Connect(sockfd, (SA*) &servaddr, sizeof(servaddr));  //10
	str_cli(stdin, sockfd);
	exit(0);
}

测试结果

1.先执行服务器端程序,此时服务器处于监听状态

2.再执行客户端程序。

客户端从标准输入获得内容,传递给服务器,又从服务器收回原数据,并显示在屏幕上。

3.当多个客户端同时连接服务器时,也可以照常工作

实例中使用的套接字介绍

socket函数

作用:

指定期望的通信协议类型(使用ipv4或ipv6 Tcp或Udp等)

使用:

#include<sys/socket.h>

int socket(int family, int type, int protocol);  //若成功则返回非负描述符

参数介绍:

family参数为协议族,包括:

AF_INET        IPv4协议

AF_INET6      IPv6协议

AF_LOCAL    Unix域协议

AF_ROUTE    路由套接字

AF_KEY          密钥套接字

type参数指明套接字类型,包括:

SOCK_STREAM          字节流套接字

SOCK_DGRAM           数据报套接字

SOCK_SEQPACKET    有序分组套接字

SOCK_RAW                原始套接字

protocol参数应设为某个协议类型常值,包括:

IPPROTO_CP       TCP传输协议

IPPROTO_UDP    UDP传输协议

IPPROTO_SCTP   SCTP传输协议

或者设为0,以选择给定family和type组合之后的默认值。

然而,并非所有套接字family和type的组合都是有效的。

然而TCP是一个字节流协议,仅支持SOCK_STREAM套接字。

connect函数

作用:

建立与TCP服务器的连接。

使用:

#include<sys/socket.h>

int connect(int sockfd, const struct sockaddr *servaddr, socklen_t addrlen);   //若成功则返回非负

参数说明:

第一个参数为客户为参与通信自身建立起来的套接字描述符(socket函数返回的)。

第二个参数为指向服务器地址结构的指针,服务器地址结构必须包含服务器的IP地址和端口号。

第三个参数为该地址结构的大小。

按照TCP状态图,connect函数导致当前套接字从CLOSED状态(socket创建后即为该状态)转移到SYN_SENT状态

若成功则再转移到ESTABLISHED状态。若失败则该套接字不再可用。

bind函数

作用:

把本地协议地址赋予一个套接字。对于TCP,bind函数可以指定一个端口号,或指定一个IP,也可以两者都指定或两种都不指定。

使用:

#include<sys/socket.h>

int bind(int sockfd, const struct sockaddr* myaddr, socklen_t addrlen);

listen函数

作用:

仅由TCP服务器调用,把未连接的套接字转换成一个被动套接字,指示内核应接受向该套接字的连接请求,并规定了

套接字排队的最大连接个数。

使用:

#include<sys/socket.h>

int listen(int sockfd, int backlog);

accept函数

作用:

由TCP服务器调用,用于从已完成连接队列队头返回下一个已完成连接。如果已完成连接队列为空,那么进程进入睡眠。

使用:

#include<sys/socket.h>

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

参数说明:

clicaddr 和 addrlen用来返回已连接的对端进程(客户)的协议地址。

如果accept成功,那么其返回值是由内核自动生成的一个全新的描述符,代表与客户的TCP连接。在讨论accept函数

时,我们称它的第一个参数为监听套接字描述符(由socket创建,随后用做bind和listen的第一个参数的描述符),

称它的返回值为已连接套接字描述符。

一个服务器通常仅仅创建一个监听套接字,它在服务器的生命周期一直存在。内核为每个由服务器进程接受的客户连

接创建一个已连接套接字(TCP三次握手已经完成)。当服务器完成对某个给定客户的服务时,相应的已连接套接字

就被关闭。

如果我们对客户进程的协议地址不感兴趣,那么可以把cliaddr和addrlen均置为空指针。

fork和exec函数

使用:

#include<unistd.h>

pid_t fork(void);

fork理解最困难的地方在于调用它一次,它却返回两次。

它在调用进程(父进程)中返回一次,返回值是子进程的ID号。在子进程又返回一次,返回值是0。因此返回值

本身告知当前是子进程还是父进程。

父进程中调用fork之前打开的所有描述符在fork返回之后由子进程分享。我们看到网络服务器利用了这个特性:父

进程调用accept之后调用fork。所接受的已连接套接字随后就在父进程与子进程之间共享。

close函数

作用:

关闭套接字,终止TCP连接。

使用:

#include<unistd.h>

int close(int sockfd);

Unix网络编程之基本TCP套接字编程(上),布布扣,bubuko.com

时间: 2024-10-12 21:13:30

Unix网络编程之基本TCP套接字编程(上)的相关文章

《网络编程》基于 TCP 套接字编程的分析

本节围绕着基于 TCP 套接字编程实现的客户端和服务器进行分析,首先给出一个简单的客户端和服务器模式的基于 TCP 套接字的编程实现,然后针对实现过程中所出现的问题逐步解决.有关基于 TCP 套接字的编程过程可参考文章<基本 TCP 套接字编程>.该编程实现的功能如下: (1)客户端从标准输入读取文本,并发送给服务器: (2)服务器从网络输入读取该文本,并回射给客户端: (3)客户端从网络读取由服务器回射的文本,并通过标准输出回显到终端: 简单实现流图如下:注:画图过程通信双方是单独的箭头,只

《网络编程》基本 TCP 套接字编程

在进行套接字编程之前必须熟悉其地址结构,有关套接字的地址结构可参考文章<套接字编程简介>.基于 TCP 的套接字编程的所有客户端和服务器端都是从调用socket 开始,它返回一个套接字描述符.客户端随后调用connect 函数,服务器端则调用 bind.listen 和accept 函数.套接字通常使用标准的close 函数关闭,但是也可以使用 shutdown 函数关闭套接字.下面针对套接字编程实现过程中所调用的函数进程分析.以下是基于 TCP 套接字编程的流程图: socket 函数 套接

【UNIX网络编程(二)】基本TCP套接字编程函数

基于TCP客户/服务器程序的套接字函数图如下: 执行网络I/O,一个进程必须做的第一件事就是调用socket函数,指定期望的通信协议类型. #include <sys/socket.h> int socket(int family, int type, int protocol);/*返回值:若成功则为非负描述符,若出错则为-1*/ socket函数成功时返回一个小的非负整数值,它与文件描述符类似,把它称为套接字描述符,简称sockfd.family参数指明协议族,被称为协议域.type参数指

【UNIX网络编程(四)】TCP套接字编程详细分析

引言: 套接字编程其实跟进程间通信有一定的相似性,可能也正因为此,stevens这位大神才会将套接字编程与进程间的通信都归为"网络编程",并分别写成了两本书<UNP1><UNP2>.TCP套接字编程是套接字编程中非常重要的一种,仔细分析,其实它的原理并不复杂.现在就以一个例子来详细分析TCP套接字编程. 一.示例要求: 本节中试着编写一个完成的TCP客户/服务器程序示例,并对它进行深入的探讨.该示例会用到绝大多数的基本函数,未用到但比较重要的函数会在后面的补充上

UNIX网络编程笔记(3)—基本TCP套接字编程

基本TCP套接字编程 主要介绍一个完整的TCP客户/服务器程序需要的基本套接字函数. 1.概述 在整个TCP客户/服务程序中,用到的函数就那么几个,其整体框图如下: 2.socket函数 为了执行网络I/O,一个进程必须要做的事情就是调用socket函数.其函数声明如下: #include <sys/socket.h> int socket(int family ,int type, int protocol); 其中: family:指定协议族 type:指定套接字类型 protocol:指

unix网络编程第四章----基于TCP套接字编程

为了执行网络I/O操作.进程必须做的第一件事情就是调用Socket函数.指定期待的通信协议 #include<sys/socket.h> int socket(int family,int type,int protocol); family表示协议族,比如AF_INET,type表示套接字类型, protocol一般设置为0 family: AF_INET ipv4协议 type: SOCK_STREAM 字节流套接字 SOCK_DGRAM 数据报套接字 SOCK_RAW 原始套接字 pro

Unix网络编程学习笔记之第4章 基于TCP套接字编程

1. socket函数 int socket(int family, int type,int protocol) 成返回一个套接字描述符.错误返回-1 其中family指定协议族,一般IPv4为AF_INET, IPv6为AF_INET6. 其中type指定套接字类型,字节流:SOCK_STREAM.   数据报:SOCK_DGRAM. 一般情况下通过family和type的组合都可以唯一确定一个套接字类型.所以一般我们就把protocol设为0就可以了. 有时在某些特殊情况下,family和

《网络编程》基本 UDP 套接字编程

在前面文章中介绍了<UDP 协议>和<套接字数据传输>.UDP 协议和 TCP 协议不同,它是一种面向无连接.不可靠的传输层协议.在基于 UDP 套接字编程中,数据传输可用函数 sendto 和 recvfrom.以下是基本 UDP 套接字编程过程: sendto 与 recvfrom 函数 这两个函数的功能类似于 write 和 read 函数,可用无连接的套接字编程.其定义如下: /* 函数功能:发送数据: * 返回值:若成功则返回已发送的字节数,若出错则返回-1: * 函数原

套接字编程相关函数(2:TCP套接字编程相关函数)

1. 基本TCP客户/服务器程序的套接字函数 2. socket函数 为了执行网络I/O,一个进程必须做的第一件事就是调用socket函数,指定期望的通信协议类型.其定义如下: #include <sys/socket.h> int socket(int family, int type, int protocol); // 返回:若成功则返回非负描述符,若失败则返回-1 其中:family参数指明协议族,它是图4-2中所示的某个常值.该参数也往往被称为协议域. type指明套接字类型,它是图