socket 套接字——代码实现(二)

 

Linux下多进程版本服务器:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
//用于服务接口
void serviceIO(int fd){
   //定义一个缓冲区
   char buf[1024];
   //开始读数据
   for(;;){
    ssize_t s=read(fd,buf,sizeof(buf)-1);
	//读成功
    if(s>0){
   buf[s]=0;
   printf("client# %s",buf);
  }
   //断开连接
   else if (s==0){
   printf("client quit!\n");
   break; 
  } 
   //读出错
   else {
   perror("read");
   break;
  } 
   //服务结束,关闭文件描述符(不关会有浪费)
   close(fd);
 }
// ./tcpServer 192.168.X.X XXX
//  端口号:众所周知,且不能随意改变
int main(int argc, char *argv[])
{
	if(argc != 3){
		printf("%s [server_ip] [server_port]\n", argv[0]);
		return 1;
	}
    //1、创建套接字,IPV4 协议 ,字节流
	int sock = socket(AF_INET, SOCK_STREAM, 0);
	//判断套接字创建是否成功
	if(sock < 0){
		perror("socket");
		return 2;
	}
    //本地填充
	struct sockaddr_in server;
	server.sin_family = AF_INET;
	//字符串风格IP转换成4字节整型风格
	server.sin_addr.s_addr = inet_addr(argv[1]);
	//atoi 字符串转整型
	//htons 主机序列转网络序列
	server.sin_port = htons(atoi(argv[2]));
     //2、绑定
	 if(bind(sock, (struct sockaddr*)&local, sizeof(local)) < 0){
		perror("bind");
		return 3;
	}
     //监听  (建立连接,返回一个sock文件描述符,只负责数据通信)
	if(listen(sock, 10) < 0){
		perror("listen");
		return 4;
	}
     //开始连接  accept (也会返回fd文件描述符,即新连接,用于服务)
	 for(;;){
	     struct sockaddr_in peer;
		 socklen_t len=sizeof(peer);
	     int fd=accept(sock,(struct sockadder)&peer,&len);
		 if(fd<0){
		    perror("accept");
			continue;
		 }
		 printf("get a new link....\n");
	 }
	 pid_t id =fork();
	 if(id <0){
	   perror("fork");
	 }
	 //子进程执行服务
	 else if(id==0){
	   //只进行服务,不监听
	   close(sock);	   
	   if(fork()>0){
	      //子进程退出
	      exit(0);
	   }
	   //子进程的子进程(孤儿进程被1号进程回收)
	   serviceIO( fd);
	   //服务结束就退出
	   exit(0);
	 }
	 //父进程继续获得新连接
	 else{
	   close(fd);
	   waitpid(id,NULL,0);
	 }
	 
	} 	 
	
}








 服务器还可以改为多线程版本:较简单

void serviceIO(int fd) {
	//定义一个缓冲区
	char buf[1024];
	//开始读数据
	for (;;) {
		ssize_t s = read(fd, buf, sizeof(buf) - 1);
		//读成功
		if (s > 0) {
			buf[s] = 0;
			printf("client# %s", buf);
		}
		//断开连接
		else if (s == 0) {
			printf("client quit!\n");
			break;
		}
		//读出错
		else {
			perror("read");
			break;
		}
		//服务结束,关闭文件描述符(不关会有浪费)
		close(fd);
}

	void * service(void * arg) {
		int fd = (int)arg;
		serviceIO(fd);
		close(fd);
		pthread_exit(0);
	}
	// ./tcpServer 192.168.X.X XXX
	//  端口号:众所周知,且不能随意改变
	int main(int argc, char *argv[])
	{
		if (argc != 3) {
			printf("%s [server_ip] [server_port]\n", argv[0]);
			return 1;
		}
		//1、创建套接字,IPV4 协议 ,字节流
		int sock = socket(AF_INET, SOCK_STREAM, 0);
		//判断套接字创建是否成功
		if (sock < 0) {
			perror("socket");
			return 2;
		}
		//本地填充
		struct sockaddr_in server;
		server.sin_family = AF_INET;
		//字符串风格IP转换成4字节整型风格
		server.sin_addr.s_addr = inet_addr(argv[1]);
		//atoi 字符串转整型
		//htons 主机序列转网络序列
		server.sin_port = htons(atoi(argv[2]));
		//2、绑定
		if (bind(sock, (struct sockaddr*)&local, sizeof(local)) < 0) {
			perror("bind");
			return 3;
		}
		//监听  (建立连接,返回一个sock文件描述符,只负责数据通信)
		if (listen(sock, 10) < 0) {
			perror("listen");
			return 4;
		}
		//开始连接  accept (也会返回fd文件描述符,即新连接,用于服务)
		for (;;) {
			struct sockaddr_in peer;
			socklen_t len = sizeof(peer);
			int fd = accept(sock, (struct sockadder)&peer, &len);
			if (fd<0) {
				perror("accept");
				continue;
			}
			printf("get a new link....\n");
			//创建线程(粒度细,消耗小)
			pthread_t tid;
			pthread_create(&tid, NULL, service, (void *)fd);

			//线程分离
			pthrread_detach(tid);

		}

 

Linux 下的客户端:

#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>

// ./tcpServer 192.168.X.X XXX
int main(int argc, char *argv[])
{
	if(argc != 3){
		printf("%s [server_ip] [server_port]\n", argv[0]);
		return 1;
	}
     //创建套接字
	int sock = socket(AF_INET, SOCK_STREAM, 0);
	if(sock < 0){
		perror("socket");
		return 2;
	}

	struct sockaddr_in server;
	server.sin_family = AF_INET;
	server.sin_addr.s_addr = inet_addr(argv[1]);
	server.sin_port = htons(atoi(argv[2]));
     //建立连接
	if(connect(sock, (struct sockaddr*)&server, sizeof(server)) < 0){
		perror("connect");
		return 3;
	}
     // 发送数据
	char buf[1024];
	for(;;){
		printf("Please Enter# ");
		scanf("%s", buf);
		write(sock, buf, strlen(buf));
	}
}


网络字节序列默认为大端;发送时主机转网络,接收时网络转主机。
struct sockaddr *:通用数据结构,类似void*
socket 
系统调用:操作系统提供的接口
两个文件描述符:
1、sock :获得新连接,只用于通信;
2、fd :新连接,用于服务;
本地环回IP:127.0.0.1  9999  (本地测试)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值