Linux下C编写基本的多线程socket服务器
不想多说什么,会搜这些东西的都是想看代码的吧。
一开始不熟悉多线程的时候还在想怎么来控制一个线程的结束,后来发现原来有pthread_exit()函数可以直接在线程函数内部调用结束这个线程。
开始还想初始化一个pthread_t thread_fd[MAX]数组来存储开启的线程,然后用一个栈存储那些未分配的数组元素(thread_fd[index]=0)的index,跟缓存的思维相似,不过实在是想多了。
废话不多说,直接上代码,服务器和客户端都已经编译通过,正常运行,有基本的容错能力,不过也只是最基本的。
服务器:
/*
* multi_thread_socket_server.c
*
* Created on: Mar 14, 2014
* Author: nerohwang
*/
#include<stdlib.h>
#include<pthread.h>
#include<sys/socket.h>
#include<sys/types.h> //pthread_t , pthread_attr_t and so on.
#include<stdio.h>
#include<netinet/in.h> //structure sockaddr_in
#include<arpa/inet.h> //Func : htonl; htons; ntohl; ntohs
#include<assert.h> //Func :assert
#include<string.h> //Func :memset
#include<unistd.h> //Func :close,write,read
#define SOCK_PORT 9988
#define BUFFER_LENGTH 1024
#define MAX_CONN_LIMIT 512 //MAX connection limit static void Data_handle(void * sock_fd); //Only can be seen in the file int main()
{
int sockfd_server;
int sockfd;
int fd_temp;
struct sockaddr_in s_addr_in;
struct sockaddr_in s_addr_client;
int client_length; sockfd_server = socket(AF_INET,SOCK_STREAM,); //ipv4,TCP
assert(sockfd_server != -); //before bind(), set the attr of structure sockaddr.
memset(&s_addr_in,,sizeof(s_addr_in));
s_addr_in.sin_family = AF_INET;
s_addr_in.sin_addr.s_addr = htonl(INADDR_ANY); //trans addr from uint32_t host byte order to network byte order.
s_addr_in.sin_port = htons(SOCK_PORT); //trans port from uint16_t host byte order to network byte order.
fd_temp = bind(sockfd_server,(struct scokaddr *)(&s_addr_in),sizeof(s_addr_in));
if(fd_temp == -)
{
fprintf(stderr,"bind error!\n");
exit();
} fd_temp = listen(sockfd_server,MAX_CONN_LIMIT);
if(fd_temp == -)
{
fprintf(stderr,"listen error!\n");
exit();
} while()
{
printf("waiting for new connection...\n");
pthread_t thread_id;
client_length = sizeof(s_addr_client); //Block here. Until server accpets a new connection.
sockfd = accept(sockfd_server,(struct sockaddr_*)(&s_addr_client),(socklen_t *)(&client_length));
if(sockfd == -)
{
fprintf(stderr,"Accept error!\n");
continue; //ignore current socket ,continue while loop.
}
printf("A new connection occurs!\n");
if(pthread_create(&thread_id,NULL,(void *)(&Data_handle),(void *)(&sockfd)) == -)
{
fprintf(stderr,"pthread_create error!\n");
break; //break while loop
}
} //Clear
int ret = shutdown(sockfd_server,SHUT_WR); //shut down the all or part of a full-duplex connection.
assert(ret != -); printf("Server shuts down\n");
return ;
} static void Data_handle(void * sock_fd)
{
int fd = *((int *)sock_fd);
int i_recvBytes;
char data_recv[BUFFER_LENGTH];
const char * data_send = "Server has received your request!\n"; while()
{
printf("waiting for request...\n");
//Reset data.
memset(data_recv,,BUFFER_LENGTH); i_recvBytes = read(fd,data_recv,BUFFER_LENGTH);
if(i_recvBytes == )
{
printf("Maybe the client has closed\n");
break;
}
if(i_recvBytes == -)
{
fprintf(stderr,"read error!\n");
break;
}
if(strcmp(data_recv,"quit")==)
{
printf("Quit command!\n");
break; //Break the while loop.
}
printf("read from client : %s\n",data_recv);
if(write(fd,data_send,strlen(data_send)) == -)
{
break;
}
} //Clear
printf("terminating current client_connection...\n");
close(fd); //close a file descriptor.
pthread_exit(NULL); //terminate calling thread!
}
外加客户端:
/*
* socket_client.c
*
* Created on: Mar 15, 2014
* Author: nerohwang
*/
#include<stdlib.h>
#include<sys/socket.h>
#include<sys/types.h> //pthread_t , pthread_attr_t and so on.
#include<stdio.h>
#include<netinet/in.h> //structure sockaddr_in
#include<arpa/inet.h> //Func : htonl; htons; ntohl; ntohs
#include<assert.h> //Func :assert
#include<string.h> //Func :memset
#include<unistd.h> //Func :close,write,read
#define SOCK_PORT 9988
#define BUFFER_LENGTH 1024
int main()
{
int sockfd;
int tempfd;
struct sockaddr_in s_addr_in;
char data_send[BUFFER_LENGTH];
char data_recv[BUFFER_LENGTH];
memset(data_send,,BUFFER_LENGTH);
memset(data_recv,,BUFFER_LENGTH); sockfd = socket(AF_INET,SOCK_STREAM,); //ipv4,TCP
if(sockfd == -)
{
fprintf(stderr,"socket error!\n");
exit();
} //before func connect, set the attr of structure sockaddr.
memset(&s_addr_in,,sizeof(s_addr_in));
s_addr_in.sin_addr.s_addr = inet_addr("127.0.0.1"); //trans char * to in_addr_t
s_addr_in.sin_family = AF_INET;
s_addr_in.sin_port = htons(SOCK_PORT); tempfd = connect(sockfd,(struct sockaddr *)(&s_addr_in),sizeof(s_addr_in));
if(tempfd == -)
{
fprintf(stderr,"Connect error! \n");
exit();
} while()
{
printf("Please input something you wanna say(input \"quit\" to quit):\n");
gets(data_send);
//scanf("%[^\n]",data_send); //or you can also use this
tempfd = write(sockfd,data_send,BUFFER_LENGTH);
if(tempfd == -)
{
fprintf(stderr,"write error\n");
exit();
} if(strcmp(data_send,"quit") == ) //quit,write the quit request and shutdown client
{
break;
}
else
{
tempfd = read(sockfd,data_recv,BUFFER_LENGTH);
assert(tempfd != -);
printf("%s\n",data_recv);
memset(data_send,,BUFFER_LENGTH);
memset(data_recv,,BUFFER_LENGTH);
}
} int ret = shutdown(sockfd,SHUT_WR); //or you can use func close()--<unistd.h> to close the fd
assert(ret != -);
return ;
}
Linux下C编写基本的多线程socket服务器的更多相关文章
- linux 下shell 编写脚本
linux 下shell 编写脚本: 1.程序结构练习:编写一个脚本,给定一个正整数,计算出这个数所有位的数字之和. 例如:程序给定输入123,那么应该返回1+2+3=6. 2.程序结构练习:编写一个 ...
- linux下将文件上传到svn服务器
linux下将文件上传到svn服务器 摘自:https://blog.csdn.net/sky_yangge/article/details/41544773 2014年11月27日 16:47:57 ...
- 2.linux下Makefile编写规范
转自陈皓 (CSDN) 概述—— 什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我觉得要作一个好的和 profession ...
- Linux下高效编写Shell——shell特殊字符汇总
Linux下无论如何都是要用到shell命令的,在Shell的实际使用中,有编程经验的很容易上手,但稍微有难度的是shell里面的那些个符号,各种特殊的符号在我们编写Shell脚本的时候如果能够用的好 ...
- Linux下批处理文件编写
linux下的批处理文件,基本就是shell脚本文件. 一.最简单的脚本书写方法为: 1.新建一个文件,名字为test(自己定义的名字) touch test.sh 2.在里面编写脚本 程序必须以下面 ...
- Linux下的IPC-UNIX Domain Socket【转】
本文转载自:http://blog.csdn.net/guxch/article/details/7041052 一. 概述 UNIX Domain Socket是在socket架构上发展起来的用于同 ...
- Linux 下C++编写
今天搞了一天Linux下C++编程,还没有什么成效.好烦躁好心焦,想砸电脑的冲动.抽根烟理下思路一定要把它拿下!! ===搞了两天,真是搞到生无可恋,试了共享文件, 试了网络配置,各种博客就是各种行不 ...
- linux下常用FTP命令 1. 连接ftp服务器
1. 连接ftp服务器 格式:ftp [hostname| ip-address] a)在linux命令行下输入: ftp 192.168.1.1 b)服务器询问你用户名和密码,分别输入用户名和相应密 ...
- linux下常用FTP命令 1. 连接ftp服务器[转]
1. 连接ftp服务器 格式:ftp [hostname| ip-address]a)在linux命令行下输入: ftp 192.168.1.1 b)服务器询问你用户名和密码,分别输入用户名和相应密码 ...
随机推荐
- 关于js的语句类型运算符等
JavaScript的基本语句有以下几种: 1.for(判断条件){执行内容}: 2.if(条件){...}else{ ....}: 3.while(条件){....}:先判断条件再执行: do{.. ...
- 【BZOJ4652】【NOI2016】循环之美(莫比乌斯反演,杜教筛)
[BZOJ4652]循环之美(莫比乌斯反演,杜教筛) 题解 到底在求什么呢... 首先不管他\(K\)进制的问题啦,真是烦死啦 所以,相当于有一个分数\(\frac{i}{j}\) 因为值要不相等 所 ...
- [HAOI2010]软件安装
简单的tarjan+(本蒟蒻刚刚接触不久)恶心的树形DP 题面 题目描述 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为 ...
- python数据类型——列表和元组类型
列表类型(list) 定义一个列表类型很简单: l = ['a','b','c','d','e','f'] 变量l即为列表类型,可以用type方法查看: print(type(l)) 列表的增删改查 ...
- c#抽取pdf文档标题(1)
首先看看我的项目结构: 从上面的结果图中,我们可以看出,主要用了两个库:itextsharp.dll 和 pdfbox-1.8.9.dll,dll文件夹存放引用的库,handles文件夹存放抽取的处理 ...
- clientTop,scrollTop,兼容
在开发中常见的额兼容性问题: scrollTop问题: function scroll() { // 开始封装自己的scrollTop if(window.pageYOffset != null) { ...
- struct 2 基本知识
(最近在写一个ssh的项目,虽然看网上好像都说ssh已经过气了...之前虽然老师有上过这个课,我还做了一个PPT专门讲这个来着,但果然没有实践经验还是不容易理解.在参照一个项目写ssh时候,表示四脸蒙 ...
- PAT乙级-1042. 字符统计(20)
请编写程序,找出一段给定文字中出现最频繁的那个英文字母. 输入格式: 输入在一行中给出一个长度不超过1000的字符串.字符串由ASCII码表中任意可见字符及空格组成,至少包含1个英文字母,以回车结束( ...
- 设计模式——适配器模式(C++实现)
#include <iostream> #include <string> using namespace std; class STTarget { publ ...
- Linux源码-等待队列注释
等待队列 Linux中了等待队列的毒,代码中充斥着等待队列.不信你翻翻代码. 等待队列的唤醒我们这里叫激活.免得和线程唤醒混淆. 数据结构 头结点wait_queue_head_t的结构 struct ...