linux socket 多线程 linux多线程pthread
各位老铁们,大家好,今天由我来为大家分享linux socket 多线程,以及linux多线程pthread的相关问题知识,希望对大家有所帮助。如果可以帮助到大家,还望关注收藏下本站,您的支持是我们最大的动力,谢谢大家了哈,下面我们开始吧!
linux下的 socket编程问题!
第一个问题:
对,是那样的,用open打开文件,用read读取文件,在发送给对方,接收方接收到后,写入文件就可以了。不过在这个过程中最好别用字符串函数,除非你很熟悉。
第二个问题
首先你得去搞清楚什么是线程,什么是进程,fork出来的叫进程,pthread_create出来的才叫线程。服务器有很多种模型(多进程,多线程,select,epoll模型,这个我的blog上有,famdestiny.cublog.cn),不一定要用多进程。
给你写了个代码,自己先看看:
注意,在自己的目录下创建一个叫pserverb的文件,程序会把这个文件复制成test文件。你可以自己根据需要改改
server:
#include<stdio.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<errno.h>
#include<signal.h>
#include<sys/wait.h>
#include<sys/types.h>
#include<string.h>
#include<stdlib.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#define SERV_PORT 5358
#define MAX_CONN 10
#define BUF_LEN 1024
void str_echo(FILE*fp, int sockfd){
ssize_t nread;
int file_fd;
char buf[BUF_LEN]={0};
file_fd= open("test", O_WRONLY| O_TRUNC| O_CREAT, 0755);
while(1){
bzero(buf, BUF_LEN);
if((nread= read(sockfd, buf, BUF_LEN))==-1){
if(errno== EINTR){
continue;
}
else{
printf("readn error:%s\n", strerror(errno));
continue;
}
}
else if(nread== 0){
break;
}
else{
printf("%s\n", buf);
write(file_fd, buf, nread);
}
}
close(file_fd);
}
void sig_chld(int sig){
pid_t pid;
int state;
while((pid= waitpid(-1,&state, WNOHANG))> 0){
printf("child process%d exited.", pid);
}
return;
}
int main(int argc, char**argv)
{
int listenfd, connfd;
socklen_t cliaddrlen;
pid_t childpid;
struct sockaddr_in servaddr, cliaddr;
if((listenfd= socket(AF_INET, SOCK_STREAM, 0))==-1){
printf("socket error:%s\n", strerror(errno));
return 0;
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family= AF_INET;
servaddr.sin_addr.s_addr= htonl(INADDR_ANY);
servaddr.sin_port= htons(SERV_PORT);
if(bind(listenfd,(struct sockaddr*)&servaddr, sizeof(servaddr))==-1){
printf("bind error:%s\n", strerror(errno));
return 0;
}
if(listen(listenfd, MAX_CONN)==-1){
printf("listen error:%s\n", strerror(errno));
return 0;
}
signal(SIGCHLD, sig_chld);
while(1){
cliaddrlen= sizeof(cliaddr);
if((connfd= accept(listenfd,(struct sockaddr*)&cliaddr,&cliaddrlen))==-1){
if(errno== EINTR){
continue;
}
else{
printf("accept error:%s\n", strerror(errno));
continue;
}
}
if((childpid= fork())== 0){
close(listenfd);
str_echo(stdin, connfd);
exit(0);
}
else if(childpid> 0){
close(connfd);
}
else{
printf("fork error!\n");
continue;
}
}
}
client:
#include<stdio.h>
#include<unistd.h>
#include<errno.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<string.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdlib.h>
#define SERV_ADDR"127.0.0.1"
#define SERV_PORT 5358
#define BUF_LEN 1024
void str_cli(char*path, int sockfd)
{
char sendbuf[BUF_LEN]={0};
int fd, n;
if((fd= open("./pserverb", O_RDONLY))==-1){
printf("%s\n", strerror(errno));
exit(0);
}
while((n= read(fd, sendbuf, BUF_LEN))!= 0){
if(n< 0){
printf("%s\n", strerror(errno));
exit(0);
}
write(sockfd, sendbuf, n);
bzero(sendbuf, BUF_LEN);
}
close(fd);
return;
}
int main(int argc, char**argv)
{
int fd;
struct sockaddr_in servaddr;
fd= socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family= AF_INET;
servaddr.sin_addr.s_addr= inet_addr(SERV_ADDR);
servaddr.sin_port= htons(SERV_PORT);
if(connect(fd,(struct sockaddr*)&servaddr, sizeof(servaddr))==-1){
printf("connect error:%s\n", strerror(errno));
return 0;
}
str_cli(argv[1], fd);
return 0;
}
linux线程查询指令linux线程查询
怎么在linux系统下查看网卡状态信息?
方法一:
ethtooleth0采用此命令可以查看到网卡相关的技术指标。
(不一定所有网卡都支持此命令)
ethtool-ieth1加上-i参数查看网卡驱动。
可以尝试其它参数查看网卡相关技术参数。
方法二:
也可以通过dmesg|grepeth0等看到网卡名字(厂家)等信息。
通过查看/etc/sysconfig/network-scripts/ifcfg-eth0可以看到当前的网卡配置包括IP、网关地址等信息。
当然也可以通过ifconfig命令查看。
Linux是一套免费使用和自由传播的类Unix操作系统,是一个基于POSIX和UNIX的多用户、多任务、支持多线程和多CPU的操作系统。它能运行主要的UNIX工具软件、应用程序和网络协议。它支持32位和64位硬件。Linux继承了Unix以网络为核心的设计思想,是一个性能稳定的多用户网络操作系统。Linux操作系统诞生于1991年10月5日(这是第一次正式向外公布时间)。Linux存在着许多不同的Linux版本,但它们都使用了Linux内核。Linux可安装在各种计算机硬件设备中,比如手机、平板电脑、路由器、视频游戏控制台、台式计算机、大型机和超级计算机。严格来讲,Linux这个词本身只表示Linux内核,但实际上人们已经习惯了用Linux来形容整个基于Linux内核,并且使用GNU工程各种工具和数据库的操作系统。
linux查看活跃线程命令?
可以执行ps-ef进行查看
Linux多线程通信?
PIPE和FIFO用来实现进程间相互发送非常短小的、频率很高的消息;
这两种方式通常适用于两个进程间的通信。
共享内存用来实现进程间共享的、非常庞大的、读写操作频率很高的数据(配合信号量使用);
这种方式通常适用于多进程间通信。
其他考虑用socket。这里的“其他情况”,其实是今天主要会碰到的情况:
分布式开发。
在多进程、多线程、多模块所构成的今天最常见的分布式系统开发中,
socket是第一选择
。消息队列,现在建议不要使用了----因为找不到使用它们的理由。在实际中,我个人感觉,PIPE和FIFO可以偶尔使用下,共享内存都用的不多了。在效率上说,socket有包装数据和解包数据的过程,所以理论上来说socket是没有PIPE/FIFO快,不过现在计算机上真心不计较这么一点点速度损失的。你费劲纠结半天,不如我把socket设计好了,多插一块CPU来得更划算。另外,进程间通信的数据一般来说我们都会存入数据库的,这样万一某个进程突然死掉或者整个服务器死了,也不至于丢失重要数据、便于回滚到之前的状态。从这个角度考虑,适用共享内存的情况也更少了,所以socket使用得更多。再多说一点关于共享内存的:共享内存的效率确实高,但它的重点在“共享”二字上。如果的确有好些进程共享一大块数据(如果把每个进程都看做是类的对象的话,那么共享数据就是这个类的static数据成员),那么共享内存就是一个不二的选择了。但是在面向对象的今天,我们更多的时候是多线程+锁+线程间共享数据。因此共享进程在今天使用的也越来越少了。不过,在面对一些极度追求效率的需求时,共享内存就会成为唯一的选择,比如高频交易系统。除此以外,一般是不需要特意使用共享内存的。另外,
PIPE和共享内存是不能跨LAN的
(FIFO可以但FIFO只能用于两个进程通信)
。
如果你的分布式系统随着需求的增加而越来越大所以你想把不同的模块放在不同机器上而你之前开发的时候用了PIPE或者共享内存,那么你将不得不对代码进行大幅修改......同时,即使FIFO可以跨越LAN,其代码的可读性、易操作性和可移植性、适应性也远没有socket大。这也就是为什么一开始说socket是第一选择的原因。最后还有个信号简单说一下。
请注意,是信号,不是信号量。
信号量是用于同步线程间的对象的使用的(建议题主看我的答案,自认为比较通俗易懂:
semaphore和mutex的区别?-Linux-知乎
)。信号也是进程间通信的一种方式。比如在Linux系统下,一个进程正在执行时,你用键盘按Ctrl+c,就是给这个进程发送了一个信号。进程在捕捉到这个信号后会做相应的动作。虽然信号是可以自定义的,但这并不能改变信号的局限性:
不能跨LAN、信息量极其有限
。在现代的分布式系统中,通常都是
消息驱动:
即进程受到某个消息后,通过对消息的内容的分析然后做相应的动作。如果你把你的分布式系统设置成信号驱动的,这就表示你收到一个信号就要做一个动作而一个信号的本质其实就是一个数字而已。这样系统稍微大一点的话,系统将变得异常难以维护;甚至在很多时候,信号驱动是无法满足我们的需求的。因此现在我们一般也不用信号了。因此,请记住:
除非你有非常有说服力的理由,否则请用socket。
顺便给你推荐个基于socket的轻量级的消息库:ZeroMQ。
linux下,如何查看工控机的串口被哪个线程占用,能否使该线程强制释放串口?
在串口的驱动程序注册的open函数里加入这样一句话:printk("process%dhasopenttyn",current->pid);可以判断出来哪个进程打开了串口设备,或者是否有进程打开串口current->pid的值表示进程号!
Windows Socket和Linux Socket编程的区别
SOCKET在原理上应该是一样的,只是不同系统的运行机置有些不同。
Socket编程 windows到Linux代码移植遇到的问题
1、一些常用函数的移植
2、网络
socket相关程序从windows移植到linux下需要注意的
1)头文件
windows下winsock.h/winsock2.h
linux下sys/socket.h
错误处理:errno.h
其他常用函数的头文件可到命令行下用man指令查询。
2)初始化
windows下需要用WSAStartup
linux下不需要(很方便),直接可以使用
3)关闭socket
windows下closesocket(...)
linux下close(...)
4)类型
windows下SOCKET
在linux下为int类型
5)绑定地址的结构体
名称相同,都是struct sockaddr、struct sockaddr_in,这两者通常转换使用;
在Windows下面名称都是大写,而在Linux下为小写
常用:
Linux下:
sockaddr_in destAddr;
destAdd.sin_family=AF_INET;
destAddr.sin_port=htons(2030);
destAddr.sin_addr.s_addr=inet_addr("192.168.1.1");
Windows下:
SOCKADDR_IN destAddr;
destAddr.sin_addr.S_un.S_addr=inet_addr("192.168.1.1");
但结构体中成员的名称不同
Windows中结构体成员
struct sockaddr_in{
short sin_family;
u_short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
struct sockaddr{
u_short sa_family;
char sa_data[14];
};
struct in_addr{
union{
struct{ u_char s_b1,s_b2,s_b3,s_b4;} S_un_b;
struct{ u_short s_w1,s_w2;} S_un_w;
u_long S_addr;
} S_un;
};
下面的一些宏可以使windows下的程序移植到linux下(通过类型的重新定义,使代码具有linux和windows下的移植性)
[cpp] view plaincopy
#ifdef WIN32
typedef int socklen_t;
typedef int ssize_t;
#endif
#ifdef __LINUX__
typedef int SOCKET;
typedef unsigned char BYTE;
typedef unsigned long DWORD;
#define FALSE 0
#define SOCKET_ERROR(-1)
#endif
[cpp] view plaincopy
#ifdef WIN32
typedef int socklen_t;
typedef int ssize_t;
#endif
#ifdef __LINUX__
typedef int SOCKET;
typedef unsigned char BYTE;
typedef unsigned long DWORD;
#define FALSE 0
#define SOCKET_ERROR(-1)
#endif
6)获取错误码
windows下getlasterror()/WSAGetLastError()
linux下errno变量
7)设置非阻塞
windows下ioctlsocket()
linux下fcntl()<fcntl.h>
8)send函数最后一个参数
windows下一般设置为0
linux下最好设置为MSG_NOSIGNAL,如果不设置,在发送出错后有可能会导致程序退出。
9)毫秒级时间获取
windows下GetTickCount()
linux下gettimeofday()
10)数据类型的一些转化
通用的:
小端到大端(网络协议使用)的转换:htonl, htons
点分十进制IP和整数之间的相互转换:inet_addr()(该函数将点分十进制转为整数),inet_aton(),inet_ntoa(),inet_pton()(linux下独有该函数可以实现相互之间的转换)
使用到的头文件不相同,linux下用man命令查询。
另外注意:
linux下使用的套接字为伯克利套接字,因此在select()函数的使用上(第一个参数的设置)也有区别;
windows下为了与伯克利套接字匹配,第一个参数是无所谓,一般可设为0;
int maxfdp是一个整数值,是指集合中所有文件描述符的范围,即所有文件描述符的最大值加1,不能错!
3、多线程
多线程:(win)process.h--〉(linux)pthread.h
_beginthread--> pthread_create
_endthread--> pthread_exit