您的位置:首页 > 理论基础 > 计算机网络

Linux网络编程--TCP的套接字通信学习笔记

2013-12-02 19:39 267 查看
TCP关于套接字socket通信涉及服务端和客户端两端的程序编写,如下:


A. TCP_server端;

1. 创建套接字socket

2.设置服务端ip并与socket进行绑定

3.设置服务端允许的最大连接数

3.服务器处于等待阻塞状态,等待来自客户端的连接

4.等待客户端的到来并连接成功,进行数据收发

5.关闭服务端

B. TCP_client

1.创建客户端套接字socket

2.设置需要访问的服务端ip项

3.连接服务端

4.连接成功进行数据收发

5.关闭客户端

inux网络编程是通过socket(套接字)实现的,socket是一种文件描述符。
Socket有三种类型:
流失套接字(SOCK_STREAM): 它可以提供可靠的、面向连接的通讯流;它使用TCP协议;TCP协议保证数据传输的正确性和顺序性。
数据套接字(SOCK_DGRAM):它定义了一种无连接的服务,数据通信相互独立的报文传输,是无序的,并且不保证可靠、无差错,他使用数据报文协议UDP。
原始套接字(SOCK_RAW):原始套接字使用IP协议,主要用于新网络协议的测试。
网络地址:
Socket网络程序设计中,struct sockaddr用于记录网络地址。
struct sockaddr
{
u_short sa_family; //协议簇,用于区分该网络地址属于那个协议,如IP
char sa_data[14]; //记录地址的数据
}
同理,也有用的多的另一种记录网络地址的数据结构体sockaddr_in:
Structsockaddr_in
{
short int sin_family; //同上,协议族
unsigned short int sin_port; //端口号
struct in_addr sin_addr; //协议特定地址
unsigned char sin_zero[8]; //无效位,填0
}
typedefstruct in_addr
{
union
{
struct
{
unsigned chars_b1,s_b2,s_b3,s_b4;
}S_un_b;
struct
{
unsigned short s_w1,s_w2;
}S_un_w;
unsignedlong s_addr; //32位bit记录IP
}S_un;
}IN_ADDR;
IP地址的转换:
IP地址通常有数字加点的形式(172.15.5.20)表示和用struct in_addr中使用32位的整型数据表示,这两种形式之间的转换有以下两个函数实现:
int inet_aton(const char *cp,structin_addr *inp);
char * inet_ntoa(struct in_addr in);
如上: a 表示字符串形式的ip n表示32位整型数据的IP
网络中的传输数据统一采用大端模式(big endian)传输。
字节序转换:
htons:把unsignedshort的主机序转换为网络序
htonl:把unsignedlong的主机序转换为网络序
ntohs:把unsignedshort的网络序转换为主机序
ntohl:把unsignedlong的网络序转换为主机序
IP与主机名:
在网络中标识一台主机可以用IP,也可以用主机名;例如本地主机可以用IP,也可以用主机名localhost来表示
下面这个函数就是提供主机名,获取IP:
struct hostent * gethostbyname(const char*hostname);
struct hostent
{
char * h_name; //主机的正式名字
char * h_aliases; //主机的别名
int h_addrtype; //主机的的类型
int h_length; //主机的地址长度
char **h_addr_list; //主机的IP地址列表
}
#defineh_addr h_addr_list[0]; //定义的主机的第一个IP地址
Socket编程函数:
socket--------------创建一个socket
int socket(int domain, int type, intprotocol)
domain指明所使用的协议族,通常为AF_INET,表示互联网协议族(TCP/IP协议族);type参数指定socket类型:SOCK_STREAM、SOCK_DGRAM、SOCK_RAW;protocol通常复制为0,该函数返回一个socket描述符,调用该函数将建立一个socket,失败返回-1,其实质分配一个socket数据结构。
bind ---------------绑定IP和端口号到socket
#include<sys/socket.h>
intbind(int socketfd, struct sockaddr *addr, socklen_t addrlen);
成功0 失败-1
socket通信时,该函数将socket与ip和端口号进行绑定
connect------------用于与服务器建立连接
listen-----设置服务器能处理的最大的连接要求
accept---用来等待来自客户端的socket连接请求
#include<sys/types.h> <sys/socket.h>
intaccept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
返回的套接字描述符,失败为-1
该函数将从连接请求队列中获得连接信息,创建新的套接字,斌返回该套接字的描述符,新的套接字用于服务器与客户端的连接通信,而旧的套接字仍处于监听状态15
send---发送数据
recv---接收数据
#include<string.h>
voidbzero((void *)s,int n); //将数据s的前n个字节置位0
下面分别是服务端和客户端的代码:
//TCP text,this is a TCP server
#include <stdio.h>
#include <errno.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <stdlib.h>

