简单的-TCP服务端 - Linux socket编程入门(1)

 
#include<stdio.h>  
#include<stdlib.h>  
#include<string.h>  
#include<errno.h>  
#include<sys/types.h>  
#include<sys/socket.h>  
#include<netinet/in.h>  
#define DEFAULT_PORT 8000  
#define MAXLINE 4096  

int main(int argc, char **argv)
{
	int listenfd, connfd;         //socket套接字
	struct sockaddr_in servaddr;  //ip地址的结构体
	char buff[MAXLINE];           //用来存放接受数据和发送数据的BUF
	int response_max_length;     
	int result;                   //判断各个功能是否开启成功
	
	listenfd = socket(AF_INET, SOCK_STREAM, 0);
	if(listenfd == -1){  //如果返回值是-1,则我们认为函数执行错误。下同。
		printf("error:socket failed\n");
		return 0;
	}
	bzero(&servaddr, sizeof(servaddr)); //对内存进行初始化(填充0).
						//因为结构体除了有用的信息需要填写外,
						//其他元素内容可以用零填满。
	servaddr.sin_family = AF_INET; //填写必要的信息
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	servaddr.sin_port = htons(9997);    //htons,htonl这些函数的意思是host to online,
						//是在主机编程的时候不可或缺
						//的函数,因为这里涉及到数据是大端还是小端
	
	result = bind(listenfd,(struct sockaddr *) &servaddr, sizeof(servaddr));  
	if(result == -1){
		printf("error:bind failed\n");
		return 0;
	}
	
     result = listen(listenfd,10);
	if(result == -1){
		printf("error:listen failed\n");
		return 0;
	}
	
	for(;;)//死循环
	{
		connfd = accept(listenfd, (struct sockaddr *)NULL, NULL);
		if(connfd == -1){
			printf("error:accept failed\n");
			return 0;
		}
		
		for(;;)
		{
			response_max_length = recv(connfd, buff, MAXLINE, 0);
			buff[response_max_length] = '\0';
			printf("%s",buff);
			result = send(connfd, buff, 26,0);
			if(result == -1)
			{
				printf("error:send failed\n");
				return 0;
			}
		}
		close(connfd);
	}
	
	close(listenfd);
	return 0;
}

  

这是TCP服务端的代码。服务端功能比较简单,就是把客户端发送过来的内容打印在屏幕上,并传给客户端一模一样的内容,

服务端的流程大致如下:

  1.  socket(); 获得套接字

  2.  bind();     绑定端口以及ip

  3.  listen();    监听端口

  4.  accept();   接受client端的来访。TCP三次握手就是这里完成的。

  5.  recv();       接受client发送过来的信息

  6.  send();      向client发送信息

 

函数参数讲解:

  int socket(int domain , int type , int protocol);

    这个函数的参数是固定(在创建TCP连接的时候)的 (AF_INET, SOCK_STREAM, 0)。创建socket成功以后,返回一个int类型的值,表示socket。

   

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

    第一个参数是socket()返回的值。 第二个参数是代表IP地址的结构体 struct sockaddr。第三个参数是sizeof(struct sockaddr).

  

    int listen(int sockfd, int backlog);

    backlog 是未经过处理的连接请求队列可以容纳的最大数目。

  int accept(int sockfd, void *addr, int *addrlen);

    第二个参数是struct sockaddr类型的结构体指针。当连接成功以后,你可以通过这个指针获取client的IP地址。第三个参数同样是sizeof(struct sockaddr)。如果不需要知道client端的IP地址,第二个第三个参数可以写NULL

  int send(int sockfd, const void *msg, int len, int flags);

  int recv(int sockfd, void *buf, int len, unsigned int flags);

    第二个参数是字符数组,用来发送或者保存通讯内容的。第三个参数是字符串长度。strlen(buf)。 第四个参数flags一般写0,初学不用深究这里。

 

小体会:

1.这里许多函数参数都会有一个length,因为参数传入以后,函数体可以通过函数的大小,判断参数是哪一个结构体。(传递的参数都有强制转换,所以函数不知道原来的结构体是什么类型的。)

2.bzero();这个函数可以很安全地对某一大片地址进行填充0。

3.每一次重要的函数都是返回值为-1表示失败。

4.在进行网络编程的时候,要注意字节流的顺序,从主机发送到网络的数据,有些需要使用htons() htonl()这些函数。

posted @ 2015-09-18 01:50  chunyi  阅读(257)  评论(0编辑  收藏  举报