1 #include "csapp.h"//是书提供的头文件
2
3 int main(int argc, char **argv)
4 {
5 int clientfd, port;
6 char *host, buf[MAXLINE];
7 rio_t rio;
8
9 if (argc != 3) {
10 fprintf(stderr, "usage: %s \n", argv[0]);
11 exit(0);
12 }
13 host = argv[1];
14 port = atoi(argv[2]);
15
16 clientfd = Open_clientfd(host, port);//根据输入的ip和端口连接相应的服务器,如果连接成功将会返回一个int型的数值代表该通道,代码中就是clientfd
17 Rio_readinitb(&rio, clientfd);//做一个读取的准备工作,表示从连接的的通道clientfd中读取,并会将读到的内容放到rio里面去
18
19 while (Fgets(buf, MAXLINE, stdin) != NULL) {//从标准的输入中读取内容,存放到缓冲区,buf里面
20 Rio_writen(clientfd, buf, strlen(buf));//缓冲区内容buf通过clientfd通道传输给服务器
21 Rio_readlineb(&rio, buf, MAXLINE);//clinetfd传来的内容会放到rio里面,这句话就是将在rio里面读一行,并且放到buf里面去。
22 Fputs(buf, stdout);//将buf里面的内容放到stdout,标准的输出,一般情况下就是屏幕。
23 }
24 Close(clientfd);//关闭掉这个连接的通道
25 exit(0);
26 }
1 #include "csapp.h"
2
3 void echo(int connfd);
4
5 int main(int argc, char **argv)
6 {
7 int listenfd, connfd, port, clientlen;
8 struct sockaddr_in clientaddr;
9 struct hostent *hp;
10 char *haddrp;
11 if (argc != 2) {
12 fprintf(stderr, "usage: %s \n", argv[0]);
13 exit(0);
14 }
15 port = atoi(argv[1]);
16
17 listenfd = Open_listenfd(port);//创建一个监听,并且返回一个int类型作为监听标示符(descriptor)
18 while (1) {
19 clientlen = sizeof(clientaddr);
20 connfd = Accept(listenfd, (SA *)&clientaddr, &clientlen);//用监听创建一个"等待连接的状态",程序会阻塞在此处,直到有客户端来连接,连接会返回一个int类型的connfd,作为与这个客户端连接的标示符
21
22 /* Determine the domain name and IP address of the client */
23 hp = Gethostbyaddr((const char *)&clientaddr.sin_addr.s_addr,
24 sizeof(clientaddr.sin_addr.s_addr), AF_INET);//利用客户端的信息返回这个客户端的名字
25 haddrp = inet_ntoa(clientaddr.sin_addr);//将ip转为点分格式,用于显示
26 printf("server connected to %s (%s)\n", hp->h_name, haddrp);//打印连接的客户端的名字和ip
27
28 echo(connfd);//echo函数见下
29 Close(connfd);
30 }
31 exit(0);
32 }
1 #include "csapp.h"
2
3 void echo(int connfd)
4 {
5 size_t n;
6 char buf[MAXLINE];
7 rio_t rio;
8
9 Rio_readinitb(&rio, connfd);//准备从connfd的通道里面读内容,读的内容放到rio缓冲区
10 while((n = Rio_readlineb(&rio, buf, MAXLINE)) != 0) {//从rio中读一行放到buf中
11 printf("server received %d bytes\n", n);
12 Rio_writen(connfd, buf, n);//再把收的到内容写到连接通道中connfd
13 }
14 }
参考书中649页。
下面的代码是一个基于线程的并发服务器,基本的思想是,每有一个客户端连接上了服务器,那么就会产生一个新的线程,那么这个新的线程负责与连接的客户端处理事务。
1 #include "csapp.h"
2
3 void echo(int connfd);
4 void *thread(void *vargp);//处理与客户端通信的线程
5
6 int main(int argc, char **argv)
7 {
8 int listenfd, *connfdp, port;
9 socklen_t clientlen=sizeof(struct sockaddr_in);
10 struct sockaddr_in clientaddr;
11 pthread_t tid;
12
13 if (argc != 2) {
14 fprintf(stderr, "usage: %s \n", argv[0]);
15 exit(0);
16 }
17 port = atoi(argv[1]);
18
19 listenfd = Open_listenfd(port);
20 while (1) {
21 connfdp = Malloc(sizeof(int));
22 *connfdp = Accept(listenfd, (SA *) &clientaddr, &clientlen);//每当接到一个client的连接后
23 Pthread_create(&tid, NULL, thread, connfdp);//产生一个线程,将执行thread函数的内容。
24 }
25 }
26
27 /* Thread routine */
28 void *thread(void *vargp)
29 {
30 int connfd = *((int *)vargp);
31 Pthread_detach(pthread_self());//分离自己这个线程,这样的话,当执行完这个代码后,线程会自我销毁
32 Free(vargp);
33 echo(connfd);//echo方法请看上一节
34 Close(connfd);
35 return NULL;
36 }
#undef UNICODE
#define WIN32_LEAN_AND_MEAN
#include
#include
#include
#include
#include
#include
// Need to link with Ws2_32.lib
#pragma comment (lib, "Ws2_32.lib")
//#define DEFAULT_PORT "27015"
// #pragma comment (lib, "Mswsock.lib")
#define DEFAULT_BUFLEN 512
typedef struct _MyData {
SOCKET ClientSocket;
} MYDATA, *PMYDATA;
DWORD WINAPI ThreadProc(LPVOID lpParameter){
PMYDATA pData;
int iResult,iSendResult;
char recvbuf[DEFAULT_BUFLEN];
int recvbuflen = DEFAULT_BUFLEN;
pData = (PMYDATA)lpParameter;
SOCKET ClientSocket = pData->ClientSocket;
// Receive until the peer shuts down the connection
do {
iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
if (iResult > 0) {
recvbuf[iResult]='\0';//因为是从0开始的,所以如果这里是14,那么第14个为\0
printf("thread ID: %d Bytes received: %s %d\n", GetCurrentThreadId(),recvbuf,iResult);
// Echo the buffer back to the sender
iSendResult = send( ClientSocket, recvbuf, iResult, 0 );
if (iSendResult == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
printf("Bytes sent: %d\n", iSendResult);
}
else if (iResult == 0)
printf("Receive Completed...\n");
else {
printf("recv failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
} while (iResult > 0);
while(1){
Sleep(10000);
printf("thread ID: %d working \n", GetCurrentThreadId());
}
// shutdown the connection since we're done
iResult = shutdown(ClientSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
// cleanup
closesocket(ClientSocket);
}
int __cdecl main(int argc, char **argv)
{
PMYDATA pData;
WSADATA wsaData;
int iResult;
char hostName[255];
PHOSTENT hostinfo;
LPCSTR hostIp;
SOCKET ListenSocket = INVALID_SOCKET;
//SOCKET ClientSocket = INVALID_SOCKET;
DWORD dwThreadId;
HANDLE hThread;
struct addrinfo *result = NULL;
struct addrinfo hints;
int iSendResult;
char recvbuf[DEFAULT_BUFLEN];
int recvbuflen = DEFAULT_BUFLEN;
if (argc != 2) {
printf("usage: %s server-port\n", argv[0]);
return 1;
}
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
// Resolve the server address and port
iResult = getaddrinfo(NULL, argv[1], &hints, &result);
if ( iResult != 0 ) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
// Create a SOCKET for connecting to server
ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (ListenSocket == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
return 1;
}
// Setup the TCP listening socket
iResult = bind( ListenSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR) {
printf("bind failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
WSACleanup();
return 1;
}
freeaddrinfo(result);
iResult = listen(ListenSocket, SOMAXCONN);
if (iResult == SOCKET_ERROR) {
printf("listen failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
if( gethostname ( hostName, sizeof(hostName)) == 0) {
//如果成功地将本地主机名存放入由name参数指定的缓冲区中
if((hostinfo = gethostbyname(hostName)) != NULL) {
//这是获取主机名,如果获得主机名成功的话,将返回一个指针,指向hostinfo,hostinfo为PHOSTENT型的变量,下面即将用到这个结构体
hostIp = inet_ntoa (*(struct in_addr *)*hostinfo->h_addr_list);
}
}
// Accept a client socket
printf("Ip: %s Listening on Port %s \n",hostIp,argv[1]);
while(1){
SOCKET ClientSocket = accept(ListenSocket, NULL, NULL);
if (ClientSocket == INVALID_SOCKET) {
printf("accept failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
pData = (PMYDATA)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(MYDATA));
pData->ClientSocket=ClientSocket;
hThread = CreateThread(
NULL, // default security attributes
0, // use default stack size
ThreadProc, // thread function
pData, // argument to thread function
0, // use default creation flags
&dwThreadId); // returns the thread identifier
// No longer need server socket
//closesocket(ListenSocket);
}
WSACleanup();
system("pause");
return 0;
}
#define WIN32_LEAN_AND_MEAN
#include
#include
#include
#include
#include
// Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib
#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")
#define DEFAULT_BUFLEN 512
//#define DEFAULT_PORT "27015"
int __cdecl main(int argc, char **argv)
{
WSADATA wsaData;
SOCKET ConnectSocket = INVALID_SOCKET;
struct addrinfo *result = NULL,
*ptr = NULL,
hints;
char *sendbuf = "hello,world!";
char recvbuf[DEFAULT_BUFLEN];
int iResult;
int recvbuflen = DEFAULT_BUFLEN;
// Validate the parameters
if (argc != 3) {
printf("usage: %s server-name\n", argv[0]);
return 1;
}
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
ZeroMemory( &hints, sizeof(hints) );
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
// Resolve the server address and port
iResult = getaddrinfo(argv[1], argv[2], &hints, &result);
if ( iResult != 0 ) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
// Attempt to connect to an address until one succeeds
for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) {
// Create a SOCKET for connecting to server
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,
ptr->ai_protocol);
if (ConnectSocket == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
// Connect to server.
iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (iResult == SOCKET_ERROR) {
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
continue;
}
break;
}
freeaddrinfo(result);
if (ConnectSocket == INVALID_SOCKET) {
printf("Unable to connect to server!\n");
WSACleanup();
return 1;
}
// Send an initial buffer
iResult = send( ConnectSocket, sendbuf, (int)strlen(sendbuf), 0 );
if (iResult == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
printf("Bytes Sent: %ld\n", iResult);
// shutdown the connection since no more data will be sent
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
// Receive until the peer closes the connection
do {
iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
if ( iResult > 0 ){
recvbuf[iResult]='\0';
if (!(strcmp(sendbuf,recvbuf)))//比对接收字符和发送字符是否相同
{ //如果相同就打印
printf("Check completed,the Bytes from server is same as sent content\n");
printf("Bytes received from Server: %s %d\n", recvbuf,iResult);
}
}
else if ( iResult == 0 )
printf("Connection closed\n");
else
printf("recv failed with error: %d\n", WSAGetLastError());
} while( iResult > 0 );
// cleanup
closesocket(ConnectSocket);
WSACleanup();
return 0;
}