#define portnumber 3333

int main()
{
	struct sockaddr_in TCP_server,TCP_client;
	int socketfd,newfd;
	int buffer[1024],tbyte;
	if((socketfd = socket(AF_INET,SOCK_STREAM,0)) == -1)	
	{
		fprintf(stderr,"Get socket error! %s \n",strerror(errno));
		exit(1);
	}
	printf("set up the socket,and sockfd is %d\n",socketfd);
	
	/*write the server address*/
	bzero(&TCP_server,sizeof(struct sockaddr_in));
	TCP_server.sin_family = AF_INET;
	TCP_server.sin_port = htons(portnumber);
	TCP_server.sin_addr.s_addr = htonl(INADDR_ANY);
	/*bind ip to socket*/
	if(bind(socketfd,(struct sockaddr *)(&TCP_server),sizeof(struct sockaddr)) == -1)
	{
		printf("bind ip to socket error!\n");
		exit(1);
	}
	if(listen(socketfd,5) == -1)
	{
		printf("set the max connect error!\n");
		exit(1); 
	}
	while(1)
	{
		bzero(&TCP_client,sizeof(struct sockaddr_in));
		tbyte = sizeof(struct sockaddr_in);	
		if((newfd = accept(socketfd,(struct sockaddr*)(&TCP_client),&tbyte)) == -1)
		{
			fprintf(stderr,"TCP connect failed: %s\n",strerror(errno));
			exit(1);
		}
		printf("Get message from: %s",inet_ntoa(TCP_client.sin_addr));
		if((tbyte = read(newfd,buffer,1024)) == -1)
		{
			printf("Get message error!\n");
			exit(1);
		}
		buffer[tbyte] = '\0';
		printf("%s\n",buffer);
		memset(buffer,'\0',1024);
		close(newfd);
	}
	return 0;
}


//TCP connect,this is a TCP client 
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <netinet/in.h>
#include <string.h>
#include <errno.h>

#define portnumber 3333

int main(int argc,char *argv[])
{
	int socketfd;
	struct sockaddr_in TCP_client;
	struct hostent *host=NULL;
	char buf[1024];
	if(argc != 2)
	{
		printf("input error!\n");
		exit(1);
	}	
	if((host = gethostbyname(argv[1])) == NULL)
	{
		printf("Get name error!\n");
		exit(1);
	}
	
	if((socketfd = socket(AF_INET,SOCK_STREAM,0)) == -1)
	{
		fprintf(stderr,"Get socket error! : %s \n",strerror(errno));
		exit(1);
	}	
	
	/*complete TCP_client*/
	bzero(&TCP_client,sizeof(struct sockaddr_in));		//clear
	TCP_client.sin_family = AF_INET;
	TCP_client.sin_port = htons(portnumber);
	TCP_client.sin_addr = *((struct in_addr *)(host->h_addr));

	if(connect(socketfd,(struct sockaddr*)(&TCP_client),sizeof(struct sockaddr)) == -1)
	{
		fprintf(stderr,"connect error! : %s\n",strerror(errno));
		exit(1);
	}	 
	printf("connect successful!\nPlease input:\n");
	fgets(buf,1024,stdin);
	write(socketfd,buf,sizeof(buf));
	printf("write succed!\n");
	close(socketfd);
	exit(0);
	return 0;
}


注:学习资料参考国嵌教学视频
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: