Linux下C语言实现简单的套接字编程

一篇水水的文章,仅记录用。

0x01 服务端 tcp_server.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#define PORT 9999  /*侦听端口地址*/
#define BACKLOG 2  /*侦听队列长度*/

/*服务器对客户端的处理*/
void process_conn_server(int s)
{
	ssize_t size = 0;
	char buffer_recv[1024];  /*数据的缓冲区*/
	char buffer_send[1024];
	for(;;){  /*循环处理过程*/		
		size = read(s, buffer_recv, 1024);  /*从套接字中读取数据放到缓冲区buffer中*/
		if(size == 0){  /*没有数据*/
			return;
		}
		/*构建响应字符,为接收到客户端字节的数量*/
		sprintf(buffer_send, "%d bytes altogether:%s\n", size, buffer_recv);
		write(s, buffer_send, strlen(buffer_send)+1);/*发给客户端*/
	}
	
}

int main(int argc, char *argv[])
{
	int ss,sc;  /*ss为服务器的socket描述符,sc为客户端的socket描述符*/
	struct sockaddr_in server_addr;  /*服务器地址结构*/
	struct sockaddr_in client_addr;  /*客户端地址结构*/
	int err;  /*返回值*/
	pid_t pid;  /*分叉的进行ID*/

	/*建立一个流式套接字*/
	ss = socket(AF_INET, SOCK_STREAM, 0);
	if(ss < 0){  /*出错*/
		printf("socket error\n");
		return -1;
	}
	
	/*设置服务器地址*/
	bzero(&server_addr, sizeof(server_addr));  /*清零*/
	server_addr.sin_family = AF_INET;  /*协议族*/
	server_addr.sin_addr.s_addr = htonl(INADDR_ANY);  /*本地地址*/
	server_addr.sin_port = htons(PORT);  /*服务器端口*/
	
	/*绑定地址结构到套接字描述符*/
	err = bind(ss, (struct sockaddr*)&server_addr, sizeof(server_addr));
	if(err < 0){/*出错*/
		printf("bind error\n");
		return -1;	
	}
	
	/*设置侦听*/
	err = listen(ss, BACKLOG);
	if(err < 0){  /*出错*/
		printf("listen error\n");
		return -1;
	}
	
		/*主循环过程*/
	for(;;)	{
		socklen_t addrlen = sizeof(struct sockaddr);
		
		sc = accept(ss, (struct sockaddr*)&client_addr, &addrlen); 
		/*接收客户端连接*/
		if(sc < 0){  /*出错*/
			continue;  /*结束本次循环*/
		}	
		
		/*建立一个新的进程处理到来的连接*/
		pid = fork();  /*分叉进程*/
		if( pid == 0 ){  /*子进程中*/
			process_conn_server(sc);  /*处理连接*/
			close(ss);  /*在子进程中关闭服务器的侦听*/
		}else{
			close(sc);  /*在父进程中关闭客户端的连接*/
		}
	}
}

0x02 客户端 tcp_client.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <fcntl.h>
#define PORT 9999  /*侦听端口地址*/

/*客户端的处理过程*/
void process_conn_client(int s)
{
	ssize_t size = 0;
	char buffer[1024];  /*数据的缓冲区*/

	for(;;){  /*循环处理过程*/
		/*从标准输入中读取数据放到缓冲区buffer中*/
		size = read(0, buffer, 1024);
		if(size > 0){  /*读到数据*/
			write(s, buffer, size);  /*发送给服务器*/
			size = read(s, buffer, 1024);  /*从服务器读取数据*/
			write(1, buffer, size);  /*写到标准输出*/
		}
	}	
}

int main(int argc, char *argv[])
{
	int s;  /*s为socket描述符*/
	struct sockaddr_in server_addr;  /*服务器地址结构*/
	if(argc<2) {
		printf("Usage ./client server-addr\n");
		return 0;
	}
	s = socket(AF_INET, SOCK_STREAM, 0);  /*建立一个流式套接字 */
	if(s < 0){  /*出错*/
		printf("socket error\n");
		return -1;
	}	
	
	/*设置服务器地址*/
	bzero(&server_addr, sizeof(server_addr));  /*清零*/
	server_addr.sin_family = AF_INET;  /*协议族*/
	server_addr.sin_addr.s_addr = htonl(INADDR_ANY);  /*本地地址*/
	server_addr.sin_port = htons(PORT);  /*服务器端口*/
	
	/*将用户输入的字符串类型的IP地址转为整型*/
	inet_pton(AF_INET, argv[1], &server_addr.sin_addr);	
	/*连接服务器*/
	connect(s, (struct sockaddr*)&server_addr, sizeof(struct sockaddr));
	process_conn_client(s);  /*客户端处理过程*/
	close(s);  /*关闭连接*/
	return 0;
}

0x03 结果

编译一下:

gcc tcp_server.c -o server
gcc tcp_client.c -o client

运行结果: