socket TCP

struct sockaddr_in include/linux/in.h

struct sockaddr_in {

  sa_family_t sin_family; //地址家族,“AF_XXX”,AF_INET,代表TCP/IP协议族

  __be16 sin_port; //存储端口号(使用网络字节顺序)

  struct in_addr sin_addr;//存储IP地址

  /* Pad to size of `struct sockaddr'. */

  unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) -

sizeof(unsigned short int) - sizeof(struct in_addr)];

};

include/linux/inet.h

#define INET_ADDRSTRLEN (16)

/* Address to accept any incoming messages. */

#define INADDR_ANY ((unsigned long int) 0x00000000)

sockaddr_in中的成员struct in_addr sin_addr表示32位的IP地址,但是我们通常用点分十进制字符串表示IP地址,以下函数可以在字符串表示和in_addr表示之间转换

字符串转in_addr的函数

#include <arpa/inet.h>

 int inet_aton(const char *cp, struct in_addr *inp);

 in_addr_t inet_addr(const char *cp);

in_addr转字符串函数

#include <arpa/inet.h>

 const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);

printf("received from [%s] at PORT [%d] \n", inet_ntop(AF_INET,&cliaddr.sin_addr, str, sizeof(str)), ntohs(cliaddr.sin_port));

/**
*TCP server
*从客户端读字符,然后将每个字符转换为大写并回送给客户端
*/

#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(void)
{
	struct sockaddr_in servaddr, cliaddr;
	socklen_t cliaddr_len;
	int listenfd, connfd;
	char buf[MAXLINE];
	char str[INET_ADDRSTRLEN];
	int i, n;
	
	/**
	*socket()打开一个网络通讯端口,成功则返回一个文件描述符
	*@AF_INET:IPv4 family参数指定为AF_INET
	*@SOCK_STREAM: TCP协议为SOCK_STREAM,UDP协议为SOCK_DGRAM
	*@0:表示IP
	*/
	listenfd = socket(AF_INET, SOCK_STREAM, 0);
	
	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);//宏INADDR_ANY表示本地的任意IP地址
	servaddr.sin_port = htons(SERV_PORT);
	
	/**
	*bind()绑定一个固定的网络地址和端口号,成功返回0,失败返回-1
	*listenfd这个用于网络通讯的文件描述符监听servaddr所描述的地址和端口
	*/
	bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
	
	/**
	*listen()声明listenfd处理监听状态,多个客户端发起连接,最多允许
	*20个客户端处于连接待状态,如果接收到更多的连接请求就忽略
	*/
	listen(listenfd, 20);
	
	printf("Accepting connections ...\n");
	
	//while死循环,每次循环处理一个客户端连接
	//cliaddr是传入传出参数,每次调用accept()之前应该重新赋值
	while (1) {
		cliaddr_len = sizeof(cliaddr);
		/**
		*三次握手后,服务器调用accept()接受连接
		*如果服务咕咕调用accept()时还没有客户端的连接请求
		*就阻塞等待直到有客户端连接
		*@cliaddr:传出参数,accept()返回时传出客户端的地址和端口号
		*如果cliaddr参数为NULL,表示不关心客户端的地址
		*/
		connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len);
		
		n = read(connfd, buf, MAXLINE);
		
		printf("received from [%s] at PORT [%d] \n", inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port));
                                                                                
	
		printf("%s \n", buf);							
		for (i = 0; i< n; i++)
			buf[i] = toupper(buf[i]);
		
		write(connfd, buf, n);
		close(connfd);
	}
}

/**
*client TCP
*从命令行参数中获得一个字符串发给服务器,然后接收服务器
*返回的字符串并打印
*/
#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\n", stderr);
		exit(1);
	}
	
	str = argv[1];
	/**
	*客户端不需要固定的端口号,因此不调用bind()
	*/
	sockfd = socket(AF_INET, SOCK_STREAM, 0);
	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	inet_pton(AF_INET, "10.50.25.10", &servaddr.sin_addr);
	servaddr.sin_port = htons(SERV_PORT);
	/**
	*客户端需要connect()连接服务器
	*@servaddr:是服务器的地址
	*/
	connect(sockfd, (struct sockaddr *)&servaddr,
						sizeof(servaddr));
						
	write(sockfd, str, strlen(str));
	
	n = read(sockfd, buf, MAXLINE);
	printf("Response from server:\n");
	write(STDOUT_FILENO, buf, n);
	
	printf("\n");
	close(sockfd);
	return 0;
}


你可能感兴趣的:(socket TCP)